diff --git a/Cargo.lock b/Cargo.lock index d5dedb345c..95ebb46bd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -984,6 +984,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex-literal", + "kilt-support", "log", "pallet-aura", "pallet-authorship", @@ -3650,7 +3651,6 @@ dependencies = [ "hex-literal", "jsonrpsee", "log", - "node-common", "pallet-transaction-payment-rpc", "parity-scale-codec", "parking_lot 0.12.1", @@ -3660,7 +3660,6 @@ dependencies = [ "polkadot-primitives", "polkadot-service", "public-credentials", - "public-credentials-rpc", "runtime-common", "sc-basic-authorship", "sc-chain-spec", @@ -4630,11 +4629,9 @@ dependencies = [ "jsonrpsee", "log", "mashnet-node-runtime", - "node-common", "pallet-transaction-payment", "pallet-transaction-payment-rpc", "public-credentials", - "public-credentials-rpc", "runtime-common", "sc-basic-authorship", "sc-cli", @@ -5081,16 +5078,6 @@ dependencies = [ "libc", ] -[[package]] -name = "node-common" -version = "1.8.0" -dependencies = [ - "kilt-support", - "public-credentials", - "public-credentials-rpc", - "serde", -] - [[package]] name = "nodrop" version = "0.1.14" @@ -8014,22 +8001,11 @@ dependencies = [ "sp-std", ] -[[package]] -name = "public-credentials-rpc" -version = "1.8.0" -dependencies = [ - "jsonrpsee", - "parity-scale-codec", - "public-credentials-runtime-api", - "sp-api", - "sp-blockchain", - "sp-runtime", -] - [[package]] name = "public-credentials-runtime-api" version = "1.8.0" dependencies = [ + "kilt-support", "parity-scale-codec", "sp-api", "sp-std", diff --git a/Cargo.toml b/Cargo.toml index 16e6b28fb1..1a0328249c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,6 @@ members = [ "nodes/*", "pallets/*", "rpc/did/runtime-api", - "rpc/public-credentials", "rpc/public-credentials/runtime-api", "runtimes/*", "support", diff --git a/nodes/common/Cargo.toml b/nodes/common/Cargo.toml deleted file mode 100644 index c61e4dce5c..0000000000 --- a/nodes/common/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -authors = ["KILT "] -edition = "2021" -description = "Set of common utility types, functions, and traits that all node executables can tap into." -name = "node-common" -version = "1.8.0" - -[dependencies] -# Client dependencies -serde = {version = "1.0.137", features = ["derive"]} - -# Runtime dependencies -kilt-support = {path = "../../support"} -public-credentials = {path = "../../pallets/public-credentials"} -public-credentials-rpc = {path = "../../rpc/public-credentials"} - -[features] -default = [] diff --git a/nodes/common/src/public_credentials.rs b/nodes/common/src/public_credentials.rs deleted file mode 100644 index 13ad2d5c7b..0000000000 --- a/nodes/common/src/public_credentials.rs +++ /dev/null @@ -1,86 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2022 BOTLabs GmbH - -// The KILT Blockchain is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The KILT Blockchain is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org - -use serde::{Deserialize, Serialize}; - -use kilt_support::deposit::Deposit; -use public_credentials::CredentialEntry; - -use public_credentials_rpc::PublicCredentialsFilter; - -#[derive(Serialize, Deserialize)] -/// Thin wrapper around a runtime credential entry as specified in the -/// `public-credentials` pallet. This wrapper implements all the -/// (de-)serialization logic. -pub struct OuterCredentialEntry { - pub ctype_hash: CTypeHash, - pub attester: Attester, - pub revoked: bool, - pub block_number: BlockNumber, - #[serde(bound( - serialize = "AccountId: Serialize, Balance: std::fmt::Display", - deserialize = "AccountId: Deserialize<'de>, Balance: std::str::FromStr" - ))] - pub deposit: Deposit, - pub authorization_id: Option, -} - -impl - From> - for OuterCredentialEntry -{ - fn from(value: CredentialEntry) -> Self { - Self { - ctype_hash: value.ctype_hash, - attester: value.attester, - revoked: value.revoked, - block_number: value.block_number, - deposit: value.deposit, - authorization_id: value.authorization_id, - } - } -} - -/// Filter for public credentials retrieved for a provided subject as specified -/// in the RPC interface. -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub enum PublicCredentialFilter { - /// Filter credentials that match a specified Ctype. - CtypeHash(CTypeHash), - /// Filter credentials that have been issued by the specified attester. - Attester(Attester), -} - -impl - PublicCredentialsFilter> - for PublicCredentialFilter -where - CTypeHash: Eq, - Attester: Eq, -{ - fn should_include( - &self, - credential: &CredentialEntry, - ) -> bool { - match self { - Self::CtypeHash(ctype_hash) => ctype_hash == &credential.ctype_hash, - Self::Attester(attester) => attester == &credential.attester, - } - } -} diff --git a/nodes/parachain/Cargo.toml b/nodes/parachain/Cargo.toml index 260944ecaa..102899a126 100644 --- a/nodes/parachain/Cargo.toml +++ b/nodes/parachain/Cargo.toml @@ -17,10 +17,8 @@ substrate-build-script-utils = {git = "https://github.com/paritytech/substrate", # Internal dependencies clone-runtime = {path = "../../runtimes/clone"} -node-common = {path = "../common"} peregrine-runtime = {path = "../../runtimes/peregrine"} public-credentials = {path = "../../pallets/public-credentials"} -public-credentials-rpc = {path = "../../rpc/public-credentials"} runtime-common = {path = "../../runtimes/common"} spiritnet-runtime = {path = "../../runtimes/spiritnet"} diff --git a/nodes/parachain/src/rpc.rs b/nodes/parachain/src/rpc.rs index 8cc5ff4ca4..716e39469a 100644 --- a/nodes/parachain/src/rpc.rs +++ b/nodes/parachain/src/rpc.rs @@ -33,11 +33,7 @@ use sp_api::ProvideRuntimeApi; use sp_block_builder::BlockBuilder; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; -use public_credentials::CredentialEntry; -use runtime_common::{ - assets::AssetDid, authorization::AuthorizationId, AccountId, Balance, Block, BlockNumber, DidIdentifier, Hash, - Index, -}; +use runtime_common::{AccountId, Balance, Block, Index}; /// Full client dependencies. pub struct FullDeps { @@ -58,17 +54,10 @@ where C::Api: frame_rpc_system::AccountNonceApi, C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, C::Api: BlockBuilder, - C::Api: public_credentials_rpc::PublicCredentialsRuntimeApi< - Block, - AssetDid, - Hash, - CredentialEntry>, - >, P: TransactionPool + 'static, { use frame_rpc_system::{System, SystemApiServer}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; - use public_credentials_rpc::{PublicCredentialsApiServer, PublicCredentialsQuery}; let mut module = RpcModule::new(()); let FullDeps { @@ -78,40 +67,12 @@ where } = deps; module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; - module.merge(TransactionPayment::new(client.clone()).into_rpc())?; + module.merge(TransactionPayment::new(client).into_rpc())?; // Extend this RPC with a custom API by using the following syntax. // `YourRpcStruct` should have a reference to a client, which is needed // to call into the runtime. // // `module.merge(YourRpcStruct::new(ReferenceToClient).into_rpc())?;` - module.merge( - PublicCredentialsQuery::< - C, - Block, - // Input subject ID - String, - // Runtime subject ID - AssetDid, - // Input/output credential ID - Hash, - // Runtime credential ID - Hash, - // Input/output credential entry - node_common::OuterCredentialEntry< - Hash, - DidIdentifier, - BlockNumber, - AccountId, - Balance, - AuthorizationId, - >, - // Runtime credential entry - CredentialEntry>, - // Credential filter - node_common::PublicCredentialFilter, - >::new(client) - .into_rpc(), - )?; Ok(module) } diff --git a/nodes/parachain/src/service.rs b/nodes/parachain/src/service.rs index a103b7a40a..6ff06b1e17 100644 --- a/nodes/parachain/src/service.rs +++ b/nodes/parachain/src/service.rs @@ -42,11 +42,7 @@ use sp_runtime::traits::BlakeTwo256; use std::{sync::Arc, time::Duration}; use substrate_prometheus_endpoint::Registry; -use public_credentials::CredentialEntry; -use runtime_common::{ - assets::AssetDid, authorization::AuthorizationId, AccountId, AuthorityId, Balance, BlockNumber, DidIdentifier, - Index, -}; +use runtime_common::{AccountId, AuthorityId, Balance, BlockNumber, Index}; type Header = sp_runtime::generic::Header; pub type Block = sp_runtime::generic::Block; @@ -255,13 +251,7 @@ where + sp_block_builder::BlockBuilder + cumulus_primitives_core::CollectCollationInfo + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi - + frame_rpc_system::AccountNonceApi - + public_credentials_rpc::PublicCredentialsRuntimeApi< - Block, - AssetDid, - Hash, - CredentialEntry>, - >, + + frame_rpc_system::AccountNonceApi, sc_client_api::StateBackendFor, Block>: sp_api::StateBackend, Executor: sc_executor::NativeExecutionDispatch + 'static, RB: FnOnce( @@ -499,13 +489,7 @@ where + frame_rpc_system::AccountNonceApi + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + sp_consensus_aura::AuraApi - + cumulus_primitives_core::CollectCollationInfo - + public_credentials_rpc::PublicCredentialsRuntimeApi< - Block, - AssetDid, - Hash, - CredentialEntry>, - >, + + cumulus_primitives_core::CollectCollationInfo, sc_client_api::StateBackendFor, Block>: sp_api::StateBackend, { start_node_impl::( diff --git a/nodes/standalone/Cargo.toml b/nodes/standalone/Cargo.toml index 709af490d8..6b3880b903 100644 --- a/nodes/standalone/Cargo.toml +++ b/nodes/standalone/Cargo.toml @@ -16,9 +16,7 @@ substrate-build-script-utils = {git = "https://github.com/paritytech/substrate", # Internal dependencies mashnet-node-runtime = {path = "../../runtimes/standalone"} -node-common = {path = "../common"} public-credentials = {path = "../../pallets/public-credentials"} -public-credentials-rpc = {path = "../../rpc/public-credentials"} runtime-common = {path = "../../runtimes/common"} # External dependencies diff --git a/nodes/standalone/src/rpc.rs b/nodes/standalone/src/rpc.rs index a4174c8bc7..d01cc66db6 100644 --- a/nodes/standalone/src/rpc.rs +++ b/nodes/standalone/src/rpc.rs @@ -33,11 +33,7 @@ use sp_api::ProvideRuntimeApi; use sp_block_builder::BlockBuilder; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; -use public_credentials::CredentialEntry; -use runtime_common::{ - assets::AssetDid, authorization::AuthorizationId, AccountId, Balance, Block, BlockNumber, DidIdentifier, Hash, - Index, -}; +use runtime_common::{AccountId, Balance, Block, Index}; /// Full client dependencies. pub struct FullDeps { @@ -58,17 +54,10 @@ where C::Api: frame_rpc_system::AccountNonceApi, C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, C::Api: BlockBuilder, - C::Api: public_credentials_rpc::PublicCredentialsRuntimeApi< - Block, - AssetDid, - Hash, - CredentialEntry>, - >, P: TransactionPool + 'static, { use frame_rpc_system::{System, SystemApiServer}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; - use public_credentials_rpc::{PublicCredentialsApiServer, PublicCredentialsQuery}; let mut module = RpcModule::new(()); let FullDeps { @@ -78,41 +67,13 @@ where } = deps; module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; - module.merge(TransactionPayment::new(client.clone()).into_rpc())?; + module.merge(TransactionPayment::new(client).into_rpc())?; // Extend this RPC with a custom API by using the following syntax. // `YourRpcStruct` should have a reference to a client, which is needed // to call into the runtime. // // `module.merge(YourRpcStruct::new(ReferenceToClient).into_rpc())?;` - module.merge( - PublicCredentialsQuery::< - C, - Block, - // Input subject ID - String, - // Runtime subject ID - AssetDid, - // Input/output credential ID - Hash, - // Runtime credential ID - Hash, - // Input/output credential entry - node_common::OuterCredentialEntry< - Hash, - DidIdentifier, - BlockNumber, - AccountId, - Balance, - AuthorizationId, - >, - // Runtime credential entry - CredentialEntry>, - // Credential filter - node_common::PublicCredentialFilter, - >::new(client) - .into_rpc(), - )?; Ok(module) } diff --git a/rpc/public-credentials/Cargo.toml b/rpc/public-credentials/Cargo.toml deleted file mode 100644 index 5a4e7f8128..0000000000 --- a/rpc/public-credentials/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "public-credentials-rpc" -version = "1.8.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -# Client dependencies -jsonrpsee = { version = "0.15.1", features = ["server", "macros"] } - -# External runtime dependencies -codec = { package = "parity-scale-codec", version = "3.1.5" } - -# Substrate runtime dependencies -sp-api = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.29"} -sp-blockchain = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.29"} -sp-runtime = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.29"} - -# Internal runtime dependencies -public-credentials-runtime-api = {version = "1.8.0", path = "./runtime-api"} - -[features] -default = ["std"] -std = [ - "codec/std", - "sp-api/std", - "sp-runtime/std", - "public-credentials-runtime-api/std", -] diff --git a/rpc/public-credentials/runtime-api/Cargo.toml b/rpc/public-credentials/runtime-api/Cargo.toml index 6e5042b7ff..0a3c995f31 100644 --- a/rpc/public-credentials/runtime-api/Cargo.toml +++ b/rpc/public-credentials/runtime-api/Cargo.toml @@ -14,10 +14,14 @@ codec = {package = "parity-scale-codec", version = "3.1.5", default-features = f sp-api = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", default-features = false} sp-std = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", default-features = false} +# Internal dependencies +kilt-support = {path = "../../../support/", default-features = false} + [features] default = ["std"] std = [ "codec/std", + "kilt-support/std", "sp-api/std", "sp-std/std", ] diff --git a/rpc/public-credentials/runtime-api/src/lib.rs b/rpc/public-credentials/runtime-api/src/lib.rs index 6b0b0ba5a8..6e4f8d6a08 100644 --- a/rpc/public-credentials/runtime-api/src/lib.rs +++ b/rpc/public-credentials/runtime-api/src/lib.rs @@ -22,14 +22,22 @@ use codec::Codec; use sp_std::vec::Vec; +use kilt_support::traits::ItemFilter; + sp_api::decl_runtime_apis! { /// The API to query public credentials for a subject. - pub trait PublicCredentialsApi where + pub trait PublicCredentials where SubjectId: Codec, CredentialId: Codec, - CredentialEntry: Codec + CredentialEntry: Codec, + Filter: Codec + ItemFilter, + Error: Codec, { + /// Return the public credential with the specified ID, if found. fn get_credential(credential_id: CredentialId) -> Option; - fn get_credentials(subject: SubjectId) -> Vec<(CredentialId, CredentialEntry)>; + /// Return all the public credentials linked to the specified subject. + /// An optional filter can be passed to be applied to the result before being returned to the client. + /// It returns an error if the provided specified subject ID is not valid. + fn get_credentials(subject: SubjectId, filter: Option) -> Result, Error>; } } diff --git a/rpc/public-credentials/src/lib.rs b/rpc/public-credentials/src/lib.rs deleted file mode 100644 index a5fede10c0..0000000000 --- a/rpc/public-credentials/src/lib.rs +++ /dev/null @@ -1,231 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2022 BOTLabs GmbH - -// The KILT Blockchain is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The KILT Blockchain is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org - -pub use public_credentials_runtime_api::PublicCredentialsApi as PublicCredentialsRuntimeApi; - -use std::sync::Arc; - -use codec::Codec; -use jsonrpsee::{ - core::{async_trait, RpcResult}, - proc_macros::rpc, - types::error::{CallError, ErrorObject}, -}; - -use sp_api::ProvideRuntimeApi; -use sp_blockchain::HeaderBackend; -use sp_runtime::{generic::BlockId, traits::Block as BlockT}; - -/// Filter that can be used after the credentials for a given subject have been -/// retrieved from the blockchain state. -pub trait PublicCredentialsFilter { - fn should_include(&self, credential: &Credential) -> bool; -} - -#[rpc(client, server)] -pub trait PublicCredentialsApi { - /// Return a credential that matches the provided credential ID, if found. - #[method(name = "credentials_getCredential")] - fn get_credential( - &self, - credential_id: OuterCredentialId, - at: Option, - ) -> RpcResult>; - - /// Return all the credentials issued to the provided subject, optionally - /// filtering with the provided logic. The result is a vector of (credential - /// identifier, credential entry). - #[method(name = "credentials_getCredentials")] - fn get_credentials( - &self, - subject: OuterSubjectId, - filter: Option, - at: Option, - ) -> RpcResult>; -} - -pub struct PublicCredentialsQuery< - Client, - Block, - OuterSubjectId, - SubjectId, - OuterCredentialId, - CredentialId, - OuterCredentialEntry, - CredentialEntry, - CredentialFilter, -> { - client: Arc, - #[allow(clippy::type_complexity)] - _marker: std::marker::PhantomData<( - Block, - OuterSubjectId, - SubjectId, - OuterCredentialId, - CredentialId, - OuterCredentialEntry, - CredentialEntry, - CredentialFilter, - )>, -} - -impl< - Client, - Block, - OuterSubjectId, - SubjectId, - OuterCredentialId, - CredentialId, - OuterCredentialEntry, - CredentialEntry, - CredentialFilter, - > - PublicCredentialsQuery< - Client, - Block, - OuterSubjectId, - SubjectId, - OuterCredentialId, - CredentialId, - OuterCredentialEntry, - CredentialEntry, - CredentialFilter, - > -{ - pub fn new(client: Arc) -> Self { - Self { - client, - _marker: Default::default(), - } - } -} - -#[repr(i32)] -pub enum Error { - Runtime = 1, - Conversion, - Internal = i32::MAX, -} - -#[async_trait] -impl< - Client, - Block, - OuterSubjectId, - SubjectId, - OuterCredentialId, - CredentialId, - OuterCredentialEntry, - CredentialEntry, - CredentialFilter, - > - PublicCredentialsApiServer< - ::Hash, - OuterSubjectId, - OuterCredentialId, - OuterCredentialEntry, - CredentialFilter, - > - for PublicCredentialsQuery< - Client, - Block, - OuterSubjectId, - SubjectId, - OuterCredentialId, - CredentialId, - OuterCredentialEntry, - CredentialEntry, - CredentialFilter, - > where - Block: BlockT, - Client: Send + Sync + 'static + ProvideRuntimeApi + HeaderBackend, - Client::Api: PublicCredentialsRuntimeApi, - OuterSubjectId: Send + Sync + 'static, - SubjectId: Codec + Send + Sync + 'static + TryFrom, - OuterCredentialId: Send + Sync + 'static, - CredentialId: Codec + Send + Sync + 'static + TryFrom + Into, - CredentialEntry: Codec + Send + Sync + 'static, - OuterCredentialEntry: Send + Sync + 'static + From, - CredentialFilter: Send + Sync + 'static + PublicCredentialsFilter, -{ - fn get_credential( - &self, - credential_id: OuterCredentialId, - at: Option<::Hash>, - ) -> RpcResult> { - let api = self.client.runtime_api(); - let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash)); - - let into_credential_id: CredentialId = credential_id.try_into().map_err(|_| { - CallError::Custom(ErrorObject::owned( - Error::Conversion as i32, - "Unable to convert input to a valid credential ID.", - Option::::None, - )) - })?; - - let credential = api.get_credential(&at, into_credential_id).map_err(|_| { - CallError::Custom(ErrorObject::owned( - Error::Runtime as i32, - "Unable to get credential.", - Option::::None, - )) - })?; - Ok(credential.map(OuterCredentialEntry::from)) - } - - fn get_credentials( - &self, - subject: OuterSubjectId, - filter: Option, - at: Option<::Hash>, - ) -> RpcResult> { - let api = self.client.runtime_api(); - let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash)); - - let into_subject: SubjectId = subject.try_into().map_err(|_| { - CallError::Custom(ErrorObject::owned( - Error::Conversion as i32, - "Unable to convert input to a valid subject ID", - Option::::None, - )) - })?; - - let credentials = api.get_credentials(&at, into_subject).map_err(|_| { - CallError::Custom(ErrorObject::owned( - Error::Runtime as i32, - "Unable to get credentials", - Option::::None, - )) - })?; - - let filtered_credentials = if let Some(filter) = filter { - credentials - .into_iter() - .filter(|(_, credential_entry)| filter.should_include(credential_entry)) - .collect() - } else { - credentials - }; - - Ok(filtered_credentials - .into_iter() - .map(|(id, entry)| (id.into(), entry.into())) - .collect()) - } -} diff --git a/runtimes/clone/Cargo.toml b/runtimes/clone/Cargo.toml index 55ea14f3ff..15f1903813 100644 --- a/runtimes/clone/Cargo.toml +++ b/runtimes/clone/Cargo.toml @@ -26,6 +26,7 @@ public-credentials-runtime-api = {path = "../../rpc/public-credentials/runtime-a # KILT pallets & primitives pallet-did-lookup = {path = "../../pallets/pallet-did-lookup", default-features = false} public-credentials = {path = "../../pallets/public-credentials", default-features = false} +kilt-support = {default-features = false, path = "../../support"} runtime-common = {path = "../../runtimes/common", default-features = false} # Substrate dependencies @@ -96,6 +97,7 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system-benchmarking", "frame-system/runtime-benchmarks", + "kilt-support/runtime-benchmarks", "hex-literal", "pallet-balances/runtime-benchmarks", "pallet-did-lookup/runtime-benchmarks", @@ -123,6 +125,7 @@ std = [ "frame-system-rpc-runtime-api/std", "frame-system/std", "frame-try-runtime/std", + "kilt-support/std", "log/std", "pallet-aura/std", "pallet-authorship/std", diff --git a/runtimes/clone/src/lib.rs b/runtimes/clone/src/lib.rs index 9fbf43faae..8b11d33c87 100644 --- a/runtimes/clone/src/lib.rs +++ b/runtimes/clone/src/lib.rs @@ -47,9 +47,10 @@ use xcm::opaque::latest::BodyId; use xcm_executor::XcmExecutor; use runtime_common::{ - assets::AssetDid, + assets::PublicCredentialsFilter, authorization::AuthorizationId, constants::{self, HOURS, MILLI_KILT}, + errors::PublicCredentialsApiError, fees::{ToAuthor, WeightToFee}, AccountId, AuthorityId, Balance, BlockHashCount, BlockLength, BlockNumber, BlockWeights, DidIdentifier, FeeSplit, Hash, Header, Index, Signature, SlowAdjustingFeeUpdate, @@ -578,13 +579,13 @@ impl_runtime_apis! { } } - impl public_credentials_runtime_api::PublicCredentialsApi>> for Runtime { + impl public_credentials_runtime_api::PublicCredentials, Hash, public_credentials::CredentialEntry>, PublicCredentialsFilter, PublicCredentialsApiError> for Runtime { fn get_credential(_credential_id: Hash) -> Option>> { None } - fn get_credentials(_subject: AssetDid) -> Vec<(Hash, public_credentials::CredentialEntry>)> { - vec![] + fn get_credentials(_subject: Vec, _filter: Option>) -> Result>)>, PublicCredentialsApiError> { + Ok(vec![]) } } diff --git a/runtimes/common/Cargo.toml b/runtimes/common/Cargo.toml index 84286d8cc4..beca2abff3 100644 --- a/runtimes/common/Cargo.toml +++ b/runtimes/common/Cargo.toml @@ -16,7 +16,7 @@ serde = {version = "1.0.144", optional = true, features = ["derive"]} smallvec = "1.8.0" attestation = {default-features = false, path = "../../pallets/attestation"} -kilt-support = { default-features = false, optional = true, path = "../../support" } +kilt-support = {default-features = false, path = "../../support"} parachain-staking = {default-features = false, path = "../../pallets/parachain-staking"} public-credentials = {default-features = false, path = "../../pallets/public-credentials"} diff --git a/runtimes/common/src/assets.rs b/runtimes/common/src/assets.rs index 4c2be05a69..3dd2c6b6fe 100644 --- a/runtimes/common/src/assets.rs +++ b/runtimes/common/src/assets.rs @@ -23,6 +23,11 @@ use sp_std::vec::Vec; use kilt_asset_dids::AssetDid as AssetIdentifier; +use kilt_support::traits::ItemFilter; +use public_credentials::CredentialEntry; + +use crate::{authorization::AuthorizationId, AccountId, Balance, BlockNumber, Hash}; + #[cfg(feature = "runtime-benchmarks")] pub use benchmarks::*; @@ -58,6 +63,30 @@ impl TryFrom for AssetDid { } } +/// Filter for public credentials retrieved for a provided subject as specified +/// in the runtime API interface. +#[derive(Encode, Decode, TypeInfo)] +pub enum PublicCredentialsFilter { + /// Filter credentials that match a specified Ctype. + CtypeHash(CTypeHash), + /// Filter credentials that have been issued by the specified attester. + Attester(Attester), +} + +impl ItemFilter>> + for PublicCredentialsFilter +{ + fn should_include( + &self, + credential: &CredentialEntry>, + ) -> bool { + match self { + Self::CtypeHash(ctype_hash) => ctype_hash == &credential.ctype_hash, + Self::Attester(attester) => attester == &credential.attester, + } + } +} + #[cfg(feature = "runtime-benchmarks")] mod benchmarks { use super::*; diff --git a/runtimes/common/src/authorization.rs b/runtimes/common/src/authorization.rs index 1e7da8bc1a..f7d7144aba 100644 --- a/runtimes/common/src/authorization.rs +++ b/runtimes/common/src/authorization.rs @@ -24,7 +24,6 @@ use attestation::AttestationAccessControl; use public_credentials::PublicCredentialsAccessControl; #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] -#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub enum AuthorizationId { Delegation(DelegationId), } diff --git a/nodes/common/src/lib.rs b/runtimes/common/src/errors.rs similarity index 84% rename from nodes/common/src/lib.rs rename to runtimes/common/src/errors.rs index 5ace9a26fa..bcde83aacf 100644 --- a/nodes/common/src/lib.rs +++ b/runtimes/common/src/errors.rs @@ -16,6 +16,10 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -pub mod public_credentials; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; -pub use crate::public_credentials::*; +#[derive(Encode, Decode, TypeInfo)] +pub enum PublicCredentialsApiError { + InvalidSubjectId, +} diff --git a/runtimes/common/src/lib.rs b/runtimes/common/src/lib.rs index 3e9c999644..c30bad31d4 100644 --- a/runtimes/common/src/lib.rs +++ b/runtimes/common/src/lib.rs @@ -45,6 +45,7 @@ use sp_std::marker::PhantomData; pub mod assets; pub mod authorization; pub mod constants; +pub mod errors; pub mod fees; pub mod migrations; pub mod pallet_id; diff --git a/runtimes/peregrine/src/lib.rs b/runtimes/peregrine/src/lib.rs index 1e5050a3d0..0804e42808 100644 --- a/runtimes/peregrine/src/lib.rs +++ b/runtimes/peregrine/src/lib.rs @@ -47,14 +47,16 @@ use xcm_executor::XcmExecutor; use delegation::DelegationAc; use did_rpc_runtime_api::runtime_decl_for_DidApi::DidApiV2; +use kilt_support::traits::ItemFilter; use pallet_did_lookup::{linkable_account::LinkableAccountId, migrations::EthereumMigration}; pub use parachain_staking::InflationInfo; pub use public_credentials; use runtime_common::{ - assets::AssetDid, + assets::{AssetDid, PublicCredentialsFilter}, authorization::{AuthorizationId, PalletAuthorize}, constants::{self, EXISTENTIAL_DEPOSIT, KILT}, + errors::PublicCredentialsApiError, fees::{ToAuthor, WeightToFee}, migrations, pallet_id, AccountId, AuthorityId, Balance, BlockHashCount, BlockLength, BlockNumber, BlockWeights, DidIdentifier, FeeSplit, Hash, Header, Index, Signature, SlowAdjustingFeeUpdate, @@ -1289,14 +1291,20 @@ impl_runtime_apis! { } } - impl public_credentials_runtime_api::PublicCredentialsApi::DelegationNodeId>>> for Runtime { + impl public_credentials_runtime_api::PublicCredentials, Hash, public_credentials::CredentialEntry::DelegationNodeId>>, PublicCredentialsFilter, PublicCredentialsApiError> for Runtime { fn get_credential(credential_id: Hash) -> Option::DelegationNodeId>>> { let subject = public_credentials::CredentialSubjects::::get(&credential_id)?; public_credentials::Credentials::::get(&subject, &credential_id) } - fn get_credentials(subject: ::SubjectId) -> Vec<(Hash, public_credentials::CredentialEntry::DelegationNodeId>>)> { - public_credentials::Credentials::::iter_prefix(&subject).collect() + fn get_credentials(subject: Vec, filter: Option>) -> Result::DelegationNodeId>>)>, PublicCredentialsApiError> { + let asset_did = AssetDid::try_from(subject).map_err(|_| PublicCredentialsApiError::InvalidSubjectId)?; + let credentials_prefix = public_credentials::Credentials::::iter_prefix(&asset_did); + if let Some(filter) = filter { + Ok(credentials_prefix.filter(|(_, entry)| filter.should_include(entry)).collect()) + } else { + Ok(credentials_prefix.collect()) + } } } diff --git a/runtimes/spiritnet/src/lib.rs b/runtimes/spiritnet/src/lib.rs index ab4eda9b51..94359c99ef 100644 --- a/runtimes/spiritnet/src/lib.rs +++ b/runtimes/spiritnet/src/lib.rs @@ -47,14 +47,16 @@ use xcm_executor::XcmExecutor; use delegation::DelegationAc; use did_rpc_runtime_api::runtime_decl_for_DidApi::DidApiV2; +use kilt_support::traits::ItemFilter; use pallet_did_lookup::{linkable_account::LinkableAccountId, migrations::EthereumMigration}; pub use parachain_staking::InflationInfo; pub use public_credentials; use runtime_common::{ - assets::AssetDid, + assets::{AssetDid, PublicCredentialsFilter}, authorization::{AuthorizationId, PalletAuthorize}, constants::{self, EXISTENTIAL_DEPOSIT, KILT}, + errors::PublicCredentialsApiError, fees::{ToAuthor, WeightToFee}, migrations, pallet_id, AccountId, AuthorityId, Balance, BlockHashCount, BlockLength, BlockNumber, BlockWeights, DidIdentifier, FeeSplit, Hash, Header, Index, Signature, SlowAdjustingFeeUpdate, @@ -1283,14 +1285,20 @@ impl_runtime_apis! { } } - impl public_credentials_runtime_api::PublicCredentialsApi::DelegationNodeId>>> for Runtime { + impl public_credentials_runtime_api::PublicCredentials, Hash, public_credentials::CredentialEntry::DelegationNodeId>>, PublicCredentialsFilter, PublicCredentialsApiError> for Runtime { fn get_credential(credential_id: Hash) -> Option::DelegationNodeId>>> { let subject = public_credentials::CredentialSubjects::::get(&credential_id)?; public_credentials::Credentials::::get(&subject, &credential_id) } - fn get_credentials(subject: ::SubjectId) -> Vec<(Hash, public_credentials::CredentialEntry::DelegationNodeId>>)> { - public_credentials::Credentials::::iter_prefix(&subject).collect() + fn get_credentials(subject: Vec, filter: Option>) -> Result::DelegationNodeId>>)>, PublicCredentialsApiError> { + let asset_did = AssetDid::try_from(subject).map_err(|_| PublicCredentialsApiError::InvalidSubjectId)?; + let credentials_prefix = public_credentials::Credentials::::iter_prefix(&asset_did); + if let Some(filter) = filter { + Ok(credentials_prefix.filter(|(_, entry)| filter.should_include(entry)).collect()) + } else { + Ok(credentials_prefix.collect()) + } } } diff --git a/runtimes/standalone/Cargo.toml b/runtimes/standalone/Cargo.toml index eb64ae5ad2..b734467749 100644 --- a/runtimes/standalone/Cargo.toml +++ b/runtimes/standalone/Cargo.toml @@ -21,7 +21,7 @@ attestation = {default-features = false, path = "../../pallets/attestation"} ctype = {default-features = false, path = "../../pallets/ctype"} delegation = {default-features = false, path = "../../pallets/delegation"} did = {default-features = false, path = "../../pallets/did"} -kilt-support = {path = "../../support", default-features = false, optional = true} +kilt-support = {path = "../../support", default-features = false} pallet-did-lookup = {default-features = false, path = "../../pallets/pallet-did-lookup"} pallet-web3-names = {default-features = false, path = "../../pallets/pallet-web3-names"} public-credentials = {default-features = false, path = "../../pallets/public-credentials"} @@ -87,7 +87,6 @@ runtime-benchmarks = [ "frame-system-benchmarking", "hex-literal", "runtime-common/runtime-benchmarks", - "kilt-support", "kilt-support/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-did-lookup/runtime-benchmarks", @@ -111,6 +110,7 @@ std = [ "frame-system-rpc-runtime-api/std", "did-rpc-runtime-api/std", "frame-try-runtime/std", + "kilt-support/std", "log/std", "pallet-aura/std", "pallet-authorship/std", diff --git a/runtimes/standalone/src/lib.rs b/runtimes/standalone/src/lib.rs index 49b2836619..0772469feb 100644 --- a/runtimes/standalone/src/lib.rs +++ b/runtimes/standalone/src/lib.rs @@ -51,11 +51,13 @@ use sp_version::RuntimeVersion; use delegation::DelegationAc; use did_rpc_runtime_api::runtime_decl_for_DidApi::DidApiV2; +use kilt_support::traits::ItemFilter; use pallet_did_lookup::{linkable_account::LinkableAccountId, migrations::EthereumMigration}; use runtime_common::{ - assets::AssetDid, + assets::{AssetDid, PublicCredentialsFilter}, authorization::{AuthorizationId, PalletAuthorize}, constants::{self, EXISTENTIAL_DEPOSIT, KILT}, + errors::PublicCredentialsApiError, fees::ToAuthor, AccountId, Balance, BlockNumber, DidIdentifier, Hash, Index, Signature, SlowAdjustingFeeUpdate, }; @@ -1041,14 +1043,20 @@ impl_runtime_apis! { } } - impl public_credentials_runtime_api::PublicCredentialsApi::DelegationNodeId>>> for Runtime { + impl public_credentials_runtime_api::PublicCredentials, Hash, public_credentials::CredentialEntry::DelegationNodeId>>, PublicCredentialsFilter, PublicCredentialsApiError> for Runtime { fn get_credential(credential_id: Hash) -> Option::DelegationNodeId>>> { let subject = public_credentials::CredentialSubjects::::get(&credential_id)?; public_credentials::Credentials::::get(&subject, &credential_id) } - fn get_credentials(subject: ::SubjectId) -> Vec<(Hash, public_credentials::CredentialEntry::DelegationNodeId>>)> { - public_credentials::Credentials::::iter_prefix(&subject).collect() + fn get_credentials(subject: Vec, filter: Option>) -> Result::DelegationNodeId>>)>, PublicCredentialsApiError> { + let asset_did = AssetDid::try_from(subject).map_err(|_| PublicCredentialsApiError::InvalidSubjectId)?; + let credentials_prefix = public_credentials::Credentials::::iter_prefix(&asset_did); + if let Some(filter) = filter { + Ok(credentials_prefix.filter(|(_, entry)| filter.should_include(entry)).collect()) + } else { + Ok(credentials_prefix.collect()) + } } } diff --git a/support/src/traits.rs b/support/src/traits.rs index 4879b2a12d..269608578d 100644 --- a/support/src/traits.rs +++ b/support/src/traits.rs @@ -75,3 +75,8 @@ pub trait GenerateBenchmarkOrigin { pub trait GetWorstCase { fn worst_case() -> Self; } + +/// Generic filter. +pub trait ItemFilter { + fn should_include(&self, credential: &Item) -> bool; +}