From 3b6a7eb84ac3027c913cff77efb9537d04558a06 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 6 Apr 2023 16:13:10 +0200 Subject: [PATCH 1/8] wip --- dip-template/runtimes/dip-receiver/src/dip.rs | 32 ++++++++++++++++++- dip-template/runtimes/dip-receiver/src/lib.rs | 4 +-- pallets/pallet-dip-receiver/src/lib.rs | 23 +++++++++++-- pallets/pallet-dip-receiver/src/origin.rs | 25 +++++++++------ pallets/pallet-dip-receiver/src/traits.rs | 9 ++++++ 5 files changed, 78 insertions(+), 15 deletions(-) diff --git a/dip-template/runtimes/dip-receiver/src/dip.rs b/dip-template/runtimes/dip-receiver/src/dip.rs index 18a5ff1b05..cd1fcb155c 100644 --- a/dip-template/runtimes/dip-receiver/src/dip.rs +++ b/dip-template/runtimes/dip-receiver/src/dip.rs @@ -16,18 +16,48 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -use runtime_common::dip::{receiver::DidMerkleProofVerifier, ProofLeaf}; +use pallet_dip_receiver::traits::DipCallOriginFilter; +use runtime_common::dip::{ + receiver::{DidMerkleProofVerifier, VerificationResult}, + ProofLeaf, KeyRelationship, +}; use sp_std::vec::Vec; use crate::{BlockNumber, DidIdentifier, Hash, Hasher, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin}; impl pallet_dip_receiver::Config for Runtime { type BlindedValue = Vec>; + type DipCallOriginFilter = DipCallFilter; type Identifier = DidIdentifier; type ProofLeaf = ProofLeaf; type ProofDigest = Hash; + type ProofVerificationResult = (); type ProofVerifier = DidMerkleProofVerifier; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; } + +pub struct DipCallFilter; + +impl DipCallOriginFilter for DipCallFilter { + type Call = RuntimeCall; + type Error = (); + type Proof = VerificationResult; + type Success = (); + + fn check_proof(call: Self::Call, proof: Self::Proof) -> Result { + if matches!(call, Self::Call::DidLookup { .. }) { + if proof + .0 + .contains(|l| matches!(l.relationship, KeyRelationship::)) + { + Ok(()) + } else { + Err(()) + } + } else { + Err(()) + } + } +} diff --git a/dip-template/runtimes/dip-receiver/src/lib.rs b/dip-template/runtimes/dip-receiver/src/lib.rs index c678bf0c2c..8df71ecef9 100644 --- a/dip-template/runtimes/dip-receiver/src/lib.rs +++ b/dip-template/runtimes/dip-receiver/src/lib.rs @@ -358,8 +358,8 @@ impl pallet_did_lookup::Config for Runtime { type Currency = Balances; type Deposit = ConstU128; type DidIdentifier = DidIdentifier; - type EnsureOrigin = EnsureDipOrigin; - type OriginSuccess = DipOrigin; + type EnsureOrigin = EnsureDipOrigin; + type OriginSuccess = DipOrigin; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } diff --git a/pallets/pallet-dip-receiver/src/lib.rs b/pallets/pallet-dip-receiver/src/lib.rs index cb93b72281..c5ae01e5ff 100644 --- a/pallets/pallet-dip-receiver/src/lib.rs +++ b/pallets/pallet-dip-receiver/src/lib.rs @@ -36,7 +36,7 @@ pub mod pallet { use dip_support::{latest::IdentityProofAction, VersionedIdentityProof, VersionedIdentityProofAction}; - use crate::traits::IdentityProofVerifier; + use crate::traits::{DipCallOriginFilter, IdentityProofVerifier}; pub type VersionedIdentityProofOf = VersionedIdentityProof<::BlindedValue, ::ProofLeaf>; @@ -52,9 +52,15 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { type BlindedValue: Parameter; + type DipCallOriginFilter: DipCallOriginFilter< + Call = ::RuntimeCall, + Proof = ::VerificationResult, + Success = Self::ProofVerificationResult, + >; type Identifier: Parameter + MaxEncodedLen; type ProofLeaf: Parameter; type ProofDigest: Parameter + MaxEncodedLen; + type ProofVerificationResult; type ProofVerifier: IdentityProofVerifier< BlindedValue = Self::BlindedValue, ProofDigest = Self::ProofDigest, @@ -80,7 +86,9 @@ pub mod pallet { } #[pallet::error] + pub enum Error { + BadOrigin, Dispatch, IdentityNotFound, InvalidProof, @@ -89,7 +97,11 @@ pub mod pallet { // The new origin other pallets can use. #[pallet::origin] - pub type Origin = DipOrigin<::Identifier, ::AccountId>; + pub type Origin = DipOrigin< + ::Identifier, + ::AccountId, + ::ProofVerificationResult, + >; // TODO: Benchmarking #[pallet::call] @@ -130,12 +142,17 @@ pub mod pallet { ) -> DispatchResult { let submitter = ensure_signed(origin)?; let proof_digest = IdentityProofs::::get(&identifier).ok_or(Error::::IdentityNotFound)?; - let _ = T::ProofVerifier::verify_proof_against_digest(proof, proof_digest) + let proof_verification_result = T::ProofVerifier::verify_proof_against_digest(proof, proof_digest) .map_err(|_| Error::::InvalidProof)?; + // TODO: Better error handling + // TODO: Avoid cloning `call` + let proof_result = T::DipCallOriginFilter::check_proof(*call.clone(), proof_verification_result) + .map_err(|_| Error::::BadOrigin)?; // TODO: Proper DID signature verification (and cross-chain replay protection) let did_origin = DipOrigin { identifier, account_address: submitter, + proof: proof_result, }; // TODO: Use dispatch info for weight calculation let _ = call.dispatch(did_origin.into()).map_err(|_| Error::::Dispatch)?; diff --git a/pallets/pallet-dip-receiver/src/origin.rs b/pallets/pallet-dip-receiver/src/origin.rs index 84b73cceae..0b86855f03 100644 --- a/pallets/pallet-dip-receiver/src/origin.rs +++ b/pallets/pallet-dip-receiver/src/origin.rs @@ -22,19 +22,22 @@ use scale_info::TypeInfo; use sp_std::marker::PhantomData; #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct DipOrigin { +pub struct DipOrigin { pub identifier: Identifier, pub account_address: AccountId, + pub proof: Proof, } -pub struct EnsureDipOrigin(PhantomData<(Identifier, AccountId)>); +pub struct EnsureDipOrigin(PhantomData<(Identifier, AccountId, Proof)>); #[cfg(not(feature = "runtime-benchmarks"))] -impl EnsureOrigin for EnsureDipOrigin +impl EnsureOrigin + for EnsureDipOrigin where - OuterOrigin: From> + Into, OuterOrigin>>, + OuterOrigin: From> + + Into, OuterOrigin>>, { - type Success = DipOrigin; + type Success = DipOrigin; fn try_origin(o: OuterOrigin) -> Result { o.into() @@ -42,12 +45,15 @@ where } #[cfg(feature = "runtime-benchmarks")] -impl EnsureOrigin for EnsureDipOrigin +impl EnsureOrigin + for EnsureDipOrigin where - OuterOrigin: From> + Into, OuterOrigin>>, + OuterOrigin: From> + + Into, OuterOrigin>>, // Additional trait bounds only valid when benchmarking Identifier: From<[u8; 32]>, AccountId: From<[u8; 32]>, + Proof: Default, { type Success = DipOrigin; @@ -59,12 +65,13 @@ where Ok(OuterOrigin::from(DipOrigin { identifier: Identifier::from([0u8; 32]), account_address: AccountId::from([0u8; 32]), + proof: Default::default(), })) } } -impl kilt_support::traits::CallSources - for DipOrigin +impl kilt_support::traits::CallSources + for DipOrigin where Identifier: Clone, AccountId: Clone, diff --git a/pallets/pallet-dip-receiver/src/traits.rs b/pallets/pallet-dip-receiver/src/traits.rs index ef7642fff9..48a1bfe921 100644 --- a/pallets/pallet-dip-receiver/src/traits.rs +++ b/pallets/pallet-dip-receiver/src/traits.rs @@ -50,3 +50,12 @@ impl IdentityProofVerifier Ok(()) } } + +pub trait DipCallOriginFilter { + type Call; + type Error; + type Proof; + type Success; + + fn check_proof(call: Self::Call, proof: Self::Proof) -> Result; +} From 9fa1afbf1987f21497d59ffc08290d1de63f3c59 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 11 Apr 2023 10:28:54 +0200 Subject: [PATCH 2/8] Compilation working --- Cargo.lock | 1 + dip-template/runtimes/dip-receiver/Cargo.toml | 8 +++++--- dip-template/runtimes/dip-receiver/src/dip.rs | 6 ++++-- pallets/pallet-dip-receiver/src/origin.rs | 2 +- runtimes/common/src/dip/receiver.rs | 6 ++++++ 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b03ccc153..942ff4fbd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2249,6 +2249,7 @@ dependencies = [ "cumulus-primitives-core", "cumulus-primitives-timestamp", "cumulus-primitives-utility", + "did", "frame-executive", "frame-support", "frame-system", diff --git a/dip-template/runtimes/dip-receiver/Cargo.toml b/dip-template/runtimes/dip-receiver/Cargo.toml index 76e495ad63..87dddba9d0 100644 --- a/dip-template/runtimes/dip-receiver/Cargo.toml +++ b/dip-template/runtimes/dip-receiver/Cargo.toml @@ -18,6 +18,7 @@ codec = {package = "parity-scale-codec", workspace = true, features = ["derive"] scale-info = {workspace = true, features = ["derive"]} # DIP +did.workspace = true pallet-did-lookup.workspace = true pallet-dip-receiver.workspace = true runtime-common.workspace = true @@ -73,6 +74,7 @@ default = [ std = [ "codec/std", "scale-info/std", + "did/std", "pallet-did-lookup/std", "pallet-dip-receiver/std", "runtime-common/std", @@ -117,10 +119,10 @@ std = [ ] runtime-benchmarks = [ - "frame-system/runtime-benchmarks", - "frame-support/runtime-benchmarks", "pallet-dip-receiver/runtime-benchmarks", "runtime-common/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", ] diff --git a/dip-template/runtimes/dip-receiver/src/dip.rs b/dip-template/runtimes/dip-receiver/src/dip.rs index cd1fcb155c..23cbede9a6 100644 --- a/dip-template/runtimes/dip-receiver/src/dip.rs +++ b/dip-template/runtimes/dip-receiver/src/dip.rs @@ -16,10 +16,11 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org +use did::DidVerificationKeyRelationship; use pallet_dip_receiver::traits::DipCallOriginFilter; use runtime_common::dip::{ receiver::{DidMerkleProofVerifier, VerificationResult}, - ProofLeaf, KeyRelationship, + ProofLeaf, }; use sp_std::vec::Vec; @@ -50,7 +51,8 @@ impl DipCallOriginFilter for DipCallFilter { if matches!(call, Self::Call::DidLookup { .. }) { if proof .0 - .contains(|l| matches!(l.relationship, KeyRelationship::)) + .iter() + .any(|l| l.relationship == DidVerificationKeyRelationship::Authentication.into()) { Ok(()) } else { diff --git a/pallets/pallet-dip-receiver/src/origin.rs b/pallets/pallet-dip-receiver/src/origin.rs index 0b86855f03..53955dfd59 100644 --- a/pallets/pallet-dip-receiver/src/origin.rs +++ b/pallets/pallet-dip-receiver/src/origin.rs @@ -55,7 +55,7 @@ where AccountId: From<[u8; 32]>, Proof: Default, { - type Success = DipOrigin; + type Success = DipOrigin; fn try_origin(o: OuterOrigin) -> Result { o.into() diff --git a/runtimes/common/src/dip/receiver.rs b/runtimes/common/src/dip/receiver.rs index b4491b568b..0ccecb191a 100644 --- a/runtimes/common/src/dip/receiver.rs +++ b/runtimes/common/src/dip/receiver.rs @@ -45,6 +45,12 @@ impl From>> for VerificationResult VerificationResult { + pub fn into_inner(self) -> Vec> { + self.0 + } +} + pub struct DidMerkleProofVerifier(PhantomData<(KeyId, BlockNumber, Hasher)>); impl IdentityProofVerifier for DidMerkleProofVerifier From 27148337788c616566e8a796254a6d28a48470c9 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 11 Apr 2023 13:34:33 +0200 Subject: [PATCH 3/8] Rename Proof to Details --- pallets/pallet-dip-receiver/src/lib.rs | 2 +- pallets/pallet-dip-receiver/src/origin.rs | 34 +++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/pallets/pallet-dip-receiver/src/lib.rs b/pallets/pallet-dip-receiver/src/lib.rs index c5ae01e5ff..3b86b5593f 100644 --- a/pallets/pallet-dip-receiver/src/lib.rs +++ b/pallets/pallet-dip-receiver/src/lib.rs @@ -152,7 +152,7 @@ pub mod pallet { let did_origin = DipOrigin { identifier, account_address: submitter, - proof: proof_result, + details: proof_result, }; // TODO: Use dispatch info for weight calculation let _ = call.dispatch(did_origin.into()).map_err(|_| Error::::Dispatch)?; diff --git a/pallets/pallet-dip-receiver/src/origin.rs b/pallets/pallet-dip-receiver/src/origin.rs index 53955dfd59..98b033791d 100644 --- a/pallets/pallet-dip-receiver/src/origin.rs +++ b/pallets/pallet-dip-receiver/src/origin.rs @@ -22,22 +22,22 @@ use scale_info::TypeInfo; use sp_std::marker::PhantomData; #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct DipOrigin { +pub struct DipOrigin { pub identifier: Identifier, pub account_address: AccountId, - pub proof: Proof, + pub details: Details, } -pub struct EnsureDipOrigin(PhantomData<(Identifier, AccountId, Proof)>); +pub struct EnsureDipOrigin(PhantomData<(Identifier, AccountId, Details)>); #[cfg(not(feature = "runtime-benchmarks"))] -impl EnsureOrigin - for EnsureDipOrigin +impl EnsureOrigin + for EnsureDipOrigin where - OuterOrigin: From> - + Into, OuterOrigin>>, + OuterOrigin: From> + + Into, OuterOrigin>>, { - type Success = DipOrigin; + type Success = DipOrigin; fn try_origin(o: OuterOrigin) -> Result { o.into() @@ -45,17 +45,17 @@ where } #[cfg(feature = "runtime-benchmarks")] -impl EnsureOrigin - for EnsureDipOrigin +impl EnsureOrigin + for EnsureDipOrigin where - OuterOrigin: From> - + Into, OuterOrigin>>, + OuterOrigin: From> + + Into, OuterOrigin>>, // Additional trait bounds only valid when benchmarking Identifier: From<[u8; 32]>, AccountId: From<[u8; 32]>, - Proof: Default, + Details: Default, { - type Success = DipOrigin; + type Success = DipOrigin; fn try_origin(o: OuterOrigin) -> Result { o.into() @@ -65,13 +65,13 @@ where Ok(OuterOrigin::from(DipOrigin { identifier: Identifier::from([0u8; 32]), account_address: AccountId::from([0u8; 32]), - proof: Default::default(), + details: Default::default(), })) } } -impl kilt_support::traits::CallSources - for DipOrigin +impl kilt_support::traits::CallSources + for DipOrigin where Identifier: Clone, AccountId: Clone, From 40b6037329b2057479bc03c8648c8a116ed691d0 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 11 Apr 2023 13:46:39 +0200 Subject: [PATCH 4/8] Add comments --- dip-template/runtimes/dip-receiver/src/dip.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dip-template/runtimes/dip-receiver/src/dip.rs b/dip-template/runtimes/dip-receiver/src/dip.rs index 23cbede9a6..a7eb8a4938 100644 --- a/dip-template/runtimes/dip-receiver/src/dip.rs +++ b/dip-template/runtimes/dip-receiver/src/dip.rs @@ -47,7 +47,10 @@ impl DipCallOriginFilter for DipCallFilter { type Proof = VerificationResult; type Success = (); + // Accepts only a DipOrigin for the DidLookup pallet calls. fn check_proof(call: Self::Call, proof: Self::Proof) -> Result { + // All calls in the pallet require a DID authentication key. + // TODO: Add support for nested calls. if matches!(call, Self::Call::DidLookup { .. }) { if proof .0 From f97f42856fb388e4ad9e567114e6b30be4db3766 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 11 Apr 2023 14:19:10 +0200 Subject: [PATCH 5/8] Remove unnecessary parameters from pallet-dip-receiver --- dip-template/runtimes/dip-receiver/src/dip.rs | 1 - pallets/pallet-dip-receiver/src/lib.rs | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/dip-template/runtimes/dip-receiver/src/dip.rs b/dip-template/runtimes/dip-receiver/src/dip.rs index a7eb8a4938..b94adf2cf9 100644 --- a/dip-template/runtimes/dip-receiver/src/dip.rs +++ b/dip-template/runtimes/dip-receiver/src/dip.rs @@ -32,7 +32,6 @@ impl pallet_dip_receiver::Config for Runtime { type Identifier = DidIdentifier; type ProofLeaf = ProofLeaf; type ProofDigest = Hash; - type ProofVerificationResult = (); type ProofVerifier = DidMerkleProofVerifier; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; diff --git a/pallets/pallet-dip-receiver/src/lib.rs b/pallets/pallet-dip-receiver/src/lib.rs index 3b86b5593f..e141ffeb08 100644 --- a/pallets/pallet-dip-receiver/src/lib.rs +++ b/pallets/pallet-dip-receiver/src/lib.rs @@ -40,6 +40,7 @@ pub mod pallet { pub type VersionedIdentityProofOf = VersionedIdentityProof<::BlindedValue, ::ProofLeaf>; + pub type VerificationResultOf = <::ProofVerifier as IdentityProofVerifier>::VerificationResult; const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); @@ -55,12 +56,10 @@ pub mod pallet { type DipCallOriginFilter: DipCallOriginFilter< Call = ::RuntimeCall, Proof = ::VerificationResult, - Success = Self::ProofVerificationResult, >; type Identifier: Parameter + MaxEncodedLen; type ProofLeaf: Parameter; type ProofDigest: Parameter + MaxEncodedLen; - type ProofVerificationResult; type ProofVerifier: IdentityProofVerifier< BlindedValue = Self::BlindedValue, ProofDigest = Self::ProofDigest, @@ -100,7 +99,7 @@ pub mod pallet { pub type Origin = DipOrigin< ::Identifier, ::AccountId, - ::ProofVerificationResult, + <::DipCallOriginFilter as DipCallOriginFilter>::Success, >; // TODO: Benchmarking From 7f81bbf206839452fb860ed12ea137acf5356e8f Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 11 Apr 2023 14:35:35 +0200 Subject: [PATCH 6/8] Cleanup --- pallets/pallet-dip-receiver/src/lib.rs | 5 ++--- runtimes/common/src/dip/receiver.rs | 6 ------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/pallets/pallet-dip-receiver/src/lib.rs b/pallets/pallet-dip-receiver/src/lib.rs index e141ffeb08..29ebb36f9a 100644 --- a/pallets/pallet-dip-receiver/src/lib.rs +++ b/pallets/pallet-dip-receiver/src/lib.rs @@ -38,9 +38,9 @@ pub mod pallet { use crate::traits::{DipCallOriginFilter, IdentityProofVerifier}; + pub type VerificationResultOf = <::ProofVerifier as IdentityProofVerifier>::VerificationResult; pub type VersionedIdentityProofOf = VersionedIdentityProof<::BlindedValue, ::ProofLeaf>; - pub type VerificationResultOf = <::ProofVerifier as IdentityProofVerifier>::VerificationResult; const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); @@ -55,7 +55,7 @@ pub mod pallet { type BlindedValue: Parameter; type DipCallOriginFilter: DipCallOriginFilter< Call = ::RuntimeCall, - Proof = ::VerificationResult, + Proof = VerificationResultOf, >; type Identifier: Parameter + MaxEncodedLen; type ProofLeaf: Parameter; @@ -85,7 +85,6 @@ pub mod pallet { } #[pallet::error] - pub enum Error { BadOrigin, Dispatch, diff --git a/runtimes/common/src/dip/receiver.rs b/runtimes/common/src/dip/receiver.rs index 0ccecb191a..b4491b568b 100644 --- a/runtimes/common/src/dip/receiver.rs +++ b/runtimes/common/src/dip/receiver.rs @@ -45,12 +45,6 @@ impl From>> for VerificationResult VerificationResult { - pub fn into_inner(self) -> Vec> { - self.0 - } -} - pub struct DidMerkleProofVerifier(PhantomData<(KeyId, BlockNumber, Hasher)>); impl IdentityProofVerifier for DidMerkleProofVerifier From 14acb44590c2b4dfea3513c66f320192997e4d93 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Wed, 12 Apr 2023 08:54:36 +0200 Subject: [PATCH 7/8] Change associated type to generic type --- dip-template/runtimes/dip-receiver/src/dip.rs | 7 +++---- pallets/pallet-dip-receiver/src/lib.rs | 7 ++----- pallets/pallet-dip-receiver/src/traits.rs | 5 ++--- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/dip-template/runtimes/dip-receiver/src/dip.rs b/dip-template/runtimes/dip-receiver/src/dip.rs index b94adf2cf9..001e38a61d 100644 --- a/dip-template/runtimes/dip-receiver/src/dip.rs +++ b/dip-template/runtimes/dip-receiver/src/dip.rs @@ -40,17 +40,16 @@ impl pallet_dip_receiver::Config for Runtime { pub struct DipCallFilter; -impl DipCallOriginFilter for DipCallFilter { - type Call = RuntimeCall; +impl DipCallOriginFilter for DipCallFilter { type Error = (); type Proof = VerificationResult; type Success = (); // Accepts only a DipOrigin for the DidLookup pallet calls. - fn check_proof(call: Self::Call, proof: Self::Proof) -> Result { + fn check_proof(call: RuntimeCall, proof: Self::Proof) -> Result { // All calls in the pallet require a DID authentication key. // TODO: Add support for nested calls. - if matches!(call, Self::Call::DidLookup { .. }) { + if matches!(call, RuntimeCall::DidLookup { .. }) { if proof .0 .iter() diff --git a/pallets/pallet-dip-receiver/src/lib.rs b/pallets/pallet-dip-receiver/src/lib.rs index 29ebb36f9a..a351ae1b9a 100644 --- a/pallets/pallet-dip-receiver/src/lib.rs +++ b/pallets/pallet-dip-receiver/src/lib.rs @@ -53,10 +53,7 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { type BlindedValue: Parameter; - type DipCallOriginFilter: DipCallOriginFilter< - Call = ::RuntimeCall, - Proof = VerificationResultOf, - >; + type DipCallOriginFilter: DipCallOriginFilter<::RuntimeCall, Proof = VerificationResultOf>; type Identifier: Parameter + MaxEncodedLen; type ProofLeaf: Parameter; type ProofDigest: Parameter + MaxEncodedLen; @@ -98,7 +95,7 @@ pub mod pallet { pub type Origin = DipOrigin< ::Identifier, ::AccountId, - <::DipCallOriginFilter as DipCallOriginFilter>::Success, + <::DipCallOriginFilter as DipCallOriginFilter<::RuntimeCall>>::Success, >; // TODO: Benchmarking diff --git a/pallets/pallet-dip-receiver/src/traits.rs b/pallets/pallet-dip-receiver/src/traits.rs index 48a1bfe921..c134a038f5 100644 --- a/pallets/pallet-dip-receiver/src/traits.rs +++ b/pallets/pallet-dip-receiver/src/traits.rs @@ -51,11 +51,10 @@ impl IdentityProofVerifier } } -pub trait DipCallOriginFilter { - type Call; +pub trait DipCallOriginFilter { type Error; type Proof; type Success; - fn check_proof(call: Self::Call, proof: Self::Proof) -> Result; + fn check_proof(call: Call, proof: Self::Proof) -> Result; } From bd1ec65a5fa6595641b2a6748a674076ea2e621f Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Wed, 12 Apr 2023 13:34:46 +0200 Subject: [PATCH 8/8] Add utility pallet to receiver template and implement nested call logic --- Cargo.lock | 1 + dip-template/runtimes/dip-receiver/Cargo.toml | 2 + dip-template/runtimes/dip-receiver/src/dip.rs | 84 ++++++++++++++++--- dip-template/runtimes/dip-receiver/src/lib.rs | 8 ++ 4 files changed, 83 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 942ff4fbd2..9aea81789f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2265,6 +2265,7 @@ dependencies = [ "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", + "pallet-utility", "pallet-xcm", "parachain-info", "parity-scale-codec", diff --git a/dip-template/runtimes/dip-receiver/Cargo.toml b/dip-template/runtimes/dip-receiver/Cargo.toml index 87dddba9d0..0621478468 100644 --- a/dip-template/runtimes/dip-receiver/Cargo.toml +++ b/dip-template/runtimes/dip-receiver/Cargo.toml @@ -36,6 +36,7 @@ pallet-sudo.workspace = true pallet-timestamp.workspace = true pallet-transaction-payment.workspace = true pallet-transaction-payment-rpc-runtime-api.workspace = true +pallet-utility.workspace = true polkadot-parachain.workspace = true sp-api.workspace = true sp-block-builder.workspace = true @@ -90,6 +91,7 @@ std = [ "pallet-timestamp/std", "pallet-transaction-payment/std", "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-utility/std", "polkadot-parachain/std", "sp-api/std", "sp-block-builder/std", diff --git a/dip-template/runtimes/dip-receiver/src/dip.rs b/dip-template/runtimes/dip-receiver/src/dip.rs index 001e38a61d..b170209347 100644 --- a/dip-template/runtimes/dip-receiver/src/dip.rs +++ b/dip-template/runtimes/dip-receiver/src/dip.rs @@ -38,6 +38,34 @@ impl pallet_dip_receiver::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; } +fn derive_verification_key_relationship(call: &RuntimeCall) -> Option { + match call { + RuntimeCall::DidLookup { .. } => Some(DidVerificationKeyRelationship::Authentication), + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) => single_key_relationship(calls).ok(), + RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => single_key_relationship(calls).ok(), + RuntimeCall::Utility(pallet_utility::Call::force_batch { calls }) => single_key_relationship(calls).ok(), + _ => None, + } +} + +// Taken and adapted from `impl +// did::DeriveDidCallAuthorizationVerificationKeyRelationship for RuntimeCall` +// in Spiritnet/Peregrine runtime. +fn single_key_relationship(calls: &[RuntimeCall]) -> Result { + let first_call_relationship = calls.get(0).and_then(derive_verification_key_relationship).ok_or(())?; + calls + .iter() + .skip(1) + .map(derive_verification_key_relationship) + .try_fold(first_call_relationship, |acc, next| { + if next == Some(acc) { + Ok(acc) + } else { + Err(()) + } + }) +} + pub struct DipCallFilter; impl DipCallOriginFilter for DipCallFilter { @@ -47,20 +75,52 @@ impl DipCallOriginFilter for DipCallFilter { // Accepts only a DipOrigin for the DidLookup pallet calls. fn check_proof(call: RuntimeCall, proof: Self::Proof) -> Result { - // All calls in the pallet require a DID authentication key. - // TODO: Add support for nested calls. - if matches!(call, RuntimeCall::DidLookup { .. }) { - if proof - .0 - .iter() - .any(|l| l.relationship == DidVerificationKeyRelationship::Authentication.into()) - { - Ok(()) - } else { - Err(()) - } + let key_relationship = single_key_relationship(&[call])?; + if proof.0.iter().any(|l| l.relationship == key_relationship.into()) { + Ok(()) } else { Err(()) } } } + +#[cfg(test)] +mod dip_call_origin_filter_tests { + use super::*; + + use frame_support::assert_err; + + #[test] + fn test_key_relationship_derivation() { + // Can call DidLookup functions with an authentication key + let did_lookup_call = RuntimeCall::DidLookup(pallet_did_lookup::Call::associate_sender {}); + assert_eq!( + single_key_relationship(&[did_lookup_call]), + Ok(DidVerificationKeyRelationship::Authentication) + ); + // Can't call System functions with a DID key (hence a DIP origin) + let system_call = RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); + assert_err!(single_key_relationship(&[system_call]), ()); + // Can't call empty batch with a DID key + let empty_batch_call = RuntimeCall::Utility(pallet_utility::Call::batch_all { calls: vec![] }); + assert_err!(single_key_relationship(&[empty_batch_call]), ()); + // Can call batch with a DipLookup with an authentication key + let did_lookup_batch_call = RuntimeCall::Utility(pallet_utility::Call::batch_all { + calls: vec![pallet_did_lookup::Call::associate_sender {}.into()], + }); + assert_eq!( + single_key_relationship(&[did_lookup_batch_call]), + Ok(DidVerificationKeyRelationship::Authentication) + ); + // Can't call a batch with different required keys + let did_lookup_batch_call = RuntimeCall::Utility(pallet_utility::Call::batch_all { + calls: vec![ + // Authentication key + pallet_did_lookup::Call::associate_sender {}.into(), + // No key + frame_system::Call::remark { remark: vec![] }.into(), + ], + }); + assert_err!(single_key_relationship(&[did_lookup_batch_call]), ()); + } +} diff --git a/dip-template/runtimes/dip-receiver/src/lib.rs b/dip-template/runtimes/dip-receiver/src/lib.rs index 8df71ecef9..1037d471ba 100644 --- a/dip-template/runtimes/dip-receiver/src/lib.rs +++ b/dip-template/runtimes/dip-receiver/src/lib.rs @@ -119,6 +119,7 @@ construct_runtime!( Timestamp: pallet_timestamp = 2, ParachainInfo: parachain_info = 3, Sudo: pallet_sudo = 4, + Utility: pallet_utility = 5, // Money Balances: pallet_balances = 10, @@ -277,6 +278,13 @@ impl pallet_sudo::Config for Runtime { type RuntimeEvent = RuntimeEvent; } +impl pallet_utility::Config for Runtime { + type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT; impl pallet_balances::Config for Runtime {