From bddc86f2ef1280b73289f60d3d4dc19223b79274 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Wed, 10 Jan 2024 09:36:27 +0100 Subject: [PATCH 01/45] Unique leaf instead of key + value --- crates/kilt-dip-primitives/src/merkle.rs | 133 +++++++----------- .../nodes/dip-consumer/src/command.rs | 11 +- .../nodes/dip-provider/src/command.rs | 11 +- runtimes/common/src/dip/merkle.rs | 87 ++++++------ 4 files changed, 98 insertions(+), 144 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle.rs b/crates/kilt-dip-primitives/src/merkle.rs index 6d744777f8..499c6dcb0c 100644 --- a/crates/kilt-dip-primitives/src/merkle.rs +++ b/crates/kilt-dip-primitives/src/merkle.rs @@ -73,75 +73,39 @@ impl TryFrom for DidVerificationKeyRelationship { } } -/// The key of a Merkle leaf revealing a DID key for a DID Document. +/// All possible Merkle leaf types that can be revealed as part of a DIP +/// identity Merkle proof. #[derive(Clone, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] -pub struct DidKeyMerkleKey(pub KeyId, pub DidKeyRelationship); - -impl From<(KeyId, DidKeyRelationship)> for DidKeyMerkleKey { - fn from(value: (KeyId, DidKeyRelationship)) -> Self { - Self(value.0, value.1) - } +pub enum RevealedDidMerkleProofLeaf { + DidKey(RevealedDidKey), + Web3Name(RevealedWeb3Name), + LinkedAccount(RevealedAccountId), } -/// The value of a Merkle leaf revealing a DID key for a DID Document. -#[derive(Clone, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] -pub struct DidKeyMerkleValue(pub DidPublicKeyDetails); -impl From> - for DidKeyMerkleValue +impl From> + for RevealedDidMerkleProofLeaf { - fn from(value: DidPublicKeyDetails) -> Self { - Self(value) - } -} - -/// The key of a Merkle leaf revealing the web3name linked to a DID Document. -#[derive(Clone, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] -pub struct Web3NameMerkleKey(pub Web3Name); - -impl From for Web3NameMerkleKey { - fn from(value: Web3Name) -> Self { - Self(value) + fn from(value: RevealedDidKey) -> Self { + Self::DidKey(value) } } -/// The value of a Merkle leaf revealing the web3name linked to a DID Document. -#[derive(Clone, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] -pub struct Web3NameMerkleValue(pub BlockNumber); - -impl From for Web3NameMerkleValue { - fn from(value: BlockNumber) -> Self { - Self(value) - } -} - -/// The key of a Merkle leaf revealing an account linked to a DID Document. -#[derive(Clone, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] -pub struct LinkedAccountMerkleKey(pub AccountId); -impl From for LinkedAccountMerkleKey { - fn from(value: AccountId) -> Self { - Self(value) +impl From> + for RevealedDidMerkleProofLeaf +{ + fn from(value: RevealedWeb3Name) -> Self { + Self::Web3Name(value) } } -/// The value of a Merkle leaf revealing an account linked to a DID -/// Document. -#[derive(Clone, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] -pub struct LinkedAccountMerkleValue; -impl From<()> for LinkedAccountMerkleValue { - fn from(_value: ()) -> Self { - Self +impl From> + for RevealedDidMerkleProofLeaf +{ + fn from(value: RevealedAccountId) -> Self { + Self::LinkedAccount(value) } } -/// All possible Merkle leaf types that can be revealed as part of a DIP -/// identity Merkle proof. -#[derive(Clone, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] -pub enum RevealedDidMerkleProofLeaf { - DidKey(DidKeyMerkleKey, DidKeyMerkleValue), - Web3Name(Web3NameMerkleKey, Web3NameMerkleValue), - LinkedAccount(LinkedAccountMerkleKey, LinkedAccountMerkleValue), -} - #[cfg(feature = "runtime-benchmarks")] impl Default for RevealedDidMerkleProofLeaf @@ -150,15 +114,16 @@ where BlockNumber: Default, { fn default() -> Self { - Self::DidKey( - (KeyId::default(), DidVerificationKeyRelationship::Authentication.into()).into(), - DidPublicKeyDetails { + RevealedDidKey { + id: KeyId::default(), + relationship: DidVerificationKeyRelationship::Authentication.into(), + details: DidPublicKeyDetails { key: did::did_details::DidVerificationKey::Ed25519(sp_core::ed25519::Public::from_raw([0u8; 32])) .into(), block_number: BlockNumber::default(), - } - .into(), - ) + }, + } + .into() } } @@ -171,9 +136,9 @@ where { pub fn encoded_key(&self) -> Vec { match self { - RevealedDidMerkleProofLeaf::DidKey(key, _) => key.encode(), - RevealedDidMerkleProofLeaf::Web3Name(key, _) => key.encode(), - RevealedDidMerkleProofLeaf::LinkedAccount(key, _) => key.encode(), + RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { id, relationship, .. }) => (id, relationship).encode(), + RevealedDidMerkleProofLeaf::Web3Name(RevealedWeb3Name { web3_name, .. }) => web3_name.encode(), + RevealedDidMerkleProofLeaf::LinkedAccount(RevealedAccountId(account_id)) => account_id.encode(), } } } @@ -186,9 +151,9 @@ where { pub fn encoded_value(&self) -> Vec { match self { - RevealedDidMerkleProofLeaf::DidKey(_, value) => value.encode(), - RevealedDidMerkleProofLeaf::Web3Name(_, value) => value.encode(), - RevealedDidMerkleProofLeaf::LinkedAccount(_, value) => value.encode(), + RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { details, .. }) => details.encode(), + RevealedDidMerkleProofLeaf::Web3Name(RevealedWeb3Name { claimed_at, .. }) => claimed_at.encode(), + RevealedDidMerkleProofLeaf::LinkedAccount(_) => ().encode(), } } } @@ -217,6 +182,11 @@ pub struct RevealedWeb3Name { pub claimed_at: BlockNumber, } +/// The details of an account after it has been successfully verified in a +/// Merkle proof. +#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] +pub struct RevealedAccountId(pub AccountId); + /// The complete set of information that is provided by the DIP Merkle proof /// verifier upon successful verification of a DIP Merkle proof. #[derive(Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen, Encode, Decode, DefaultNoBound)] @@ -236,7 +206,7 @@ pub struct RevealedDidMerkleProofLeaves< pub web3_name: Option>, /// The list of linked accounts revealed in the Merkle proof, up to a /// maximum of `MAX_REVEALED_ACCOUNTS_COUNT`. - pub linked_accounts: BoundedVec>, + pub linked_accounts: BoundedVec, ConstU32>, } impl< @@ -361,7 +331,7 @@ where let (did_keys, web3_name, linked_accounts): ( BoundedVec, ConstU32>, Option>, - BoundedVec>, + BoundedVec, ConstU32>, ) = proof.revealed.into_iter().try_fold( ( BoundedVec::with_bounded_capacity(MAX_REVEALED_KEYS_COUNT.saturated_into()), @@ -369,12 +339,8 @@ where BoundedVec::with_bounded_capacity(MAX_REVEALED_ACCOUNTS_COUNT.saturated_into()), ), |(mut keys, web3_name, mut linked_accounts), leaf| match leaf { - RevealedDidMerkleProofLeaf::DidKey(key_id, key_value) => { - let res = keys.try_push(RevealedDidKey { - id: key_id.0, - relationship: key_id.1, - details: key_value.0, - }); + RevealedDidMerkleProofLeaf::DidKey(revealed_did_key) => { + let res = keys.try_push(revealed_did_key); cfg_if::cfg_if! { if #[cfg(feature = "runtime-benchmarks")] { drop(res); @@ -385,16 +351,11 @@ where Ok::<_, DidMerkleProofVerifierError>((keys, web3_name, linked_accounts)) } - RevealedDidMerkleProofLeaf::Web3Name(revealed_web3_name, details) => Ok(( - keys, - Some(RevealedWeb3Name { - web3_name: revealed_web3_name.0, - claimed_at: details.0, - }), - linked_accounts, - )), - RevealedDidMerkleProofLeaf::LinkedAccount(account_id, _) => { - let res = linked_accounts.try_push(account_id.0); + RevealedDidMerkleProofLeaf::Web3Name(revealed_web3name) => { + Ok((keys, Some(revealed_web3name), linked_accounts)) + } + RevealedDidMerkleProofLeaf::LinkedAccount(revealed_account_id) => { + let res = linked_accounts.try_push(revealed_account_id); cfg_if::cfg_if! { if #[cfg(feature = "runtime-benchmarks")] { drop(res); diff --git a/dip-template/nodes/dip-consumer/src/command.rs b/dip-template/nodes/dip-consumer/src/command.rs index f41f3c337a..f804bc0f43 100644 --- a/dip-template/nodes/dip-consumer/src/command.rs +++ b/dip-template/nodes/dip-consumer/src/command.rs @@ -210,14 +210,11 @@ pub fn run() -> Result<()> { cmd.run(partials.client) }), #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => { - return Err(sc_cli::Error::Input( - "Compile with --features=runtime-benchmarks \ + BenchmarkCmd::Storage(_) => Err(sc_cli::Error::Input( + "Compile with --features=runtime-benchmarks \ to enable storage benchmarks." - .into(), - ) - .into()) - } + .into(), + )), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { let partials = new_partial(&config)?; diff --git a/dip-template/nodes/dip-provider/src/command.rs b/dip-template/nodes/dip-provider/src/command.rs index 3fb8b8322b..acde956922 100644 --- a/dip-template/nodes/dip-provider/src/command.rs +++ b/dip-template/nodes/dip-provider/src/command.rs @@ -210,14 +210,11 @@ pub fn run() -> Result<()> { cmd.run(partials.client) }), #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => { - return Err(sc_cli::Error::Input( - "Compile with --features=runtime-benchmarks \ + BenchmarkCmd::Storage(_) => Err(sc_cli::Error::Input( + "Compile with --features=runtime-benchmarks \ to enable storage benchmarks." - .into(), - ) - .into()) - } + .into(), + )), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { let partials = new_partial(&config)?; diff --git a/runtimes/common/src/dip/merkle.rs b/runtimes/common/src/dip/merkle.rs index 2ab8cb5bec..839aeb5231 100644 --- a/runtimes/common/src/dip/merkle.rs +++ b/runtimes/common/src/dip/merkle.rs @@ -18,7 +18,7 @@ use did::{DidVerificationKeyRelationship, KeyIdOf}; use frame_support::RuntimeDebug; use frame_system::pallet_prelude::BlockNumberFor; -use kilt_dip_primitives::merkle::{DidKeyMerkleKey, DidKeyMerkleValue, DidMerkleProof}; +use kilt_dip_primitives::merkle::DidMerkleProof; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_provider::{ traits::{IdentityCommitmentGenerator, IdentityProvider}, @@ -79,6 +79,8 @@ impl From for u16 { } pub mod v0 { + use kilt_dip_primitives::merkle::{RevealedAccountId, RevealedDidKey, RevealedWeb3Name}; + use super::*; /// Type of a Merkle leaf revealed as part of a DIP Merkle proof. @@ -115,13 +117,11 @@ pub mod v0 { log::error!("Authentication key should be part of the public keys."); DidMerkleProofError::Internal })?; - let auth_leaf = ProofLeafOf::::DidKey( - DidKeyMerkleKey( - did_details.authentication_key, - DidVerificationKeyRelationship::Authentication.into(), - ), - DidKeyMerkleValue(auth_key_details.clone()), - ); + let auth_leaf = ProofLeafOf::::from(RevealedDidKey { + id: did_details.authentication_key, + relationship: DidVerificationKeyRelationship::Authentication.into(), + details: auth_key_details.clone(), + }); trie_builder .insert(auth_leaf.encoded_key().as_slice(), auth_leaf.encoded_value().as_slice()) .map_err(|_| { @@ -137,10 +137,11 @@ pub mod v0 { log::error!("Attestation key should be part of the public keys."); DidMerkleProofError::Internal })?; - let att_leaf = ProofLeafOf::::DidKey( - (att_key_id, DidVerificationKeyRelationship::AssertionMethod.into()).into(), - att_key_details.clone().into(), - ); + let att_leaf = ProofLeafOf::::from(RevealedDidKey { + id: att_key_id, + relationship: DidVerificationKeyRelationship::AssertionMethod.into(), + details: att_key_details.clone(), + }); trie_builder .insert(att_leaf.encoded_key().as_slice(), att_leaf.encoded_value().as_slice()) .map_err(|_| { @@ -157,10 +158,11 @@ pub mod v0 { log::error!("Delegation key should be part of the public keys."); DidMerkleProofError::Internal })?; - let del_leaf = ProofLeafOf::::DidKey( - (del_key_id, DidVerificationKeyRelationship::CapabilityDelegation.into()).into(), - del_key_details.clone().into(), - ); + let del_leaf = ProofLeafOf::::from(RevealedDidKey { + id: del_key_id, + relationship: DidVerificationKeyRelationship::CapabilityDelegation.into(), + details: del_key_details.clone(), + }); trie_builder .insert(del_leaf.encoded_key().as_slice(), del_leaf.encoded_value().as_slice()) .map_err(|_| { @@ -180,10 +182,11 @@ pub mod v0 { log::error!("Key agreement key should be part of the public keys."); DidMerkleProofError::Internal })?; - let enc_leaf = ProofLeafOf::::DidKey( - (*id, DidKeyRelationship::Encryption).into(), - key_agreement_details.clone().into(), - ); + let enc_leaf = ProofLeafOf::::from(RevealedDidKey { + id: *id, + relationship: DidKeyRelationship::Encryption, + details: key_agreement_details.clone(), + }); trie_builder .insert(enc_leaf.encoded_key().as_slice(), enc_leaf.encoded_value().as_slice()) .map_err(|_| { @@ -200,8 +203,7 @@ pub mod v0 { linked_accounts .iter() .try_for_each(|linked_account| -> Result<(), DidMerkleProofError> { - let linked_account_leaf = - ProofLeafOf::::LinkedAccount(linked_account.clone().into(), ().into()); + let linked_account_leaf = ProofLeafOf::::from(RevealedAccountId(linked_account.clone())); trie_builder .insert( linked_account_leaf.encoded_key().as_slice(), @@ -219,10 +221,10 @@ pub mod v0 { // Web3name, if present if let Some(web3name_details) = web3_name_details { - let web3_name_leaf = ProofLeafOf::::Web3Name( - web3name_details.web3_name.clone().into(), - web3name_details.claimed_at.into(), - ); + let web3_name_leaf = ProofLeafOf::::from(RevealedWeb3Name { + web3_name: web3name_details.web3_name.clone(), + claimed_at: web3name_details.claimed_at, + }); trie_builder .insert( web3_name_leaf.encoded_key().as_slice(), @@ -274,30 +276,27 @@ pub mod v0 { .ok_or(DidMerkleProofError::KeyNotFound)?; // Create the merkle leaf key depending on the relationship of the key to the // DID document. - let did_key_merkle_key: DidKeyMerkleKey> = if *key_id == did_details.authentication_key - { - Ok((*key_id, DidVerificationKeyRelationship::Authentication.into()).into()) + let key_relationship = if *key_id == did_details.authentication_key { + Ok(DidVerificationKeyRelationship::Authentication.into()) } else if Some(*key_id) == did_details.attestation_key { - Ok((*key_id, DidVerificationKeyRelationship::AssertionMethod.into()).into()) + Ok(DidVerificationKeyRelationship::AssertionMethod.into()) } else if Some(*key_id) == did_details.delegation_key { - Ok((*key_id, DidVerificationKeyRelationship::CapabilityDelegation.into()).into()) + Ok(DidVerificationKeyRelationship::CapabilityDelegation.into()) } else if did_details.key_agreement_keys.contains(key_id) { - Ok((*key_id, DidKeyRelationship::Encryption).into()) + Ok(DidKeyRelationship::Encryption) } else { log::error!("Unknown key ID {:#?} retrieved from DID details.", key_id); Err(DidMerkleProofError::Internal) }?; - Ok(RevealedDidMerkleProofLeaf::DidKey( - did_key_merkle_key, - key_details.clone().into(), - )) + Ok(RevealedDidMerkleProofLeaf::from(RevealedDidKey { + id: *key_id, + relationship: key_relationship, + details: key_details.clone(), + })) }) .chain(account_ids.map(|account_id| -> Result<_, DidMerkleProofError> { if linked_accounts.contains(account_id) { - Ok(RevealedDidMerkleProofLeaf::LinkedAccount( - account_id.clone().into(), - ().into(), - )) + Ok(RevealedDidMerkleProofLeaf::from(RevealedAccountId(account_id.clone()))) } else { Err(DidMerkleProofError::LinkedAccountNotFound) } @@ -307,10 +306,10 @@ pub mod v0 { match (should_include_web3_name, web3_name_details) { // If web3name should be included and it exists, add to the leaves to be revealed... (true, Some(web3name_details)) => { - leaves.push(RevealedDidMerkleProofLeaf::Web3Name( - web3name_details.web3_name.clone().into(), - web3name_details.claimed_at.into(), - )); + leaves.push(RevealedDidMerkleProofLeaf::from(RevealedWeb3Name { + web3_name: web3name_details.web3_name.clone(), + claimed_at: web3name_details.claimed_at, + })); } // ...else if web3name should be included and it DOES NOT exist, return an error... (true, None) => return Err(DidMerkleProofError::Web3NameNotFound), From 15253bc14bffd341d4fb53af42cd7c87a1b4a5ba Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Wed, 10 Jan 2024 12:55:46 +0100 Subject: [PATCH 02/45] Refactor merkle proof verification into single function --- .../src/state_proofs/mod.rs | 182 ++++++++---- .../src/state_proofs/parachain.rs | 168 ----------- .../src/state_proofs/relaychain.rs | 261 ------------------ .../src/state_proofs/substrate_no_std_port.rs | 69 +++++ .../src/verifier/parachain.rs | 98 +++---- .../src/verifier/relaychain.rs | 79 +++--- 6 files changed, 291 insertions(+), 566 deletions(-) delete mode 100644 crates/kilt-dip-primitives/src/state_proofs/parachain.rs delete mode 100644 crates/kilt-dip-primitives/src/state_proofs/relaychain.rs create mode 100644 crates/kilt-dip-primitives/src/state_proofs/substrate_no_std_port.rs diff --git a/crates/kilt-dip-primitives/src/state_proofs/mod.rs b/crates/kilt-dip-primitives/src/state_proofs/mod.rs index f21a27b147..0963d7b075 100644 --- a/crates/kilt-dip-primitives/src/state_proofs/mod.rs +++ b/crates/kilt-dip-primitives/src/state_proofs/mod.rs @@ -18,64 +18,146 @@ //! Module to deal with cross-chain state proofs. -/// Parachain-related state proof logic. -pub(crate) mod parachain; -/// Relaychain-related state proof logic. -pub(crate) mod relaychain; +use parity_scale_codec::Decode; +use sp_runtime::traits::Hash; +use sp_std::vec::Vec; +use sp_trie::StorageProof; + +use crate::{state_proofs::substrate_no_std_port::read_proof_check, utils::OutputOf}; // Ported from https://github.com/paritytech/substrate/blob/b27c470eaff379f512d1dec052aff5d551ed3b03/primitives/state-machine/src/lib.rs#L1076 // Needs to be replaced with its runtime-friendly version when available, or be // kept up-to-date with upstream. -mod substrate_no_std_port { - use hash_db::EMPTY_PREFIX; - use parity_scale_codec::Codec; - use sp_core::Hasher; - use sp_state_machine::{Backend, TrieBackend, TrieBackendBuilder}; - use sp_std::{collections::btree_map::BTreeMap, vec::Vec}; - use sp_trie::{HashDBT, MemoryDB, StorageProof}; - - pub(super) fn read_proof_check( - root: H::Out, - proof: StorageProof, - keys: I, - ) -> Result, Option>>, ()> - where - H: Hasher, - H::Out: Ord + Codec, - I: IntoIterator, - I::Item: AsRef<[u8]>, - { - let proving_backend = create_proof_check_backend::(root, proof)?; - let mut result = BTreeMap::new(); - for key in keys.into_iter() { - let value = read_proof_check_on_proving_backend(&proving_backend, key.as_ref())?; - result.insert(key.as_ref().to_vec(), value); +mod substrate_no_std_port; + +#[derive(Debug)] +pub enum MerkleProofError { + InvalidProof, + RequiredLeafNotRevealed, + ResultDecoding, +} + +impl From for u8 { + fn from(value: MerkleProofError) -> Self { + match value { + MerkleProofError::InvalidProof => 0, + MerkleProofError::RequiredLeafNotRevealed => 1, + MerkleProofError::ResultDecoding => 2, } - Ok(result) } +} + +/// Verify a Merkle-based storage proof for a given storage key according to the +/// provided state root. The generic types indicate the following: +/// * `StorageKey`: defines the type of the storage key included in the proof. +/// * `MerkleHasher`: defines the hashing algorithm used to calculate the Merkle +/// root. +/// * `Success`: defines the type expected to be revealed in a valid Merkle +/// proof. +pub fn verify_storage_value_proof( + storage_key: &StorageKey, + state_root: OutputOf, + state_proof: impl IntoIterator>, +) -> Result +where + StorageKey: AsRef<[u8]>, + MerkleHasher: Hash, + OutputOf: Ord, + Success: Decode, +{ + let storage_proof = StorageProof::new(state_proof); + let revealed_leaves = read_proof_check::(state_root, storage_proof, [storage_key].iter()) + .map_err(|_| MerkleProofError::InvalidProof)?; + + #[cfg(feature)] - fn read_proof_check_on_proving_backend( - proving_backend: &TrieBackend, H>, - key: &[u8], - ) -> Result>, ()> - where - H: Hasher, - H::Out: Ord + Codec, - { - proving_backend.storage(key).map_err(|_| ()) + debug_assert!( + revealed_leaves.len() == 1usize, + "Only a single leaf is expected to be revealed in the storage proof." + ); + debug_assert!( + revealed_leaves.contains_key(storage_key.as_ref()), + "Proof does not include the expected storage key." + ); + + let Some(Some(encoded_revealed_leaf)) = revealed_leaves.get(storage_key.as_ref()) else { + return Err(MerkleProofError::RequiredLeafNotRevealed); + }; + + Success::decode(&mut &encoded_revealed_leaf[..]).map_err(|_| MerkleProofError::ResultDecoding) +} + +#[cfg(test)] +mod test { + use cumulus_primitives_core::relay_chain::HeadData; + use hex_literal::hex; + use parity_scale_codec::Encode; + use sp_core::{storage::StorageKey, H256}; + use sp_runtime::traits::BlakeTwo256; + + use crate::state_proofs::verify_storage_value_proof; + + #[test] + fn spiritnet_system_event_count() { + // As of RPC state_getReadProof(" + // 0x26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850", + // "0x2c0746e7e9ccc6e4d27bcb4118cb6821ae53ae9bf372f4f49ac28d8598f9bed5") + let events_count_storage_key = + StorageKey(frame_support::storage::storage_prefix(b"System", b"EventCount").to_vec()); + let spiritnet_event_count_proof_at_block = [ + hex!("800404645ea5c1b19ab7a04f536c519aca4983ac205cda3f0000000000545e98fdbe9ce6c55837576c60c7af38501005000000").to_vec(), + hex!("80401080481e2bd8085a02c5b58987bce7a69f0b5c7fa651e8e82c5481c94707860be9078067785103d453293707ba847e21df7e35a7a57b8fb929d40465328b6642669fcc").to_vec(), + hex!("80ffff8010623b5a3a9dbc752963d827be0bb855bf3e24258ae09341d5f762e96a836ac180c34b753605e821528756b55b4ddafb742df6e54fbc03ef401d4ebfd6dd4f3e44806f83646e0bf3ca0ac9f2092dea5b0e3caf210cc6b54c3b44a51855a133367a6580b02cde7b1fd3f8d13f698ef6e9daa29b32258d4d97a8947051070a4540aecacd80903d521961849d07ceee132617b8dde96c3ff472f5a9a089d4055ffe7ffd1e988016c29c943c106713bb8f16b776eb7daed005540165696da286cddf6b25d085448019a464010cb746b0589891f72b0eed603d4712b04af46f7bcae724564194801480a305ffe069db7eb21841f75b5939943f62c4abb3a051d530839c5dd935ccbc8a8035d8938b0c856878de1e3fe45a559588b2da52ccf195ab1e3d0aca6ac7bb079d8064019a474a283c19f46ff4652a5e1f636efd4013d3b8a91c49573045c6ff01c0801a191dcb736faddb84889a13c7aa717d260e9b635b30a9eb3907f925a2253d6880f8bc389fc62ca951609bae208b7506bae497623e647424062d1c56cb1f2d2e1c80211a9fb5f8b794f9fbfbdcd4519aa475ecaf9737b4ee513dde275d5fbbe64da080c267d0ead99634e9b9cfbf61a583877e0241ac518e62e909fbb017469de275f780b3059a7226d4b320c25e9b2f8ffe19cf93467e3b306885962c5f34b5671d15fe8092dfba9e30e1bbefab13c792755d06927e6141f7220b7485e5aa40de92401a66").to_vec(), + hex!("9eaa394eea5630e07c48ae0c9558cef7398f8069ef420a0deb5a428c9a08563b28a78874bba09124eecc8d28bf30b0e2ddd310745f04abf5cb34d6244378cddbf18e849d962c000000000736d8e8140100505f0e7b9012096b41c4eb3aaf947f6ea4290800004c5f0684a022a34dd8bfa2baaf44f172b710040180dd3270a03a1a13fc20bcdf24d1aa4ddccc6183db2e2e153b8a68ba8540699a8a80b413dad63538a591f7f2575d287520ee44d7143aa5ec2411969861e1f55a2989804c3f0f541a13980689894db7c60c785dd29e066f213bb29b17aa740682ad7efd8026d3a50544f5c89500745aca2be36cfe076f599c5115192fb9deae227e2710c980bd04b00bf6b42756a06a4fbf05a5231c2094e48182eca95d2cff73ab907592aa").to_vec(), + ].to_vec(); + let spiritnet_state_root: H256 = + hex!("94c23fda279cea4a4370e90f1544c8938923dfd4ac201a420c7a26fb0d3caf8c").into(); + // As of query system::eventCount() at block + // "0x2c0746e7e9ccc6e4d27bcb4118cb6821ae53ae9bf372f4f49ac28d8598f9bed5" which + // results in the key + // "0x26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850" + let expected_event_count_at_block = 5u32; + let event_count_at_block = verify_storage_value_proof::<_, BlakeTwo256, u32>( + &events_count_storage_key, + spiritnet_state_root, + spiritnet_event_count_proof_at_block, + ) + .expect("Merkle proof verification for pre-calculated Spiritnet storage entry should not fail."); + assert_eq!(expected_event_count_at_block, event_count_at_block); } - fn create_proof_check_backend(root: H::Out, proof: StorageProof) -> Result, H>, ()> - where - H: Hasher, - H::Out: Codec, - { - let db = proof.into_memory_db(); - - if db.contains(&root, EMPTY_PREFIX) { - Ok(TrieBackendBuilder::new(db, root).build()) - } else { - Err(()) - } + #[test] + fn polkadot_parahead_proof_for_spiritnet() { + // As of RPC state_getReadProof("0xcd710b30bd2eab0352ddcc26417aa1941b3c252fcb29d88eff4f3de5de4476c32c0cfd6c23b92a7826080000", "0x18e90e9aa8e3b063f60386ba1b0415111798e72d01de58b1438d620d42f58e39") + let spiritnet_head_storage_key = StorageKey( + [ + frame_support::storage::storage_prefix(b"Paras", b"Heads").as_slice(), + sp_io::hashing::twox_64(2_086u32.encode().as_ref()).as_slice(), + 2_086u32.encode().as_slice(), + ] + .concat(), + ); + let spiritnet_head_proof_at_block = [ + hex!("570c0cfd6c23b92a7826080000f102e90265541097fb02782e14f43074f0b00e44ae8e9fe426982323ef1d329739740d37f252ff006d1156941db1bccd58ce3a1cac4f40cad91f692d94e98f501dd70081a129b69a3e2ef7e1ff84ba3d86dab4e95f2c87f6b1055ebd48519c185360eae58f05d1ea08066175726120dcdc6308000000000561757261010170ccfaf3756d1a8dd8ae5c89094199d6d32e5dd9f0920f6fe30f986815b5e701974ea0e0e0a901401f2c72e3dd8dbdf4aa55d59bf3e7021856cdb8038419eb8c").to_vec(), + hex!("80046480186b1513c5112466ada33da3c65558979906ca9fb82510b62f6ea01f550a4807808bc90ded5636f31c8395a315b5f27a1a25a2ceebd36921a518669ce7e52f80e680993c5e952e6e4f72f295ba04951ace9029b23e9a87887b41895c16f77bec42ee80b798b224c5ee3d668519e75ca98504116f645fb969a5e2653a298b0181f9a694").to_vec(), + hex!("80ffff806ecd86e87715a007ee9b216d8a99a604773014260d51f6552b6fbd7c21786d9c80e23ef51809d6c80c01a6e264ff0d298cce01c1addfdbb0789597b9a6b3f3e4fd80c9c5f0f29d777e2cebcdbd06ddf1c2cfa8ee83524b37ace99d8b7a3aeff039b380da013185503cfefa6c9cc88751993f1f2bf4b8fa4918e876f499fb9405e3206c803a89668f636552a0fb93619913dcc46cf3e087363d532b76a345155a44a46b5180c2e7fc654720b7dcc0316ae1591fde4beb8b853a343b7e5e3ee564d2692c2ee280840f9c4ae7c16ae948828bf50faf062264402e6134d2d6144a5e3ecb0a1e1d9c80f93c2be1ef51fb2032445cc7fbc2023b9e3b8cf8c0d832b464ae48a020bfaa8c8010c63537c9bf58d50c8c0e13c154fd88b2f683e13701901bdc64565aa9b756d580f0b60eaf17fb680827e8a8938c717ac943b85ff373c0fc911e06c34a3a30327280ccb29f1efa59fd7c80a730cb88789a5a256b01fee7e83ac9a3c90da330adc7a480c8e57c547edb33d4b712f017f09d2de2e055f18815669c83eef2f7f3e5dcafae80b7b7e7ffc91a7dd4c4902f7f15cd7598d1258a75433ea953565661d114e2dcca80ebc3a2df819c7c2fd1a33eb1d484beaf7b71114d6a6db240d8b07dc10bfdc49b80a71f21aa3fa5d7475bf134d50f25e2515c797d0a4c2e93998888150c1f969ab8801e32613f54e70c95e9b16a14f5797522ef5e2ef7867868ff663e33e8880994ed").to_vec(), + hex!("9e710b30bd2eab0352ddcc26417aa1945fd380d49ebc7ca5c1b751c2badb5e5a326d3ba9e331d8b7c6cf279ed7fd71a8882b6c8038088652f73dc8a22336d10f492f0ef8836beaba0ccfeb0f8fabdc9df1d17e2d807f88402cbbed7fa3307e07044200b572d5e8e12913b41e1923dcb2c0799bc2be804d57e9a8e4934fab698a9db50682052ee9459c666a075d1bfc471da8e5da14da80b9aee043e378f8313e68a6030679ccf3880fa1e7ab19b6244b5c262b7a152f004c5f03c716fb8fff3de61a883bb76adb34a2040080f282bc12648ffb197ffc257edc7ff3a3fdda452daa51091ccbd2dfb91d8aa9518008a0c609ab4888f02c2545c002153297c2641c5a7b4f3d8e25c634e721f80bea80b6617c764df278313c426c46961ccde8ee7a03f9007b74bc8bc6c49d1583cf7d8077b493d45eb153353026cc330307e0753ac41a5cb8e843ceb1efdc46655f33a0808bdaa43fc5dc0e928e2da0ce8ed02096b0b74c61feaba2546980ed9c6174f71d").to_vec(), + hex!("9f0b3c252fcb29d88eff4f3de5de4476c3ffbf8013c601cc93de3437f9d415bd52c48d794b341f218b9d0020a4b646746c24d0ca80348b8e2c39c479a146933297f62b7051df82e92e1bca761432c3e6f64c74033f80220131e7cd7a08b97f8aa06225f7aefbbca8118fb436c07689c552ed3f577145806d974dd9e4db5e407e29f84c4121ccc58f9c6adc3933afc1bcaef52defe77de5801e9e1a21db053de56365fdee57998488ddae7d664c0430da90469dde17936c1f80c5c11751bbfc99a1ad805c58a65b9704e0bad58e694023e9cc57ce6ef84cdb0b8038f6c242700eaea04ffad5c25ca9a9b1cc2af7303655a32eb59e84b6bb927cd3802575469e76e104b0db8b18dbc762b997a78aa666432a44c4b955ced044a4691f80a81408b856272feeec08845af515e27d033efd3ff8b46de6bc706c38e600086a809ee78332c2a38a3918070942421e651e0b9a43e4b8b2c92e87a2552cede73e8380c9d79f411f742cad0c6f2b070aa08703a04cb7db840c3821a6762837dd8d00e9807dcfbc7f2fcc9415e2cb40eef7f718758d76193f325b3f8b7180e3e5e7d6b81e8036252cae6d24a531a151ce1ee223a07bf71cf82a7fdf49090e4ca345d27d68ca80e3f08ef11671f8f1defa66fa2af71e1a871430e9352df9b3f1d427b5a5dabfb280b51d28c9b99030d050fc1578cd23b5506e769b86c8f4ccc6aded4b8d7c1a73b7").to_vec(), + ].to_vec(); + let polkadot_state_root: H256 = hex!("81b75d95075d16005ee0a987a3f061d3011ada919b261e9b02961b9b3725f3fd").into(); + // As of query paras::heads(2_086) at block + // "0x18e90e9aa8e3b063f60386ba1b0415111798e72d01de58b1438d620d42f58e39" + // (16_363_919) which results in the key + // "0xcd710b30bd2eab0352ddcc26417aa1941b3c252fcb29d88eff4f3de5de4476c32c0cfd6c23b92a7826080000" + let expected_spiritnet_head_at_block = hex!("65541097fb02782e14f43074f0b00e44ae8e9fe426982323ef1d329739740d37f252ff006d1156941db1bccd58ce3a1cac4f40cad91f692d94e98f501dd70081a129b69a3e2ef7e1ff84ba3d86dab4e95f2c87f6b1055ebd48519c185360eae58f05d1ea08066175726120dcdc6308000000000561757261010170ccfaf3756d1a8dd8ae5c89094199d6d32e5dd9f0920f6fe30f986815b5e701974ea0e0e0a901401f2c72e3dd8dbdf4aa55d59bf3e7021856cdb8038419eb8c").to_vec(); + let spiritnet_head_at_block = verify_storage_value_proof::<_, BlakeTwo256, HeadData>( + &spiritnet_head_storage_key, + polkadot_state_root, + spiritnet_head_proof_at_block, + ) + .expect( + "Merkle proof verification for pre-calculated Polkadot storage entry for Spiritnet head should not fail.", + ); + assert_eq!(expected_spiritnet_head_at_block, spiritnet_head_at_block.0); } } diff --git a/crates/kilt-dip-primitives/src/state_proofs/parachain.rs b/crates/kilt-dip-primitives/src/state_proofs/parachain.rs deleted file mode 100644 index 3ad51695f0..0000000000 --- a/crates/kilt-dip-primitives/src/state_proofs/parachain.rs +++ /dev/null @@ -1,168 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 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 parity_scale_codec::Decode; -use sp_core::RuntimeDebug; -use sp_std::marker::PhantomData; -use sp_trie::StorageProof; - -use crate::{ - state_proofs::substrate_no_std_port::read_proof_check, traits::ProviderParachainStorageInfo, utils::OutputOf, -}; - -#[derive(RuntimeDebug)] -pub enum DipIdentityCommitmentProofVerifierError { - InvalidMerkleProof, - RequiredLeafNotRevealed, - CommitmentDecode, -} - -impl From for u8 { - fn from(value: DipIdentityCommitmentProofVerifierError) -> Self { - match value { - DipIdentityCommitmentProofVerifierError::InvalidMerkleProof => 0, - DipIdentityCommitmentProofVerifierError::RequiredLeafNotRevealed => 1, - DipIdentityCommitmentProofVerifierError::CommitmentDecode => 2, - } - } -} - -/// Verifier of state proofs that reveal the value of the DIP commitment for -/// a given subject on the provider chain. The generic types indicate the -/// following: -/// * `ParaInfo`: defines the provider parachain runtime types relevant for -/// state proof verification, and returns the provider's runtime storage key -/// identifying the identity commitment for a subject with the given -/// identifier. -pub struct DipIdentityCommitmentProofVerifier(PhantomData); - -impl DipIdentityCommitmentProofVerifier -where - ParaInfo: ProviderParachainStorageInfo, - OutputOf: Ord, - ParaInfo::Commitment: Decode, - ParaInfo::Key: AsRef<[u8]>, -{ - /// Given a parachain state root, verify a state proof for the - /// commitment of a given subject identifier. - #[cfg(not(feature = "runtime-benchmarks"))] - pub fn verify_proof_for_identifier( - identifier: &ParaInfo::Identifier, - state_root: OutputOf, - proof: impl IntoIterator>, - ) -> Result { - let dip_commitment_storage_key = ParaInfo::dip_subject_storage_key(identifier, 0); - let storage_proof = StorageProof::new(proof); - let revealed_leaves = - read_proof_check::(state_root, storage_proof, [&dip_commitment_storage_key].iter()) - .map_err(|_| DipIdentityCommitmentProofVerifierError::InvalidMerkleProof)?; - // TODO: Remove at some point - { - debug_assert!(revealed_leaves.len() == 1usize); - debug_assert!(revealed_leaves.contains_key(dip_commitment_storage_key.as_ref())); - } - let Some(Some(encoded_commitment)) = revealed_leaves.get(dip_commitment_storage_key.as_ref()) else { - return Err(DipIdentityCommitmentProofVerifierError::RequiredLeafNotRevealed); - }; - ParaInfo::Commitment::decode(&mut &encoded_commitment[..]) - .map_err(|_| DipIdentityCommitmentProofVerifierError::CommitmentDecode) - } - - #[cfg(feature = "runtime-benchmarks")] - pub fn verify_proof_for_identifier( - identifier: &ParaInfo::Identifier, - state_root: OutputOf, - proof: impl IntoIterator>, - ) -> Result - where - ParaInfo::Commitment: Default, - { - let dip_commitment_storage_key = ParaInfo::dip_subject_storage_key(identifier, 0); - let storage_proof = StorageProof::new(proof); - let revealed_leaves = - read_proof_check::(state_root, storage_proof, [&dip_commitment_storage_key].iter()) - .unwrap_or_default(); - let encoded_commitment = - if let Some(Some(encoded_commitment)) = revealed_leaves.get(dip_commitment_storage_key.as_ref()) { - encoded_commitment.clone() - } else { - sp_std::vec::Vec::default() - }; - let commitment = ParaInfo::Commitment::decode(&mut &encoded_commitment[..]).unwrap_or_default(); - Ok(commitment) - } -} - -#[cfg(test)] -mod spiritnet_test_event_count_value { - use super::*; - - use hex_literal::hex; - use pallet_dip_provider::IdentityCommitmentVersion; - use sp_core::{storage::StorageKey, H256}; - use sp_runtime::traits::BlakeTwo256; - - // Spiritnet block n: 4_184_668, - // hash 0x2c0746e7e9ccc6e4d27bcb4118cb6821ae53ae9bf372f4f49ac28d8598f9bed5 - struct StaticSpiritnetInfoProvider; - - // We use the `system::eventCount()` storage entry as a unit test here. - impl ProviderParachainStorageInfo for StaticSpiritnetInfoProvider { - type BlockNumber = u32; - // The type of the `eventCount()` storage entry. - type Commitment = u32; - type Hasher = BlakeTwo256; - // Irrelevant for this test here - type Identifier = (); - type Key = StorageKey; - - fn dip_subject_storage_key(_identifier: &Self::Identifier, _version: IdentityCommitmentVersion) -> Self::Key { - // system::eventCount() raw storage key - let storage_key = hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec(); - StorageKey(storage_key) - } - } - - #[test] - fn test_spiritnet_event_count() { - // As of RPC state_getReadProof(" - // 0x26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850", - // "0x2c0746e7e9ccc6e4d27bcb4118cb6821ae53ae9bf372f4f49ac28d8598f9bed5") - let spiritnet_event_count_proof_at_block = [ - hex!("800404645ea5c1b19ab7a04f536c519aca4983ac205cda3f0000000000545e98fdbe9ce6c55837576c60c7af38501005000000").to_vec(), - hex!("80401080481e2bd8085a02c5b58987bce7a69f0b5c7fa651e8e82c5481c94707860be9078067785103d453293707ba847e21df7e35a7a57b8fb929d40465328b6642669fcc").to_vec(), - hex!("80ffff8010623b5a3a9dbc752963d827be0bb855bf3e24258ae09341d5f762e96a836ac180c34b753605e821528756b55b4ddafb742df6e54fbc03ef401d4ebfd6dd4f3e44806f83646e0bf3ca0ac9f2092dea5b0e3caf210cc6b54c3b44a51855a133367a6580b02cde7b1fd3f8d13f698ef6e9daa29b32258d4d97a8947051070a4540aecacd80903d521961849d07ceee132617b8dde96c3ff472f5a9a089d4055ffe7ffd1e988016c29c943c106713bb8f16b776eb7daed005540165696da286cddf6b25d085448019a464010cb746b0589891f72b0eed603d4712b04af46f7bcae724564194801480a305ffe069db7eb21841f75b5939943f62c4abb3a051d530839c5dd935ccbc8a8035d8938b0c856878de1e3fe45a559588b2da52ccf195ab1e3d0aca6ac7bb079d8064019a474a283c19f46ff4652a5e1f636efd4013d3b8a91c49573045c6ff01c0801a191dcb736faddb84889a13c7aa717d260e9b635b30a9eb3907f925a2253d6880f8bc389fc62ca951609bae208b7506bae497623e647424062d1c56cb1f2d2e1c80211a9fb5f8b794f9fbfbdcd4519aa475ecaf9737b4ee513dde275d5fbbe64da080c267d0ead99634e9b9cfbf61a583877e0241ac518e62e909fbb017469de275f780b3059a7226d4b320c25e9b2f8ffe19cf93467e3b306885962c5f34b5671d15fe8092dfba9e30e1bbefab13c792755d06927e6141f7220b7485e5aa40de92401a66").to_vec(), - hex!("9eaa394eea5630e07c48ae0c9558cef7398f8069ef420a0deb5a428c9a08563b28a78874bba09124eecc8d28bf30b0e2ddd310745f04abf5cb34d6244378cddbf18e849d962c000000000736d8e8140100505f0e7b9012096b41c4eb3aaf947f6ea4290800004c5f0684a022a34dd8bfa2baaf44f172b710040180dd3270a03a1a13fc20bcdf24d1aa4ddccc6183db2e2e153b8a68ba8540699a8a80b413dad63538a591f7f2575d287520ee44d7143aa5ec2411969861e1f55a2989804c3f0f541a13980689894db7c60c785dd29e066f213bb29b17aa740682ad7efd8026d3a50544f5c89500745aca2be36cfe076f599c5115192fb9deae227e2710c980bd04b00bf6b42756a06a4fbf05a5231c2094e48182eca95d2cff73ab907592aa").to_vec(), - ].to_vec(); - let spiritnet_state_root: H256 = - hex!("94c23fda279cea4a4370e90f1544c8938923dfd4ac201a420c7a26fb0d3caf8c").into(); - // As of query system::eventCount() at block - // "0x2c0746e7e9ccc6e4d27bcb4118cb6821ae53ae9bf372f4f49ac28d8598f9bed5" which - // results in the key - // "0x26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850" - let expected_event_count_at_block = 5; - let returned_event_count = - DipIdentityCommitmentProofVerifier::::verify_proof_for_identifier( - &(), - spiritnet_state_root, - spiritnet_event_count_proof_at_block, - ) - .unwrap(); - assert!(returned_event_count == expected_event_count_at_block, "Spiritnet event count returned from the state proof verification should not be different than the pre-computed one."); - } -} diff --git a/crates/kilt-dip-primitives/src/state_proofs/relaychain.rs b/crates/kilt-dip-primitives/src/state_proofs/relaychain.rs deleted file mode 100644 index 018b98481b..0000000000 --- a/crates/kilt-dip-primitives/src/state_proofs/relaychain.rs +++ /dev/null @@ -1,261 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 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 parity_scale_codec::{Encode, HasCompact}; -use sp_core::{storage::StorageKey, RuntimeDebug, U256}; -use sp_runtime::{generic::Header, traits::BlakeTwo256}; -use sp_std::{marker::PhantomData, vec::Vec}; -use sp_trie::StorageProof; - -use crate::{ - state_proofs::substrate_no_std_port::read_proof_check, - traits::{RelayChainStateInfo, RelayChainStorageInfo}, - utils::OutputOf, -}; - -#[derive(RuntimeDebug)] -pub enum ParachainHeadProofVerifierError { - InvalidMerkleProof, - RequiredLeafNotRevealed, - HeaderDecode, - RelaychainStateRootNotFound, -} - -impl From for u8 { - fn from(value: ParachainHeadProofVerifierError) -> Self { - match value { - ParachainHeadProofVerifierError::InvalidMerkleProof => 0, - ParachainHeadProofVerifierError::RequiredLeafNotRevealed => 1, - ParachainHeadProofVerifierError::HeaderDecode => 2, - ParachainHeadProofVerifierError::RelaychainStateRootNotFound => 3, - } - } -} - -/// Verifier of state proofs that reveal the value of a parachain head at a -/// given relaychain block number. -/// The generic types are the following: -/// * `RelayChainState`: defines the relaychain runtime types relevant for state -/// proof verification, and returns the relaychain runtime's storage key -/// identifying a parachain with a given ID. -pub struct ParachainHeadProofVerifier(PhantomData); - -// Uses the provided `root` to verify the proof. -impl ParachainHeadProofVerifier -where - RelayChainState: RelayChainStorageInfo, - OutputOf: Ord, - RelayChainState::BlockNumber: Copy + Into + TryFrom + HasCompact, - RelayChainState::Key: AsRef<[u8]>, -{ - /// Given a relaychain state root, verify a state proof for the - /// parachain with the provided ID. - #[cfg(not(feature = "runtime-benchmarks"))] - pub fn verify_proof_for_parachain_with_root( - para_id: &RelayChainState::ParaId, - root: &OutputOf<::Hasher>, - proof: impl IntoIterator>, - ) -> Result, ParachainHeadProofVerifierError> { - use parity_scale_codec::Decode; - - let parachain_storage_key = RelayChainState::parachain_head_storage_key(para_id); - let storage_proof = StorageProof::new(proof); - let revealed_leaves = - read_proof_check::(*root, storage_proof, [¶chain_storage_key].iter()) - .map_err(|_| ParachainHeadProofVerifierError::InvalidMerkleProof)?; - // TODO: Remove at some point - { - debug_assert!(revealed_leaves.len() == 1usize); - debug_assert!(revealed_leaves.contains_key(parachain_storage_key.as_ref())); - } - let Some(Some(encoded_head)) = revealed_leaves.get(parachain_storage_key.as_ref()) else { - return Err(ParachainHeadProofVerifierError::RequiredLeafNotRevealed); - }; - // TODO: Figure out why RPC call returns 2 bytes in front which we don't need - let mut unwrapped_head = &encoded_head[2..]; - Header::decode(&mut unwrapped_head).map_err(|_| ParachainHeadProofVerifierError::HeaderDecode) - } - - // Ignores any errors returned by the `read_proof_check` function and returns a - // default Header in case of failure. - #[cfg(feature = "runtime-benchmarks")] - pub fn verify_proof_for_parachain_with_root( - para_id: &RelayChainState::ParaId, - root: &OutputOf<::Hasher>, - proof: impl IntoIterator>, - ) -> Result, ParachainHeadProofVerifierError> { - use parity_scale_codec::Decode; - - let parachain_storage_key = RelayChainState::parachain_head_storage_key(para_id); - let storage_proof = StorageProof::new(proof); - let revealed_leaves = - read_proof_check::(*root, storage_proof, [¶chain_storage_key].iter()) - .unwrap_or_default(); - let encoded_head = if let Some(Some(encoded_head)) = revealed_leaves.get(parachain_storage_key.as_ref()) { - encoded_head.clone() - } else { - sp_std::vec![0u8; 3] - }; - let mut unwrapped_head = &encoded_head[2..]; - let header = Header::decode(&mut unwrapped_head).unwrap_or(Header { - number: U256::from(0u64) - .try_into() - .map_err(|_| "Block number should be created from a u64") - .unwrap(), - digest: Default::default(), - extrinsics_root: Default::default(), - parent_hash: Default::default(), - state_root: Default::default(), - }); - Ok(header) - } - - /// Given a relaychain state root provided by the `RelayChainState` - /// generic type, verify a state proof for the parachain with the - /// provided ID. - #[cfg(not(feature = "runtime-benchmarks"))] - pub fn verify_proof_for_parachain( - para_id: &RelayChainState::ParaId, - relay_height: &RelayChainState::BlockNumber, - proof: impl IntoIterator>, - ) -> Result, ParachainHeadProofVerifierError> - where - RelayChainState: RelayChainStateInfo, - { - let relay_state_root = RelayChainState::state_root_for_block(relay_height) - .ok_or(ParachainHeadProofVerifierError::RelaychainStateRootNotFound)?; - Self::verify_proof_for_parachain_with_root(para_id, &relay_state_root, proof) - } - - #[cfg(feature = "runtime-benchmarks")] - pub fn verify_proof_for_parachain( - para_id: &RelayChainState::ParaId, - relay_height: &RelayChainState::BlockNumber, - proof: impl IntoIterator>, - ) -> Result, ParachainHeadProofVerifierError> - where - RelayChainState: RelayChainStateInfo, - { - let relay_state_root = RelayChainState::state_root_for_block(relay_height).unwrap_or_default(); - Self::verify_proof_for_parachain_with_root(para_id, &relay_state_root, proof) - } -} - -/// Implementor of the [`RelayChainStorageInfo`] trait that return the state -/// root of a relaychain block with a given number by retrieving it from the -/// [`pallet_relay_store::Pallet`] pallet storage. It hardcodes the -/// relaychain `BlockNumber`, `Hasher`, `StorageKey`, and `ParaId` to the -/// ones used by Polkadot-based relaychains. This type cannot be used with -/// relaychains that adopt a different definition for any on those types. -pub struct RelayStateRootsViaRelayStorePallet(PhantomData); - -impl RelayChainStorageInfo for RelayStateRootsViaRelayStorePallet -where - Runtime: pallet_relay_store::Config, -{ - type BlockNumber = u32; - type Hasher = BlakeTwo256; - type Key = StorageKey; - type ParaId = u32; - - fn parachain_head_storage_key(para_id: &Self::ParaId) -> Self::Key { - // TODO: Access the runtime definition from here, once and if exposed. - let encoded_para_id = para_id.encode(); - let storage_key = [ - frame_support::storage::storage_prefix(b"Paras", b"Heads").as_slice(), - sp_io::hashing::twox_64(&encoded_para_id).as_slice(), - encoded_para_id.as_slice(), - ] - .concat(); - StorageKey(storage_key) - } -} - -impl RelayChainStateInfo for RelayStateRootsViaRelayStorePallet -where - Runtime: pallet_relay_store::Config, -{ - fn state_root_for_block(block_height: &Self::BlockNumber) -> Option> { - pallet_relay_store::Pallet::::latest_relay_head_for_block(block_height) - .map(|relay_header| relay_header.relay_parent_storage_root) - } -} - -#[cfg(test)] -mod polkadot_parachain_head_proof_verifier_tests { - use super::*; - - use hex_literal::hex; - use sp_runtime::traits::BlakeTwo256; - - // Polkadot block n: 16_363_919, - // hash 0x18e90e9aa8e3b063f60386ba1b0415111798e72d01de58b1438d620d42f58e39 - struct StaticPolkadotInfoProvider; - - impl RelayChainStorageInfo for StaticPolkadotInfoProvider { - type BlockNumber = u32; - type Hasher = BlakeTwo256; - type Key = StorageKey; - type ParaId = u32; - - fn parachain_head_storage_key(para_id: &Self::ParaId) -> Self::Key { - // Adapted from https://github.com/polytope-labs/substrate-ismp/blob/7fb09da6c7b818a98c25c962fee0ddde8e737306/parachain/src/consensus.rs#L369 - // Used for testing. In production this would be generated from the relay - // runtime definition of the `paras` storage map. - let encoded_para_id = para_id.encode(); - let storage_key = [ - frame_support::storage::storage_prefix(b"Paras", b"Heads").as_slice(), - sp_io::hashing::twox_64(&encoded_para_id).as_slice(), - encoded_para_id.as_slice(), - ] - .concat(); - StorageKey(storage_key) - } - } - - impl RelayChainStateInfo for StaticPolkadotInfoProvider { - fn state_root_for_block(_block_height: &Self::BlockNumber) -> Option> { - Some(hex!("81b75d95075d16005ee0a987a3f061d3011ada919b261e9b02961b9b3725f3fd").into()) - } - } - - #[test] - fn test_spiritnet_head_proof() { - // As of RPC state_getReadProof("0xcd710b30bd2eab0352ddcc26417aa1941b3c252fcb29d88eff4f3de5de4476c32c0cfd6c23b92a7826080000", "0x18e90e9aa8e3b063f60386ba1b0415111798e72d01de58b1438d620d42f58e39") - let spiritnet_head_proof_at_block = [ - hex!("570c0cfd6c23b92a7826080000f102e90265541097fb02782e14f43074f0b00e44ae8e9fe426982323ef1d329739740d37f252ff006d1156941db1bccd58ce3a1cac4f40cad91f692d94e98f501dd70081a129b69a3e2ef7e1ff84ba3d86dab4e95f2c87f6b1055ebd48519c185360eae58f05d1ea08066175726120dcdc6308000000000561757261010170ccfaf3756d1a8dd8ae5c89094199d6d32e5dd9f0920f6fe30f986815b5e701974ea0e0e0a901401f2c72e3dd8dbdf4aa55d59bf3e7021856cdb8038419eb8c").to_vec(), - hex!("80046480186b1513c5112466ada33da3c65558979906ca9fb82510b62f6ea01f550a4807808bc90ded5636f31c8395a315b5f27a1a25a2ceebd36921a518669ce7e52f80e680993c5e952e6e4f72f295ba04951ace9029b23e9a87887b41895c16f77bec42ee80b798b224c5ee3d668519e75ca98504116f645fb969a5e2653a298b0181f9a694").to_vec(), - hex!("80ffff806ecd86e87715a007ee9b216d8a99a604773014260d51f6552b6fbd7c21786d9c80e23ef51809d6c80c01a6e264ff0d298cce01c1addfdbb0789597b9a6b3f3e4fd80c9c5f0f29d777e2cebcdbd06ddf1c2cfa8ee83524b37ace99d8b7a3aeff039b380da013185503cfefa6c9cc88751993f1f2bf4b8fa4918e876f499fb9405e3206c803a89668f636552a0fb93619913dcc46cf3e087363d532b76a345155a44a46b5180c2e7fc654720b7dcc0316ae1591fde4beb8b853a343b7e5e3ee564d2692c2ee280840f9c4ae7c16ae948828bf50faf062264402e6134d2d6144a5e3ecb0a1e1d9c80f93c2be1ef51fb2032445cc7fbc2023b9e3b8cf8c0d832b464ae48a020bfaa8c8010c63537c9bf58d50c8c0e13c154fd88b2f683e13701901bdc64565aa9b756d580f0b60eaf17fb680827e8a8938c717ac943b85ff373c0fc911e06c34a3a30327280ccb29f1efa59fd7c80a730cb88789a5a256b01fee7e83ac9a3c90da330adc7a480c8e57c547edb33d4b712f017f09d2de2e055f18815669c83eef2f7f3e5dcafae80b7b7e7ffc91a7dd4c4902f7f15cd7598d1258a75433ea953565661d114e2dcca80ebc3a2df819c7c2fd1a33eb1d484beaf7b71114d6a6db240d8b07dc10bfdc49b80a71f21aa3fa5d7475bf134d50f25e2515c797d0a4c2e93998888150c1f969ab8801e32613f54e70c95e9b16a14f5797522ef5e2ef7867868ff663e33e8880994ed").to_vec(), - hex!("9e710b30bd2eab0352ddcc26417aa1945fd380d49ebc7ca5c1b751c2badb5e5a326d3ba9e331d8b7c6cf279ed7fd71a8882b6c8038088652f73dc8a22336d10f492f0ef8836beaba0ccfeb0f8fabdc9df1d17e2d807f88402cbbed7fa3307e07044200b572d5e8e12913b41e1923dcb2c0799bc2be804d57e9a8e4934fab698a9db50682052ee9459c666a075d1bfc471da8e5da14da80b9aee043e378f8313e68a6030679ccf3880fa1e7ab19b6244b5c262b7a152f004c5f03c716fb8fff3de61a883bb76adb34a2040080f282bc12648ffb197ffc257edc7ff3a3fdda452daa51091ccbd2dfb91d8aa9518008a0c609ab4888f02c2545c002153297c2641c5a7b4f3d8e25c634e721f80bea80b6617c764df278313c426c46961ccde8ee7a03f9007b74bc8bc6c49d1583cf7d8077b493d45eb153353026cc330307e0753ac41a5cb8e843ceb1efdc46655f33a0808bdaa43fc5dc0e928e2da0ce8ed02096b0b74c61feaba2546980ed9c6174f71d").to_vec(), - hex!("9f0b3c252fcb29d88eff4f3de5de4476c3ffbf8013c601cc93de3437f9d415bd52c48d794b341f218b9d0020a4b646746c24d0ca80348b8e2c39c479a146933297f62b7051df82e92e1bca761432c3e6f64c74033f80220131e7cd7a08b97f8aa06225f7aefbbca8118fb436c07689c552ed3f577145806d974dd9e4db5e407e29f84c4121ccc58f9c6adc3933afc1bcaef52defe77de5801e9e1a21db053de56365fdee57998488ddae7d664c0430da90469dde17936c1f80c5c11751bbfc99a1ad805c58a65b9704e0bad58e694023e9cc57ce6ef84cdb0b8038f6c242700eaea04ffad5c25ca9a9b1cc2af7303655a32eb59e84b6bb927cd3802575469e76e104b0db8b18dbc762b997a78aa666432a44c4b955ced044a4691f80a81408b856272feeec08845af515e27d033efd3ff8b46de6bc706c38e600086a809ee78332c2a38a3918070942421e651e0b9a43e4b8b2c92e87a2552cede73e8380c9d79f411f742cad0c6f2b070aa08703a04cb7db840c3821a6762837dd8d00e9807dcfbc7f2fcc9415e2cb40eef7f718758d76193f325b3f8b7180e3e5e7d6b81e8036252cae6d24a531a151ce1ee223a07bf71cf82a7fdf49090e4ca345d27d68ca80e3f08ef11671f8f1defa66fa2af71e1a871430e9352df9b3f1d427b5a5dabfb280b51d28c9b99030d050fc1578cd23b5506e769b86c8f4ccc6aded4b8d7c1a73b7").to_vec(), - ].to_vec(); - // As of query paras::heads(2_086) at block - // "0x18e90e9aa8e3b063f60386ba1b0415111798e72d01de58b1438d620d42f58e39" - // (16_363_919) which results in the key - // "0xcd710b30bd2eab0352ddcc26417aa1941b3c252fcb29d88eff4f3de5de4476c32c0cfd6c23b92a7826080000" - // - let expected_spiritnet_head_at_block = hex!("65541097fb02782e14f43074f0b00e44ae8e9fe426982323ef1d329739740d37f252ff006d1156941db1bccd58ce3a1cac4f40cad91f692d94e98f501dd70081a129b69a3e2ef7e1ff84ba3d86dab4e95f2c87f6b1055ebd48519c185360eae58f05d1ea08066175726120dcdc6308000000000561757261010170ccfaf3756d1a8dd8ae5c89094199d6d32e5dd9f0920f6fe30f986815b5e701974ea0e0e0a901401f2c72e3dd8dbdf4aa55d59bf3e7021856cdb8038419eb8c").to_vec(); - let returned_head = ParachainHeadProofVerifier::::verify_proof_for_parachain( - &2_086, - &16_363_919, - spiritnet_head_proof_at_block, - ) - .expect("Parachain head proof verification should not fail."); - assert!(returned_head.encode() == expected_spiritnet_head_at_block, "Parachain head returned from the state proof verification should not be different than the pre-computed one."); - } -} diff --git a/crates/kilt-dip-primitives/src/state_proofs/substrate_no_std_port.rs b/crates/kilt-dip-primitives/src/state_proofs/substrate_no_std_port.rs new file mode 100644 index 0000000000..927927215c --- /dev/null +++ b/crates/kilt-dip-primitives/src/state_proofs/substrate_no_std_port.rs @@ -0,0 +1,69 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 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 hash_db::EMPTY_PREFIX; +use parity_scale_codec::Codec; +use sp_core::Hasher; +use sp_state_machine::{Backend, TrieBackend, TrieBackendBuilder}; +use sp_std::{collections::btree_map::BTreeMap, vec::Vec}; +use sp_trie::{HashDBT, MemoryDB, StorageProof}; + +pub(super) fn read_proof_check( + root: H::Out, + proof: StorageProof, + keys: I, +) -> Result, Option>>, ()> +where + H: Hasher, + H::Out: Ord + Codec, + I: IntoIterator, + I::Item: AsRef<[u8]>, +{ + let proving_backend = create_proof_check_backend::(root, proof)?; + let mut result = BTreeMap::new(); + for key in keys.into_iter() { + let value = read_proof_check_on_proving_backend(&proving_backend, key.as_ref())?; + result.insert(key.as_ref().to_vec(), value); + } + Ok(result) +} + +fn read_proof_check_on_proving_backend( + proving_backend: &TrieBackend, H>, + key: &[u8], +) -> Result>, ()> +where + H: Hasher, + H::Out: Ord + Codec, +{ + proving_backend.storage(key).map_err(|_| ()) +} + +fn create_proof_check_backend(root: H::Out, proof: StorageProof) -> Result, H>, ()> +where + H: Hasher, + H::Out: Codec, +{ + let db = proof.into_memory_db(); + + if db.contains(&root, EMPTY_PREFIX) { + Ok(TrieBackendBuilder::new(db, root).build()) + } else { + Err(()) + } +} diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index c8b7151729..f88ba7dcac 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -32,7 +32,7 @@ use sp_std::marker::PhantomData; use crate::{ did::RevealedDidKeysSignatureAndCallVerifierError, merkle::{DidMerkleProofVerifierError, RevealedDidMerkleProofLeaf, RevealedDidMerkleProofLeaves}, - state_proofs::{parachain::DipIdentityCommitmentProofVerifierError, relaychain::ParachainHeadProofVerifierError}, + state_proofs::{relaychain::ParachainHeadProofVerifierError, MerkleProofError}, traits::{self, DidSignatureVerifierContext, DipCallOriginFilter, Incrementable}, utils::OutputOf, BoundedBlindedValue, FrameSystemDidSignatureContext, ProviderParachainStateInfoViaProviderPallet, @@ -243,7 +243,7 @@ impl< { type Error = DipParachainStateProofVerifierError< ParachainHeadProofVerifierError, - DipIdentityCommitmentProofVerifierError, + MerkleProofError, DidMerkleProofVerifierError, RevealedDidKeysSignatureAndCallVerifierError, >; @@ -401,7 +401,7 @@ impl< { type Error = DipParachainStateProofVerifierError< ParachainHeadProofVerifierError, - DipIdentityCommitmentProofVerifierError, + MerkleProofError, DidMerkleProofVerifierError, RevealedDidKeysSignatureAndCallVerifierError, >; @@ -472,7 +472,7 @@ pub mod v0 { use crate::{ did::{verify_did_signature_for_call, RevealedDidKeysAndSignature}, merkle::verify_dip_merkle_proof, - state_proofs::{parachain::DipIdentityCommitmentProofVerifier, relaychain::ParachainHeadProofVerifier}, + state_proofs::{relaychain::ParachainHeadProofVerifier, verify_storage_value_proof}, traits::ProviderParachainStorageInfo, verifier::common::v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof}, }; @@ -678,7 +678,7 @@ pub mod v0 { { type Error = DipParachainStateProofVerifierError< ParachainHeadProofVerifierError, - DipIdentityCommitmentProofVerifierError, + MerkleProofError, DidMerkleProofVerifierError, RevealedDidKeysSignatureAndCallVerifierError, >; @@ -720,49 +720,51 @@ pub mod v0 { ) .map_err(DipParachainStateProofVerifierError::ParachainHeadMerkleProof)?; - // 2. Verify commitment is included in provider parachain. - let subject_identity_commitment = - DipIdentityCommitmentProofVerifier::::verify_proof_for_identifier( - subject, - provider_parachain_header.state_root.into(), - proof.dip_identity_commitment, - ) - .map_err(DipParachainStateProofVerifierError::IdentityCommitmentMerkleProof)?; - - // 3. Verify DIP merkle proof. - let proof_leaves: RevealedDidMerkleProofLeaves< - ProviderDidKeyId, - ProviderAccountId, - ::BlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - > = verify_dip_merkle_proof::< - ProviderDipMerkleHasher, - _, - _, - _, - _, - _, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - >(&subject_identity_commitment, proof.did.leaves) - .map_err(DipParachainStateProofVerifierError::DipProof)?; - - // 4. Verify call is signed by one of the DID keys revealed at step 3. - verify_did_signature_for_call::<_, _, _, _, LocalContextProvider, _, _, _, LocalDidCallVerifier>( - call, - submitter, - identity_details, - RevealedDidKeysAndSignature { - merkle_leaves: proof_leaves.borrow(), - did_signature: proof.did.signature, - }, - ) - .map_err(DipParachainStateProofVerifierError::DidSignature)?; - - Ok(proof_leaves) + Ok(Default::default()) + + // // 2. Verify commitment is included in provider parachain. + // let subject_identity_commitment = + // DipIdentityCommitmentProofVerifier::::verify_proof_for_identifier( + // subject, + // provider_parachain_header.state_root.into(), + // proof.dip_identity_commitment, + // ) + // .map_err(DipParachainStateProofVerifierError::IdentityCommitmentMerkleProof)?; + + // // 3. Verify DIP merkle proof. + // let proof_leaves: RevealedDidMerkleProofLeaves< + // ProviderDidKeyId, + // ProviderAccountId, + // ::BlockNumber, ProviderWeb3Name, + // ProviderLinkedAccountId, + // MAX_REVEALED_KEYS_COUNT, + // MAX_REVEALED_ACCOUNTS_COUNT, + // > = verify_dip_merkle_proof::< + // ProviderDipMerkleHasher, + // _, + // _, + // _, + // _, + // _, + // MAX_REVEALED_KEYS_COUNT, + // MAX_REVEALED_ACCOUNTS_COUNT, + // >(&subject_identity_commitment, proof.did.leaves) + // .map_err(DipParachainStateProofVerifierError::DipProof)?; + + // // 4. Verify call is signed by one of the DID keys revealed at + // step 3. verify_did_signature_for_call::<_, _, _, _, + // LocalContextProvider, _, _, _, LocalDidCallVerifier>( call, + // submitter, + // identity_details, + // RevealedDidKeysAndSignature { + // merkle_leaves: proof_leaves.borrow(), + // did_signature: proof.did.signature, + // }, + // ) + // .map_err(DipParachainStateProofVerifierError::DidSignature)?; + + // Ok(proof_leaves) } } } diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index a68dd497f2..32989c6e51 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -32,7 +32,7 @@ use sp_std::marker::PhantomData; use crate::{ did::RevealedDidKeysSignatureAndCallVerifierError, merkle::{DidMerkleProofVerifierError, RevealedDidMerkleProofLeaf, RevealedDidMerkleProofLeaves}, - state_proofs::{parachain::DipIdentityCommitmentProofVerifierError, relaychain::ParachainHeadProofVerifierError}, + state_proofs::{relaychain::ParachainHeadProofVerifierError, MerkleProofError}, traits::{ DidSignatureVerifierContext, DipCallOriginFilter, HistoricalBlockRegistry, Incrementable, ProviderParachainStorageInfo, RelayChainStorageInfo, @@ -247,7 +247,7 @@ impl< { type Error = DipRelaychainStateProofVerifierError< ParachainHeadProofVerifierError, - DipIdentityCommitmentProofVerifierError, + MerkleProofError, DidMerkleProofVerifierError, RevealedDidKeysSignatureAndCallVerifierError, >; @@ -421,7 +421,7 @@ impl< { type Error = DipRelaychainStateProofVerifierError< ParachainHeadProofVerifierError, - DipIdentityCommitmentProofVerifierError, + MerkleProofError, DidMerkleProofVerifierError, RevealedDidKeysSignatureAndCallVerifierError, >; @@ -502,8 +502,8 @@ pub mod v0 { RevealedDidMerkleProofLeaves, }, state_proofs::{ - parachain::{DipIdentityCommitmentProofVerifier, DipIdentityCommitmentProofVerifierError}, relaychain::{ParachainHeadProofVerifier, ParachainHeadProofVerifierError}, + MerkleProofError, }, traits::{ DidSignatureVerifierContext, DipCallOriginFilter, HistoricalBlockRegistry, Incrementable, @@ -713,7 +713,7 @@ pub mod v0 { { type Error = DipRelaychainStateProofVerifierError< ParachainHeadProofVerifierError, - DipIdentityCommitmentProofVerifierError, + MerkleProofError, DidMerkleProofVerifierError, RevealedDidKeysSignatureAndCallVerifierError, >; @@ -766,40 +766,41 @@ pub mod v0 { ) .map_err(DipRelaychainStateProofVerifierError::ParachainHeadMerkleProof)?; - // 3. Verify parachain state proof. - let subject_identity_commitment = - DipIdentityCommitmentProofVerifier::::verify_proof_for_identifier( - subject, - provider_parachain_header.state_root.into(), - proof.dip_identity_commitment, - ) - .map_err(DipRelaychainStateProofVerifierError::IdentityCommitmentMerkleProof)?; - - // 4. Verify DIP merkle proof. - let proof_leaves = verify_dip_merkle_proof::< - ProviderDipMerkleHasher, - _, - _, - _, - _, - _, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - >(&subject_identity_commitment, proof.did.leaves) - .map_err(DipRelaychainStateProofVerifierError::DipProof)?; - - // 5. Verify DID signature. - verify_did_signature_for_call::<_, _, _, _, LocalContextProvider, _, _, _, LocalDidCallVerifier>( - call, - submitter, - identity_details, - RevealedDidKeysAndSignature { - merkle_leaves: proof_leaves.borrow(), - did_signature: proof.did.signature, - }, - ) - .map_err(DipRelaychainStateProofVerifierError::DidSignature)?; - Ok(proof_leaves) + // // 3. Verify parachain state proof. + // let subject_identity_commitment = + // DipIdentityCommitmentProofVerifier::::verify_proof_for_identifier( + // subject, + // provider_parachain_header.state_root.into(), + // proof.dip_identity_commitment, + // ) + // .map_err(DipRelaychainStateProofVerifierError::IdentityCommitmentMerkleProof)?; + + // // 4. Verify DIP merkle proof. + // let proof_leaves = verify_dip_merkle_proof::< + // ProviderDipMerkleHasher, + // _, + // _, + // _, + // _, + // _, + // MAX_REVEALED_KEYS_COUNT, + // MAX_REVEALED_ACCOUNTS_COUNT, + // >(&subject_identity_commitment, proof.did.leaves) + // .map_err(DipRelaychainStateProofVerifierError::DipProof)?; + + // // 5. Verify DID signature. + // verify_did_signature_for_call::<_, _, _, _, LocalContextProvider, _, _, _, + // LocalDidCallVerifier>( call, + // submitter, + // identity_details, + // RevealedDidKeysAndSignature { + // merkle_leaves: proof_leaves.borrow(), + // did_signature: proof.did.signature, + // }, + // ) + // .map_err(DipRelaychainStateProofVerifierError::DidSignature)?; + // Ok(proof_leaves) + Ok(Default::default()) } } } From 555927f98e92a37014649e92e45e76df7a2cfb9d Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Wed, 10 Jan 2024 15:46:37 +0100 Subject: [PATCH 03/45] More refactoring --- crates/kilt-dip-primitives/src/did.rs | 200 +++---------- crates/kilt-dip-primitives/src/lib.rs | 5 +- crates/kilt-dip-primitives/src/merkle.rs | 266 +++++------------- .../src/state_proofs/mod.rs | 6 +- .../src/verifier/parachain.rs | 2 +- dip-template/runtimes/dip-provider/src/dip.rs | 2 +- pallets/pallet-deposit-storage/src/deposit.rs | 8 +- runtimes/common/src/dip/did.rs | 6 +- runtimes/common/src/dip/merkle.rs | 8 +- runtimes/peregrine/src/dip/deposit.rs | 2 +- 10 files changed, 123 insertions(+), 382 deletions(-) diff --git a/crates/kilt-dip-primitives/src/did.rs b/crates/kilt-dip-primitives/src/did.rs index 683e952284..0984921b82 100644 --- a/crates/kilt-dip-primitives/src/did.rs +++ b/crates/kilt-dip-primitives/src/did.rs @@ -18,31 +18,12 @@ //! Module to deal with cross-chain KILT DIDs. -use did::{ - did_details::{DidPublicKey, DidPublicKeyDetails, DidVerificationKey}, - DidSignature, DidVerificationKeyRelationship, -}; +use did::DidSignature; +use frame_support::ensure; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_core::RuntimeDebug; use sp_runtime::traits::CheckedSub; -use sp_std::vec::Vec; - -use crate::{ - merkle::RevealedDidKey, - traits::{DidSignatureVerifierContext, DipCallOriginFilter, Incrementable}, -}; - -/// Type returned by the Merkle proof verifier component of the DIP consumer -/// after verifying a DIP Merkle proof. -#[derive(Encode, Decode, RuntimeDebug, Clone, Eq, PartialEq, TypeInfo)] -pub(crate) struct RevealedDidKeysAndSignature { - /// The keys revelaed in the Merkle proof. - pub merkle_leaves: RevealedDidKeys, - /// The [`DIDSignature`] + consumer chain block number to which the DID - /// signature is anchored. - pub did_signature: TimeBoundDidSignature, -} /// A DID signature anchored to a specific block height. #[derive(Encode, Decode, RuntimeDebug, Clone, Eq, PartialEq, TypeInfo)] @@ -54,6 +35,33 @@ pub struct TimeBoundDidSignature { pub block_number: BlockNumber, } +impl TimeBoundDidSignature +where + BlockNumber: CheckedSub + Ord, +{ + /// Verifies the time bounds of the DID signatures and returns the signature + /// information after stripping time-related information. + pub(crate) fn verify_time_bounds( + self, + current_block_number: BlockNumber, + max_offset: BlockNumber, + ) -> Result { + let signature_block_number = self.block_number; + + let is_signature_fresh = + if let Some(blocks_ago_from_now) = current_block_number.checked_sub(&signature_block_number) { + // False if the signature is too old. + blocks_ago_from_now <= max_offset + } else { + // Signature generated for a future time, not possible to verify. + false + }; + ensure!(is_signature_fresh, DidSignatureVerificationError::SignatureNotFresh); + + Ok(self.signature) + } +} + #[cfg(feature = "runtime-benchmarks")] impl kilt_support::traits::GetWorstCase for TimeBoundDidSignature where @@ -68,156 +76,20 @@ where } } -pub enum RevealedDidKeysSignatureAndCallVerifierError { +pub enum DidSignatureVerificationError { SignatureNotFresh, SignatureUnverifiable, OriginCheckFailed, Internal, } -impl From for u8 { - fn from(value: RevealedDidKeysSignatureAndCallVerifierError) -> Self { +impl From for u8 { + fn from(value: DidSignatureVerificationError) -> Self { match value { - RevealedDidKeysSignatureAndCallVerifierError::SignatureNotFresh => 0, - RevealedDidKeysSignatureAndCallVerifierError::SignatureUnverifiable => 1, - RevealedDidKeysSignatureAndCallVerifierError::OriginCheckFailed => 2, - RevealedDidKeysSignatureAndCallVerifierError::Internal => u8::MAX, - } - } -} - -/// Function that tries to verify a DID signature over a given payload by -/// using one of the DID keys revealed in the Merkle proof. This verifier is -/// typically used in conjunction with a verifier that takes a user-provided -/// input Merkle proof, verifies it, and transforms it into a struct that this -/// and other verifiers can easily consume, e.g., a list of DID keys. -/// The generic types are the following: -/// * `Call`: The call to be dispatched on the local chain after verifying the -/// DID signature. -/// * `Submitter`: The blockchain account (**not** the identity subject) -/// submitting the cross-chain transaction (and paying for its execution -/// fees). -/// * `DidLocalDetails`: Any information associated to the identity subject that -/// is stored locally, e.g., under the `IdentityEntries` map of the -/// `pallet-dip-consumer` pallet. -/// * `MerkleProofEntries`: The type returned by the Merkle proof verifier that -/// includes the identity parts revealed in the Merkle proof. -/// * `ContextProvider`: Provides additional local context (e.g., current block -/// number) to verify the DID signature. -/// * `RemoteKeyId`: Definition of a DID key ID as specified by the provider. -/// * `RemoteAccountId`: Definition of a linked account ID as specified by the -/// provider. -/// * `RemoteBlockNumber`: Definition of a block number on the provider chain. -/// * `CallVerifier`: A type specifying whether the provided `Call` can be -/// dispatched with the information provided in the DIP proof. -pub(crate) fn verify_did_signature_for_call< - Call, - Submitter, - DidLocalDetails, - MerkleProofEntries, - ContextProvider, - RemoteKeyId, - RemoteAccountId, - RemoteBlockNumber, - CallVerifier, ->( - call: &Call, - submitter: &Submitter, - local_details: &mut Option, - merkle_revealed_did_signature: RevealedDidKeysAndSignature, -) -> Result< - (DidVerificationKey, DidVerificationKeyRelationship), - RevealedDidKeysSignatureAndCallVerifierError, -> -where - Call: Encode, - Submitter: Encode, - ContextProvider: DidSignatureVerifierContext, - ContextProvider::BlockNumber: Encode + CheckedSub + From + PartialOrd, - ContextProvider::Hash: Encode, - ContextProvider::SignedExtra: Encode, - DidLocalDetails: Incrementable + Default + Encode, - RemoteAccountId: Clone, - MerkleProofEntries: sp_std::borrow::Borrow<[RevealedDidKey]>, - CallVerifier: - DipCallOriginFilter, DidVerificationKeyRelationship)>, -{ - cfg_if::cfg_if! { - if #[cfg(feature = "runtime-benchmarks")] { - {} - } else { - let block_number = ContextProvider::current_block_number(); - let is_signature_fresh = if let Some(blocks_ago_from_now) = - block_number.checked_sub(&merkle_revealed_did_signature.did_signature.block_number) - { - // False if the signature is too old. - blocks_ago_from_now <= ContextProvider::SIGNATURE_VALIDITY.into() - } else { - // Signature generated at a future time, not possible to verify. - false - }; - frame_support::ensure!( - is_signature_fresh, - RevealedDidKeysSignatureAndCallVerifierError::SignatureNotFresh, - ); - } - } - let encoded_payload = ( - call, - &local_details, - submitter, - &merkle_revealed_did_signature.did_signature.block_number, - ContextProvider::genesis_hash(), - ContextProvider::signed_extra(), - ) - .encode(); - // Only consider verification keys from the set of revealed keys. - let proof_verification_keys: Vec<(DidVerificationKey, DidVerificationKeyRelationship)> = merkle_revealed_did_signature.merkle_leaves.borrow().iter().filter_map(|RevealedDidKey { - relationship, details: DidPublicKeyDetails { key, .. }, .. } | { - let DidPublicKey::PublicVerificationKey(key) = key else { return None }; - if let Ok(vr) = DidVerificationKeyRelationship::try_from(*relationship) { - // TODO: Fix this logic to avoid cloning - Some(Ok((key.clone(), vr))) - } else { - cfg_if::cfg_if! { - if #[cfg(feature = "runtime-benchmarks")] { - None - } else { - log::error!("Should never fail to build a VerificationRelationship from the given DidKeyRelationship because we have already made sure the conditions hold."); - Some(Err(RevealedDidKeysSignatureAndCallVerifierError::Internal)) - } - } - } - }).collect::>()?; - let valid_signing_key = proof_verification_keys.iter().find(|(verification_key, _)| { - verification_key - .verify_signature(&encoded_payload, &merkle_revealed_did_signature.did_signature.signature) - .is_ok() - }); - cfg_if::cfg_if! { - if #[cfg(feature = "runtime-benchmarks")] { - let default = ( - DidVerificationKey::Ed25519(sp_core::ed25519::Public::from_raw([0u8; 32])), - DidVerificationKeyRelationship::Authentication, - ); - let (key, relationship) = valid_signing_key.unwrap_or(&default); - } else { - let (key, relationship) = valid_signing_key.ok_or(RevealedDidKeysSignatureAndCallVerifierError::SignatureUnverifiable)?; - } - } - - if let Some(details) = local_details { - details.increment(); - } else { - *local_details = Some(DidLocalDetails::default()); - }; - let res = CallVerifier::check_call_origin_info(call, &(key.clone(), *relationship)); - cfg_if::cfg_if! { - if #[cfg(feature = "runtime-benchmarks")] { - drop(res); - } else { - res.map_err(|_| RevealedDidKeysSignatureAndCallVerifierError::OriginCheckFailed)?; + DidSignatureVerificationError::SignatureNotFresh => 1, + DidSignatureVerificationError::SignatureUnverifiable => 2, + DidSignatureVerificationError::OriginCheckFailed => 3, + DidSignatureVerificationError::Internal => u8::MAX, } } - Ok((key.clone(), *relationship)) } diff --git a/crates/kilt-dip-primitives/src/lib.rs b/crates/kilt-dip-primitives/src/lib.rs index f8abdd6aad..c44d7708d2 100644 --- a/crates/kilt-dip-primitives/src/lib.rs +++ b/crates/kilt-dip-primitives/src/lib.rs @@ -31,9 +31,8 @@ pub mod merkle; pub mod state_proofs; pub mod traits; pub mod utils; -pub mod verifier; +// pub mod verifier; -pub use state_proofs::relaychain::RelayStateRootsViaRelayStorePallet; pub use traits::{FrameSystemDidSignatureContext, ProviderParachainStateInfoViaProviderPallet}; pub use utils::BoundedBlindedValue; -pub use verifier::*; +// pub use verifier::*; diff --git a/crates/kilt-dip-primitives/src/merkle.rs b/crates/kilt-dip-primitives/src/merkle.rs index 499c6dcb0c..367ca69db3 100644 --- a/crates/kilt-dip-primitives/src/merkle.rs +++ b/crates/kilt-dip-primitives/src/merkle.rs @@ -19,32 +19,77 @@ //! Module to deal with cross-chain Merkle proof as generated by the KILT chain. use did::{did_details::DidPublicKeyDetails, DidVerificationKeyRelationship}; -use frame_support::{traits::ConstU32, DefaultNoBound, RuntimeDebug}; +use frame_support::{ensure, RuntimeDebug}; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; -use sp_runtime::{BoundedVec, SaturatedConversion}; -use sp_std::{fmt::Debug, vec::Vec}; +use sp_runtime::traits::Hash; +use sp_std::vec::Vec; use sp_trie::{verify_trie_proof, LayoutV1}; +use crate::{utils::OutputOf, BoundedBlindedValue}; + /// Type of a Merkle proof containing DID-related information. -#[derive(Encode, Decode, RuntimeDebug, Clone, Eq, PartialEq, Default, TypeInfo)] -pub struct DidMerkleProof { - pub blinded: BlindedValues, - // TODO: Probably replace with a different data structure for better lookup capabilities - pub revealed: Vec, +/// The generic types are the following: +/// * `KeyId`: The type of a DID key ID according to the producer's definition. +/// * `AccountId`: The type of an account ID according to the producer's +/// definition. +/// * `BlockNumber`: The type of a block number according to the producer's +/// definition. +/// * `Web3Name`: The type of a web3names according to the producer's +/// definition. +/// * `LinkedAccountId`: The type of a DID-linked account ID according to the +/// producer's definition. +#[derive(Encode, Decode, RuntimeDebug, Clone, Eq, PartialEq, TypeInfo)] +pub struct DidMerkleProof { + pub blinded: BoundedBlindedValue, + pub revealed: Vec>, } -#[cfg(feature = "runtime-benchmarks")] -impl kilt_support::traits::GetWorstCase for DidMerkleProof +impl + DidMerkleProof where - BlindedValues: kilt_support::traits::GetWorstCase, - Leaf: Default + Clone, + KeyId: Encode, + AccountId: Encode, + BlockNumber: Encode, + Web3Name: Encode, + LinkedAccountId: Encode, { - fn worst_case(context: Context) -> Self { - Self { - blinded: BlindedValues::worst_case(context), - revealed: sp_std::vec![Leaf::default(); 64], - } + /// Verifies the DIP Merkle proof revealing some leaves + /// representing parts of a KILT DID identity stored on the KILT chain + /// against a given identity commitment. If cross-chain DID signatures are + /// not required for the specific use case, this verifier can also be used + /// on its own, without any DID signature verification. + /// The Merkle proof is assumed to have been generated using one of the + /// versioned identity commitment generators, as shown in the [KILT runtime + /// definitions](../../../runtimes/common/src/dip/README.md). The function + /// returns the revealed leaves if the Merkle proof is correct and if the + /// number of leaves does not exceed the maximum configured. The generic + /// types are the following: + /// * `Hasher`: The hasher used by the producer to hash the Merkle leaves + /// and produce the identity commitment. + pub fn verify_against_commitment( + &self, + commitment: &OutputOf, + max_leaves_revealed: usize, + ) -> Result<(), DidMerkleProofVerificationError> + where + Hasher: Hash, + { + let mut revealed_keys = self.revealed.iter().take(max_leaves_revealed); + // If there are more keys than MAX_LEAVES_REVEALED, bail out. + ensure!( + revealed_keys.next().is_none(), + DidMerkleProofVerificationError::TooManyLeaves, + ); + let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = revealed_keys + .by_ref() + .map(|revealed_leaf| (revealed_leaf.encoded_key(), Some(revealed_leaf.encoded_value()))) + .collect(); + + verify_trie_proof::, _, _, _>(commitment, &self.blinded, &proof_leaves_key_value_pairs) + .map_err(|_| DidMerkleProofVerificationError::InvalidMerkleProof)?; + + Ok(()) } } @@ -187,191 +232,16 @@ pub struct RevealedWeb3Name { #[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] pub struct RevealedAccountId(pub AccountId); -/// The complete set of information that is provided by the DIP Merkle proof -/// verifier upon successful verification of a DIP Merkle proof. -#[derive(Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen, Encode, Decode, DefaultNoBound)] -pub struct RevealedDidMerkleProofLeaves< - KeyId, - AccountId, - BlockNumber, - Web3Name, - LinkedAccountId, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, -> { - /// The list of [`RevealedDidKey`]s revealed in the Merkle proof, up to a - /// maximum of `MAX_REVEALED_KEYS_COUNT`. - pub did_keys: BoundedVec, ConstU32>, - /// The optional [`RevealedWeb3Name`] revealed in the Merkle proof. - pub web3_name: Option>, - /// The list of linked accounts revealed in the Merkle proof, up to a - /// maximum of `MAX_REVEALED_ACCOUNTS_COUNT`. - pub linked_accounts: BoundedVec, ConstU32>, -} - -impl< - KeyId, - AccountId, - BlockNumber, - Web3Name, - LinkedAccountId, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, - > sp_std::borrow::Borrow<[RevealedDidKey]> - for RevealedDidMerkleProofLeaves< - KeyId, - AccountId, - BlockNumber, - Web3Name, - LinkedAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - > -{ - fn borrow(&self) -> &[RevealedDidKey] { - self.did_keys.borrow() - } -} - -pub enum DidMerkleProofVerifierError { +pub enum DidMerkleProofVerificationError { InvalidMerkleProof, - TooManyRevealedKeys, - TooManyRevealedAccounts, + TooManyLeaves, } -impl From for u8 { - fn from(value: DidMerkleProofVerifierError) -> Self { +impl From for u8 { + fn from(value: DidMerkleProofVerificationError) -> Self { match value { - DidMerkleProofVerifierError::InvalidMerkleProof => 0, - DidMerkleProofVerifierError::TooManyRevealedKeys => 1, - DidMerkleProofVerifierError::TooManyRevealedAccounts => 2, + DidMerkleProofVerificationError::InvalidMerkleProof => 1, + DidMerkleProofVerificationError::TooManyLeaves => 2, } } } - -/// A function that verifies a DIP Merkle proof revealing some leaves -/// representing parts of a KILT DID identity stored on the KILT chain. -/// If cross-chain DID signatures are not required for the specific use case, -/// this verifier can also be used on its own, without any DID signature -/// verification. -/// The Merkle proof is assumed to have been generated using one of the -/// versioned identity commitment generators, as shown in the [KILT runtime -/// definitions](../../../runtimes/common/src/dip/README.md). -/// The generic types are the following: -/// * `Hasher`: The hasher used by the producer to hash the Merkle leaves and -/// produce the identity commitment. -/// * `KeyId`: The type of a DID key ID according to the producer's definition. -/// * `AccountId`: The type of an account ID according to the producer's -/// definition. -/// * `BlockNumber`: The type of a block number according to the producer's -/// definition. -/// * `Web3Name`: The type of a web3names according to the producer's -/// definition. -/// * `LinkedAccountId`: The type of a DID-linked account ID according to the -/// producer's definition. -/// * `MAX_REVEALED_KEYS_COUNT`: The maximum number of DID keys that are -/// supported when verifying the Merkle proof. -/// * `MAX_REVEALED_ACCOUNTS_COUNT`: The maximum number of linked accounts that -/// are supported when verifying the Merkle proof. -pub(crate) fn verify_dip_merkle_proof< - Hasher, - KeyId, - AccountId, - BlockNumber, - Web3Name, - LinkedAccountId, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, ->( - identity_commitment: &Hasher::Out, - proof: DidMerkleProof< - crate::BoundedBlindedValue, - RevealedDidMerkleProofLeaf, - >, -) -> Result< - RevealedDidMerkleProofLeaves< - KeyId, - AccountId, - BlockNumber, - Web3Name, - LinkedAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - >, - DidMerkleProofVerifierError, -> -where - BlockNumber: Encode + Clone, - Hasher: sp_core::Hasher, - KeyId: Encode + Clone, - AccountId: Encode + Clone, - LinkedAccountId: Encode + Clone, - Web3Name: Encode + Clone, -{ - // TODO: more efficient by removing cloning and/or collecting. - // Did not find another way of mapping a Vec<(Vec, Vec)> to a - // Vec<(Vec, Option>)>. - let proof_leaves = proof - .revealed - .iter() - .map(|leaf| (leaf.encoded_key(), Some(leaf.encoded_value()))) - .collect::, Option>)>>(); - let res = verify_trie_proof::, _, _, _>(identity_commitment, &proof.blinded, &proof_leaves); - cfg_if::cfg_if! { - if #[cfg(feature = "runtime-benchmarks")] { - drop(res); - } else { - res.map_err(|_| DidMerkleProofVerifierError::InvalidMerkleProof)?; - } - } - - // At this point, we know the proof is valid. We just need to map the revealed - // leaves to something the consumer can easily operate on. - #[allow(clippy::type_complexity)] - let (did_keys, web3_name, linked_accounts): ( - BoundedVec, ConstU32>, - Option>, - BoundedVec, ConstU32>, - ) = proof.revealed.into_iter().try_fold( - ( - BoundedVec::with_bounded_capacity(MAX_REVEALED_KEYS_COUNT.saturated_into()), - None, - BoundedVec::with_bounded_capacity(MAX_REVEALED_ACCOUNTS_COUNT.saturated_into()), - ), - |(mut keys, web3_name, mut linked_accounts), leaf| match leaf { - RevealedDidMerkleProofLeaf::DidKey(revealed_did_key) => { - let res = keys.try_push(revealed_did_key); - cfg_if::cfg_if! { - if #[cfg(feature = "runtime-benchmarks")] { - drop(res); - } else { - res.map_err(|_| DidMerkleProofVerifierError::TooManyRevealedKeys)?; - } - } - - Ok::<_, DidMerkleProofVerifierError>((keys, web3_name, linked_accounts)) - } - RevealedDidMerkleProofLeaf::Web3Name(revealed_web3name) => { - Ok((keys, Some(revealed_web3name), linked_accounts)) - } - RevealedDidMerkleProofLeaf::LinkedAccount(revealed_account_id) => { - let res = linked_accounts.try_push(revealed_account_id); - cfg_if::cfg_if! { - if #[cfg(feature = "runtime-benchmarks")] { - drop(res); - } else { - res.map_err(|_| DidMerkleProofVerifierError::TooManyRevealedAccounts)?; - } - } - - Ok::<_, DidMerkleProofVerifierError>((keys, web3_name, linked_accounts)) - } - }, - )?; - - Ok(RevealedDidMerkleProofLeaves { - did_keys, - web3_name, - linked_accounts, - }) -} diff --git a/crates/kilt-dip-primitives/src/state_proofs/mod.rs b/crates/kilt-dip-primitives/src/state_proofs/mod.rs index 0963d7b075..129a9694ce 100644 --- a/crates/kilt-dip-primitives/src/state_proofs/mod.rs +++ b/crates/kilt-dip-primitives/src/state_proofs/mod.rs @@ -40,9 +40,9 @@ pub enum MerkleProofError { impl From for u8 { fn from(value: MerkleProofError) -> Self { match value { - MerkleProofError::InvalidProof => 0, - MerkleProofError::RequiredLeafNotRevealed => 1, - MerkleProofError::ResultDecoding => 2, + MerkleProofError::InvalidProof => 1, + MerkleProofError::RequiredLeafNotRevealed => 2, + MerkleProofError::ResultDecoding => 3, } } } diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index f88ba7dcac..1d337fd214 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -121,7 +121,7 @@ where >, ) -> Self { match value { - DipParachainStateProofVerifierError::UnsupportedVersion => 0, + DipParachainStateProofVerifierError::UnsupportedVersion => 1, DipParachainStateProofVerifierError::ParachainHeadMerkleProof(error) => { u8::MAX as u16 + error.into() as u16 } diff --git a/dip-template/runtimes/dip-provider/src/dip.rs b/dip-template/runtimes/dip-provider/src/dip.rs index 2af1620430..98f59b59bf 100644 --- a/dip-template/runtimes/dip-provider/src/dip.rs +++ b/dip-template/runtimes/dip-provider/src/dip.rs @@ -127,7 +127,7 @@ pub mod deposit { impl From for u16 { fn from(value: CommitmentDepositRemovalHookError) -> Self { match value { - CommitmentDepositRemovalHookError::DecodeKey => 0, + CommitmentDepositRemovalHookError::DecodeKey => 1, CommitmentDepositRemovalHookError::Internal => u16::MAX, } } diff --git a/pallets/pallet-deposit-storage/src/deposit.rs b/pallets/pallet-deposit-storage/src/deposit.rs index b4784be30c..081c0aef64 100644 --- a/pallets/pallet-deposit-storage/src/deposit.rs +++ b/pallets/pallet-deposit-storage/src/deposit.rs @@ -59,10 +59,10 @@ pub enum FixedDepositCollectorViaDepositsPalletError { impl From for u16 { fn from(value: FixedDepositCollectorViaDepositsPalletError) -> Self { match value { - FixedDepositCollectorViaDepositsPalletError::DepositAlreadyTaken => 0, - FixedDepositCollectorViaDepositsPalletError::DepositNotFound => 1, - FixedDepositCollectorViaDepositsPalletError::FailedToHold => 2, - FixedDepositCollectorViaDepositsPalletError::FailedToRelease => 3, + FixedDepositCollectorViaDepositsPalletError::DepositAlreadyTaken => 1, + FixedDepositCollectorViaDepositsPalletError::DepositNotFound => 2, + FixedDepositCollectorViaDepositsPalletError::FailedToHold => 3, + FixedDepositCollectorViaDepositsPalletError::FailedToRelease => 4, FixedDepositCollectorViaDepositsPalletError::Internal => u16::MAX, } } diff --git a/runtimes/common/src/dip/did.rs b/runtimes/common/src/dip/did.rs index 9056b7990d..688aeba2a4 100644 --- a/runtimes/common/src/dip/did.rs +++ b/runtimes/common/src/dip/did.rs @@ -42,9 +42,9 @@ pub enum LinkedDidInfoProviderError { impl From for u16 { fn from(value: LinkedDidInfoProviderError) -> Self { match value { - LinkedDidInfoProviderError::DidNotFound => 0, - LinkedDidInfoProviderError::DidDeleted => 1, - LinkedDidInfoProviderError::TooManyLinkedAccounts => 2, + LinkedDidInfoProviderError::DidNotFound => 1, + LinkedDidInfoProviderError::DidDeleted => 2, + LinkedDidInfoProviderError::TooManyLinkedAccounts => 3, LinkedDidInfoProviderError::Internal => u16::MAX, } } diff --git a/runtimes/common/src/dip/merkle.rs b/runtimes/common/src/dip/merkle.rs index 839aeb5231..05078521b1 100644 --- a/runtimes/common/src/dip/merkle.rs +++ b/runtimes/common/src/dip/merkle.rs @@ -69,10 +69,10 @@ pub enum DidMerkleProofError { impl From for u16 { fn from(value: DidMerkleProofError) -> Self { match value { - DidMerkleProofError::UnsupportedVersion => 0, - DidMerkleProofError::KeyNotFound => 1, - DidMerkleProofError::LinkedAccountNotFound => 2, - DidMerkleProofError::Web3NameNotFound => 3, + DidMerkleProofError::UnsupportedVersion => 1, + DidMerkleProofError::KeyNotFound => 2, + DidMerkleProofError::LinkedAccountNotFound => 3, + DidMerkleProofError::Web3NameNotFound => 4, DidMerkleProofError::Internal => u16::MAX, } } diff --git a/runtimes/peregrine/src/dip/deposit.rs b/runtimes/peregrine/src/dip/deposit.rs index 3a429989ea..24aab0df62 100644 --- a/runtimes/peregrine/src/dip/deposit.rs +++ b/runtimes/peregrine/src/dip/deposit.rs @@ -74,7 +74,7 @@ pub enum CommitmentDepositRemovalHookError { impl From for u16 { fn from(value: CommitmentDepositRemovalHookError) -> Self { match value { - CommitmentDepositRemovalHookError::DecodeKey => 0, + CommitmentDepositRemovalHookError::DecodeKey => 1, CommitmentDepositRemovalHookError::Internal => u16::MAX, } } From e142c8a813e49589068df23b33213654de364cde Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 11 Jan 2024 11:28:19 +0100 Subject: [PATCH 04/45] Refactor compiling --- crates/kilt-dip-primitives/src/did.rs | 6 +- crates/kilt-dip-primitives/src/lib.rs | 4 +- crates/kilt-dip-primitives/src/traits.rs | 12 + .../src/verifier/common.rs | 21 +- .../kilt-dip-primitives/src/verifier/mod.rs | 15 +- .../src/verifier/parachain.rs | 748 ++++++------------ nodes/parachain/src/chain_spec/clone.rs | 8 +- runtimes/clone/src/lib.rs | 2 +- 8 files changed, 250 insertions(+), 566 deletions(-) diff --git a/crates/kilt-dip-primitives/src/did.rs b/crates/kilt-dip-primitives/src/did.rs index 0984921b82..1d033174fe 100644 --- a/crates/kilt-dip-primitives/src/did.rs +++ b/crates/kilt-dip-primitives/src/did.rs @@ -41,7 +41,7 @@ where { /// Verifies the time bounds of the DID signatures and returns the signature /// information after stripping time-related information. - pub(crate) fn verify_time_bounds( + pub fn verify_time_bounds( self, current_block_number: BlockNumber, max_offset: BlockNumber, @@ -79,8 +79,6 @@ where pub enum DidSignatureVerificationError { SignatureNotFresh, SignatureUnverifiable, - OriginCheckFailed, - Internal, } impl From for u8 { @@ -88,8 +86,6 @@ impl From for u8 { match value { DidSignatureVerificationError::SignatureNotFresh => 1, DidSignatureVerificationError::SignatureUnverifiable => 2, - DidSignatureVerificationError::OriginCheckFailed => 3, - DidSignatureVerificationError::Internal => u8::MAX, } } } diff --git a/crates/kilt-dip-primitives/src/lib.rs b/crates/kilt-dip-primitives/src/lib.rs index c44d7708d2..359d858c21 100644 --- a/crates/kilt-dip-primitives/src/lib.rs +++ b/crates/kilt-dip-primitives/src/lib.rs @@ -31,8 +31,8 @@ pub mod merkle; pub mod state_proofs; pub mod traits; pub mod utils; -// pub mod verifier; +pub mod verifier; pub use traits::{FrameSystemDidSignatureContext, ProviderParachainStateInfoViaProviderPallet}; pub use utils::BoundedBlindedValue; -// pub use verifier::*; +pub use verifier::*; diff --git a/crates/kilt-dip-primitives/src/traits.rs b/crates/kilt-dip-primitives/src/traits.rs index b96ac7d33a..483fc00bce 100644 --- a/crates/kilt-dip-primitives/src/traits.rs +++ b/crates/kilt-dip-primitives/src/traits.rs @@ -212,3 +212,15 @@ where } } } + +pub trait GetWithArg { + type Result; + + fn get(arg: &Arg) -> Self::Result; +} + +pub trait GetWithoutArg { + type Result; + + fn get() -> Self::Result; +} diff --git a/crates/kilt-dip-primitives/src/verifier/common.rs b/crates/kilt-dip-primitives/src/verifier/common.rs index 455c5848a9..bc4fce0911 100644 --- a/crates/kilt-dip-primitives/src/verifier/common.rs +++ b/crates/kilt-dip-primitives/src/verifier/common.rs @@ -50,28 +50,11 @@ pub mod v0 { } #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)] - pub struct DipMerkleProofAndDidSignature { + pub struct DipMerkleProofAndDidSignature { /// The DIP Merkle proof revealing some leaves about the DID subject's /// identity. - pub(crate) leaves: DidMerkleProof, + pub(crate) leaves: DidMerkleProof, /// The cross-chain DID signature. pub(crate) signature: TimeBoundDidSignature, } - - #[cfg(feature = "runtime-benchmarks")] - impl kilt_support::traits::GetWorstCase - for DipMerkleProofAndDidSignature - where - BlindedValues: kilt_support::traits::GetWorstCase, - Leaf: Default + Clone, - BlockNumber: Default, - Context: Clone, - { - fn worst_case(context: Context) -> Self { - Self { - leaves: DidMerkleProof::worst_case(context.clone()), - signature: TimeBoundDidSignature::worst_case(context), - } - } - } } diff --git a/crates/kilt-dip-primitives/src/verifier/mod.rs b/crates/kilt-dip-primitives/src/verifier/mod.rs index a48871a305..88c86fcd04 100644 --- a/crates/kilt-dip-primitives/src/verifier/mod.rs +++ b/crates/kilt-dip-primitives/src/verifier/mod.rs @@ -16,20 +16,19 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -/// Verification logic to integrate a sibling chain as a DIP provider. -pub mod parachain; /// Verification logic to integrate a child chain as a DIP provider. -pub mod relaychain; - +// pub mod relaychain; mod common; +/// Verification logic to integrate a sibling chain as a DIP provider. +pub mod parachain; pub use parachain::{ DipParachainStateProofVerifierError, KiltVersionedParachainVerifier, VersionedDipParachainStateProof, }; -pub use relaychain::{ - DipRelaychainStateProofVerifierError, KiltVersionedRelaychainVerifier, VersionedRelaychainStateProof, -}; +// pub use relaychain::{ +// DipRelaychainStateProofVerifierError, KiltVersionedRelaychainVerifier, +// VersionedRelaychainStateProof, }; pub mod latest { - pub use super::{common::latest::*, parachain::latest::*, relaychain::latest::*}; + pub use super::{common::latest::*, parachain::latest::*}; } diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 1d337fd214..a0b2ec1dea 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -16,26 +16,22 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -use cumulus_primitives_core::ParaId; use did::{did_details::DidVerificationKey, DidVerificationKeyRelationship, KeyIdOf}; -use frame_support::Parameter; use frame_system::pallet_prelude::BlockNumberFor; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_consumer::{traits::IdentityProofVerifier, RuntimeCallOf}; use pallet_dip_provider::IdentityCommitmentOf; -use parity_scale_codec::{Decode, Encode, HasCompact}; +use pallet_web3_names::Web3NameOf; +use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_core::{RuntimeDebug, U256}; -use sp_runtime::traits::Get; +use sp_core::RuntimeDebug; use sp_std::marker::PhantomData; use crate::{ - did::RevealedDidKeysSignatureAndCallVerifierError, - merkle::{DidMerkleProofVerifierError, RevealedDidMerkleProofLeaf, RevealedDidMerkleProofLeaves}, - state_proofs::{relaychain::ParachainHeadProofVerifierError, MerkleProofError}, - traits::{self, DidSignatureVerifierContext, DipCallOriginFilter, Incrementable}, + merkle::RevealedDidMerkleProofLeaf, + traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, - BoundedBlindedValue, FrameSystemDidSignatureContext, ProviderParachainStateInfoViaProviderPallet, + BoundedBlindedValue, }; /// A KILT-specific DIP identity proof for a sibling consumer that supports @@ -45,40 +41,24 @@ use crate::{ #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)] pub enum VersionedDipParachainStateProof< RelayBlockHeight, - DipMerkleProofBlindedValues, - DipMerkleProofRevealedLeaf, + ProviderKeyId, + ProviderAccountId, + ProviderWeb3Name, + ProviderLinkedAccountId, LocalBlockNumber, > { V0( v0::ParachainDipStateProof< RelayBlockHeight, - DipMerkleProofBlindedValues, - DipMerkleProofRevealedLeaf, + ProviderKeyId, + ProviderAccountId, + ProviderWeb3Name, + ProviderLinkedAccountId, LocalBlockNumber, >, ), } -#[cfg(feature = "runtime-benchmarks")] -impl - kilt_support::traits::GetWorstCase - for VersionedDipParachainStateProof< - RelayBlockHeight, - DipMerkleProofBlindedValues, - DipMerkleProofRevealedLeaf, - LocalBlockNumber, - > where - RelayBlockHeight: Default, - DipMerkleProofBlindedValues: kilt_support::traits::GetWorstCase, - DipMerkleProofRevealedLeaf: Default + Clone, - LocalBlockNumber: Default, - Context: Clone, -{ - fn worst_case(context: Context) -> Self { - Self::V0(v0::ParachainDipStateProof::worst_case(context)) - } -} - pub enum DipParachainStateProofVerifierError< ParachainHeadMerkleProofVerificationError, IdentityCommitmentMerkleProofVerificationError, @@ -179,61 +159,55 @@ where /// `MAX_DID_SIGNATURE_DURATION`. /// * `LocalDidCallVerifier`: The provided `LocalDidCallVerifier`. pub struct KiltVersionedParachainVerifier< - KiltRuntime, - KiltParachainId, - RelayChainStateInfo, - KiltDipMerkleHasher, - LocalDidCallVerifier, - const MAX_REVEALED_KEYS_COUNT: u32 = 10, - const MAX_REVEALED_ACCOUNTS_COUNT: u32 = 10, - const MAX_DID_SIGNATURE_DURATION: u16 = 50, + RelaychainRuntime, + RelaychainStateRoot, + const PROVIDER_PARA_ID: u32, + ProviderRuntime, + SignedExtra, + DidCallVerifier, + const MAX_LEAVES_REVEALED: usize, + const SIGNATURE_VALIDITY: u32, >( PhantomData<( - KiltRuntime, - KiltParachainId, - RelayChainStateInfo, - KiltDipMerkleHasher, - LocalDidCallVerifier, + RelaychainRuntime, + RelaychainStateRoot, + ProviderRuntime, + SignedExtra, + DidCallVerifier, )>, ); impl< ConsumerRuntime, + RelaychainRuntime, + RelaychainStateRoot, + const PROVIDER_PARA_ID: u32, KiltRuntime, - KiltParachainId, - RelayChainStateInfo, - KiltDipMerkleHasher, - LocalDidCallVerifier, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, - const MAX_DID_SIGNATURE_DURATION: u16, + SignedExtra, + DidCallVerifier, + const MAX_LEAVES_REVEALED: usize, + const SIGNATURE_VALIDITY: u32, > IdentityProofVerifier for KiltVersionedParachainVerifier< + RelaychainRuntime, + RelaychainStateRoot, + PROVIDER_PARA_ID, KiltRuntime, - KiltParachainId, - RelayChainStateInfo, - KiltDipMerkleHasher, - LocalDidCallVerifier, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - MAX_DID_SIGNATURE_DURATION, + SignedExtra, + DidCallVerifier, + MAX_LEAVES_REVEALED, + SIGNATURE_VALIDITY, > where - KiltRuntime: did::Config - + pallet_web3_names::Config - + pallet_did_lookup::Config - + parachain_info::Config - + pallet_dip_provider::Config, - KiltParachainId: Get, - OutputOf: Ord + From>, - KeyIdOf: Into, - KiltDipMerkleHasher: sp_core::Hasher>, - ConsumerRuntime: pallet_dip_consumer::Config, - ConsumerRuntime::LocalIdentityInfo: Incrementable + Default + Encode, - RelayChainStateInfo: traits::RelayChainStorageInfo + traits::RelayChainStateInfo, - RelayChainStateInfo::ParaId: From, - RelayChainStateInfo::BlockNumber: Parameter + 'static + Copy + Into + TryFrom + HasCompact, - RelayChainStateInfo::Key: AsRef<[u8]>, - LocalDidCallVerifier: DipCallOriginFilter< + ConsumerRuntime: pallet_dip_consumer::Config + pallet_relay_store::Config, + ConsumerRuntime::LocalIdentityInfo: Incrementable + Default, + RelaychainRuntime: frame_system::Config, + RelaychainStateRoot: + GetWithArg, Result = Option>>, + KiltRuntime: pallet_dip_provider::Config + did::Config + pallet_web3_names::Config + pallet_did_lookup::Config, + IdentityCommitmentOf: Into, + SignedExtra: GetWithoutArg, + SignedExtra::Result: Encode, + DidCallVerifier: DipCallOriginFilter< RuntimeCallOf, OriginInfo = ( DidVerificationKey, @@ -241,191 +215,16 @@ impl< ), >, { - type Error = DipParachainStateProofVerifierError< - ParachainHeadProofVerifierError, - MerkleProofError, - DidMerkleProofVerifierError, - RevealedDidKeysSignatureAndCallVerifierError, - >; + type Error = u16; type Proof = VersionedDipParachainStateProof< - RelayChainStateInfo::BlockNumber, - BoundedBlindedValue, - RevealedDidMerkleProofLeaf< - KeyIdOf, - KiltRuntime::AccountId, - BlockNumberFor, - KiltRuntime::Web3Name, - LinkableAccountId, - >, - BlockNumberFor, - >; - type VerificationResult = RevealedDidMerkleProofLeaves< + BlockNumberFor, KeyIdOf, KiltRuntime::AccountId, - BlockNumberFor, - KiltRuntime::Web3Name, + Web3NameOf, LinkableAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - >; - - fn verify_proof_for_call_against_details( - call: &RuntimeCallOf, - subject: &ConsumerRuntime::Identifier, - submitter: &ConsumerRuntime::AccountId, - identity_details: &mut Option, - proof: Self::Proof, - ) -> Result { - , - KiltDipMerkleHasher, - KeyIdOf, - KiltRuntime::AccountId, - KiltRuntime::Web3Name, - LinkableAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - FrameSystemDidSignatureContext, - LocalDidCallVerifier, - > as IdentityProofVerifier>::verify_proof_for_call_against_details( - call, - subject, - submitter, - identity_details, - proof, - ) - } -} - -/// Generic proof verifier for KILT-specific DIP identity proofs of different -/// versions coming from a sibling provider running one of the available KILT -/// runtimes. -/// -/// It expects the DIP proof to be a [`VersionedDipParachainStateProof`], -/// and returns [`RevealedDidMerkleProofLeaves`] if the proof is successfully -/// verified. -/// -/// For more info, refer to the version-specific proof identifiers. -pub struct GenericVersionedParachainVerifier< - RelayChainStateInfo, - SiblingProviderParachainId, - SiblingProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, - LocalContextProvider, - LocalDidCallVerifier, ->( - #[allow(clippy::type_complexity)] - PhantomData<( - RelayChainStateInfo, - SiblingProviderParachainId, - SiblingProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - LocalContextProvider, - LocalDidCallVerifier, - )>, -); - -impl< - ConsumerRuntime, - RelayChainStateInfo, - SiblingProviderParachainId, - SiblingProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, - LocalContextProvider, - LocalDidCallVerifier, - > IdentityProofVerifier - for GenericVersionedParachainVerifier< - RelayChainStateInfo, - SiblingProviderParachainId, - SiblingProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - LocalContextProvider, - LocalDidCallVerifier, - > where - ConsumerRuntime: pallet_dip_consumer::Config, - ConsumerRuntime::LocalIdentityInfo: Incrementable + Default, - - RelayChainStateInfo: traits::RelayChainStorageInfo + traits::RelayChainStateInfo, - OutputOf: Ord, - RelayChainStateInfo::BlockNumber: Parameter + 'static + Copy + Into + TryFrom + HasCompact, - RelayChainStateInfo::Key: AsRef<[u8]>, - - SiblingProviderParachainId: Get, - - SiblingProviderStateInfo: traits::ProviderParachainStorageInfo< - Identifier = ConsumerRuntime::Identifier, - Commitment = ProviderDipMerkleHasher::Out, - >, - OutputOf: Ord + From>, - SiblingProviderStateInfo::BlockNumber: Parameter + 'static, - SiblingProviderStateInfo::Commitment: Decode, - SiblingProviderStateInfo::Key: AsRef<[u8]>, - - LocalContextProvider: - DidSignatureVerifierContext, Hash = ConsumerRuntime::Hash>, - LocalContextProvider::SignedExtra: Encode, - LocalDidCallVerifier: DipCallOriginFilter< - RuntimeCallOf, - OriginInfo = (DidVerificationKey, DidVerificationKeyRelationship), - >, - - ProviderDipMerkleHasher: sp_core::Hasher, - ProviderDidKeyId: Parameter + 'static + Into, - ProviderAccountId: Parameter + 'static, - ProviderLinkedAccountId: Parameter + 'static, - ProviderWeb3Name: Parameter + 'static, -{ - type Error = DipParachainStateProofVerifierError< - ParachainHeadProofVerifierError, - MerkleProofError, - DidMerkleProofVerifierError, - RevealedDidKeysSignatureAndCallVerifierError, - >; - type Proof = VersionedDipParachainStateProof< - RelayChainStateInfo::BlockNumber, - BoundedBlindedValue, - RevealedDidMerkleProofLeaf< - ProviderDidKeyId, - ProviderAccountId, - SiblingProviderStateInfo::BlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, - >, BlockNumberFor, >; - type VerificationResult = RevealedDidMerkleProofLeaves< - ProviderDidKeyId, - ProviderAccountId, - SiblingProviderStateInfo::BlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - >; + type VerificationResult = (); fn verify_proof_for_call_against_details( call: &RuntimeCallOf, @@ -435,19 +234,15 @@ impl< proof: Self::Proof, ) -> Result { match proof { - VersionedDipParachainStateProof::V0(v0_proof) => as IdentityProofVerifier>::verify_proof_for_call_against_details( call, subject, @@ -460,20 +255,20 @@ impl< } pub mod latest { - pub use super::v0::ParachainDipStateProof; + // pub use super::v0::ParachainDipStateProof; } pub mod v0 { use super::*; - use frame_support::Parameter; - use sp_std::borrow::Borrow; + use did::did_details::DidPublicKey; + use frame_system::pallet_prelude::HeaderFor; + use pallet_web3_names::Web3NameOf; + use sp_core::storage::StorageKey; + use sp_runtime::traits::{Header, Zero}; use crate::{ - did::{verify_did_signature_for_call, RevealedDidKeysAndSignature}, - merkle::verify_dip_merkle_proof, - state_proofs::{relaychain::ParachainHeadProofVerifier, verify_storage_value_proof}, - traits::ProviderParachainStorageInfo, + state_proofs::verify_storage_value_proof, verifier::common::v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof}, }; @@ -484,287 +279,188 @@ pub mod v0 { #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)] pub struct ParachainDipStateProof< RelayBlockHeight, - DipMerkleProofBlindedValues, - DipMerkleProofRevealedLeaf, + ProviderKeyId, + ProviderAccountId, + ProviderWeb3Name, + ProviderLinkedAccountId, LocalBlockNumber, > { - /// The state proof for the given parachain head. pub(crate) para_state_root: ParachainRootStateProof, - /// The raw state proof for the DIP commitment of the given subject. pub(crate) dip_identity_commitment: BoundedBlindedValue, - /// The cross-chain DID signature. - pub(crate) did: - DipMerkleProofAndDidSignature, - } - - #[cfg(feature = "runtime-benchmarks")] - impl - kilt_support::traits::GetWorstCase - for ParachainDipStateProof - where - DipMerkleProofBlindedValues: kilt_support::traits::GetWorstCase, - DipMerkleProofRevealedLeaf: Default + Clone, - RelayBlockHeight: Default, - LocalBlockNumber: Default, - Context: Clone, - { - fn worst_case(context: Context) -> Self { - Self { - para_state_root: ParachainRootStateProof::worst_case(context.clone()), - dip_identity_commitment: BoundedBlindedValue::worst_case(context.clone()), - did: DipMerkleProofAndDidSignature::worst_case(context), - } - } + pub(crate) did: DipMerkleProofAndDidSignature< + ProviderKeyId, + ProviderAccountId, + LocalBlockNumber, + ProviderWeb3Name, + ProviderLinkedAccountId, + >, } - /// Generic proof verifier for KILT-specific DIP identity proofs coming from - /// a sibling provider running one of the available KILT runtimes. - /// - /// The proof verification step is performed on every request, and this - /// specific verifier has no knowledge of caching or storing state about the - /// subject. It only takes the provided - /// `ConsumerRuntime::LocalIdentityInfo` and increases it if the proof is - /// successfully verified, to prevent replay attacks. If additional logic is - /// to be stored under the `ConsumerRuntime::LocalIdentityInfo` entry, a - /// different verifier or a wrapper around this verifier must be built. - /// - /// It expects the DIP proof to be a - /// [`VersionedDipParachainStateProof`], and returns - /// [`RevealedDidMerkleProofLeaves`] if the proof is successfully verified. - /// This information is then made availabe as an origin to the downstream - /// call dispatched. - /// - /// The verifier performs the following steps: - /// 1. Verifies the state proof about the state root of the relaychain block - /// at the provided height. The state root is provided by the - /// `RelayChainInfo` type. - /// 2. Verifies the state proof about the DIP commitment value on the - /// provider parachain at the block finalized at the given relaychain - /// block, using the relay state root validated in the previous step. - /// 3. Verifies the DIP Merkle proof revealing parts of the subject's DID - /// Document against the retrieved DIP commitment validated in the - /// previous step. - /// 4. Verifies the cross-chain DID signature over the payload composed by - /// the SCALE-encoded tuple of `(C, D, S, B, G, E)`, with: - /// * `C`: The `RuntimeCall` to dispatch after performing DIP - /// verification. - /// * `D`: The local details associated to the DID subject as stored in - /// the [`pallet_dip_consumer`] `IdentityEntries` storage map. - /// * `S`: The tx submitter's address. - /// * `B`: The block number of the consumer chain provided in the - /// cross-chain DID signature. - /// * `G`: The genesis hash of the consumer chain. - /// * `E`: Any additional information provided by the - /// `LocalContextProvider` implementation. - /// The generic types - /// indicate the following: - /// * `RelayChainInfo`: The type providing information about the relaychain. - /// * `SiblingProviderParachainId`: The parachain ID of the provider KILT - /// sibling parachain. - /// * `SiblingProviderStateInfo`: The type providing storage and state - /// information about the provider KILT sibling parachain. - /// * `ProviderDipMerkleHasher`: The hashing algorithm used by the KILT - /// parachain for the generation of the DIP identity commitment. - /// * `ProviderDidKeyId`: The runtime type of a DID key ID as defined by the - /// KILT child parachain. - /// * `ProviderAccountId`: The runtime type of an account ID as defined by - /// the KILT child parachain. - /// * `ProviderWeb3Name`: The runtime type of a web3name as defined by the - /// KILT child parachain. - /// * `ProviderLinkedAccountId`: The runtime type of a linked account ID as - /// defined by the KILT child parachain. - /// * `MAX_REVEALED_KEYS_COUNT`: Max number of DID keys that the verifier - /// will accept revealed as part of the DIP identity proof. - /// * `MAX_REVEALED_ACCOUNTS_COUNT`: Max number of linked accounts that the - /// verifier will accept revealed as part of the DIP identity proof. - /// * `LocalContextProvider`: The type providing context of the consumer - /// chain (e.g., current block number) for the sake of cross-chain DID - /// signature verification. - /// * `LocalDidCallVerifier`: Logic to map `RuntimeCall`s to a specific DID - /// key relationship. This information is used once the Merkle proof is - /// verified, to filter only the revealed keys that match the provided - /// relationship. - #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] - pub struct ParachainVerifier< - RelayChainStateInfo, - SiblingProviderParachainId, - SiblingProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, - LocalContextProvider, - LocalDidCallVerifier, + pub struct Verifier< + RelaychainRuntime, + RelaychainStateRoot, + const PROVIDER_PARA_ID: u32, + ProviderRuntime, + SignedExtra, + DidCallVerifier, + const MAX_LEAVES_REVEALED: usize, + const SIGNATURE_VALIDITY: u32, >( - #[allow(clippy::type_complexity)] PhantomData<( - RelayChainStateInfo, - SiblingProviderParachainId, - SiblingProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - LocalContextProvider, - LocalDidCallVerifier, + RelaychainRuntime, + RelaychainStateRoot, + ProviderRuntime, + SignedExtra, + DidCallVerifier, )>, ); impl< ConsumerRuntime, - RelayChainStateInfo, - SiblingProviderParachainId, - SiblingProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, - LocalContextProvider, - LocalDidCallVerifier, + RelaychainRuntime, + RelaychainStateRoot, + const PROVIDER_PARA_ID: u32, + ProviderRuntime, + SignedExtra, + DidCallVerifier, + const MAX_LEAVES_REVEALED: usize, + const SIGNATURE_VALIDITY: u32, > IdentityProofVerifier - for ParachainVerifier< - RelayChainStateInfo, - SiblingProviderParachainId, - SiblingProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - LocalContextProvider, - LocalDidCallVerifier, + for Verifier< + RelaychainRuntime, + RelaychainStateRoot, + PROVIDER_PARA_ID, + ProviderRuntime, + SignedExtra, + DidCallVerifier, + MAX_LEAVES_REVEALED, + SIGNATURE_VALIDITY, > where - ConsumerRuntime: pallet_dip_consumer::Config, + ConsumerRuntime: + pallet_dip_consumer::Config + pallet_relay_store::Config, ConsumerRuntime::LocalIdentityInfo: Incrementable + Default, - - RelayChainStateInfo: traits::RelayChainStorageInfo + traits::RelayChainStateInfo, - OutputOf: Ord, - RelayChainStateInfo::BlockNumber: Parameter + 'static + Copy + Into + TryFrom + HasCompact, - RelayChainStateInfo::Key: AsRef<[u8]>, - - SiblingProviderParachainId: Get, - - SiblingProviderStateInfo: traits::ProviderParachainStorageInfo< - Identifier = ConsumerRuntime::Identifier, - Commitment = ProviderDipMerkleHasher::Out, - >, - OutputOf: Ord + From>, - SiblingProviderStateInfo::BlockNumber: Parameter + 'static, - SiblingProviderStateInfo::Commitment: Decode, - SiblingProviderStateInfo::Key: AsRef<[u8]>, - - LocalContextProvider: - DidSignatureVerifierContext, Hash = ConsumerRuntime::Hash>, - LocalContextProvider::SignedExtra: Encode, - LocalDidCallVerifier: DipCallOriginFilter< + RelaychainRuntime: frame_system::Config, + RelaychainStateRoot: + GetWithArg, Result = Option>>, + ProviderRuntime: + pallet_dip_provider::Config + did::Config + pallet_web3_names::Config + pallet_did_lookup::Config, + IdentityCommitmentOf: Into, + SignedExtra: GetWithoutArg, + SignedExtra::Result: Encode, + DidCallVerifier: DipCallOriginFilter< RuntimeCallOf, - OriginInfo = (DidVerificationKey, DidVerificationKeyRelationship), + OriginInfo = ( + DidVerificationKey, + DidVerificationKeyRelationship, + ), >, - - ProviderDipMerkleHasher: sp_core::Hasher, - ProviderDidKeyId: Parameter + 'static + Into, - ProviderAccountId: Parameter + 'static, - ProviderLinkedAccountId: Parameter + 'static, - ProviderWeb3Name: Parameter + 'static, { - type Error = DipParachainStateProofVerifierError< - ParachainHeadProofVerifierError, - MerkleProofError, - DidMerkleProofVerifierError, - RevealedDidKeysSignatureAndCallVerifierError, - >; + type Error = u16; type Proof = ParachainDipStateProof< - RelayChainStateInfo::BlockNumber, - BoundedBlindedValue, - RevealedDidMerkleProofLeaf< - ProviderDidKeyId, - ProviderAccountId, - SiblingProviderStateInfo::BlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, - >, + BlockNumberFor, + KeyIdOf, + ProviderRuntime::AccountId, + Web3NameOf, + LinkableAccountId, BlockNumberFor, >; - type VerificationResult = RevealedDidMerkleProofLeaves< - ProviderDidKeyId, - ProviderAccountId, - SiblingProviderStateInfo::BlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - >; + type VerificationResult = (); fn verify_proof_for_call_against_details( call: &RuntimeCallOf, - subject: &ConsumerRuntime::Identifier, - submitter: &ConsumerRuntime::AccountId, - identity_details: &mut Option, + subject: &::Identifier, + submitter: &::AccountId, + identity_details: &mut Option<::LocalIdentityInfo>, proof: Self::Proof, ) -> Result { // 1. Verify parachain state is finalized by relay chain and fresh. + let provider_head_storage_key = StorageKey( + [ + frame_support::storage::storage_prefix(b"Paras", b"Heads").as_slice(), + sp_io::hashing::twox_64(PROVIDER_PARA_ID.encode().as_ref()).as_slice(), + PROVIDER_PARA_ID.encode().as_slice(), + ] + .concat(), + ); + let relaychain_root_at_proof_block = RelaychainStateRoot::get(&proof.para_state_root.relay_block_height) + .expect("No relaychain block found for given height."); let provider_parachain_header = - ParachainHeadProofVerifier::::verify_proof_for_parachain( - &SiblingProviderParachainId::get(), - &proof.para_state_root.relay_block_height, + verify_storage_value_proof::<_, RelaychainRuntime::Hashing, HeaderFor>( + &provider_head_storage_key, + relaychain_root_at_proof_block, proof.para_state_root.proof, ) - .map_err(DipParachainStateProofVerifierError::ParachainHeadMerkleProof)?; - - Ok(Default::default()) - - // // 2. Verify commitment is included in provider parachain. - // let subject_identity_commitment = - // DipIdentityCommitmentProofVerifier::::verify_proof_for_identifier( - // subject, - // provider_parachain_header.state_root.into(), - // proof.dip_identity_commitment, - // ) - // .map_err(DipParachainStateProofVerifierError::IdentityCommitmentMerkleProof)?; - - // // 3. Verify DIP merkle proof. - // let proof_leaves: RevealedDidMerkleProofLeaves< - // ProviderDidKeyId, - // ProviderAccountId, - // ::BlockNumber, ProviderWeb3Name, - // ProviderLinkedAccountId, - // MAX_REVEALED_KEYS_COUNT, - // MAX_REVEALED_ACCOUNTS_COUNT, - // > = verify_dip_merkle_proof::< - // ProviderDipMerkleHasher, - // _, - // _, - // _, - // _, - // _, - // MAX_REVEALED_KEYS_COUNT, - // MAX_REVEALED_ACCOUNTS_COUNT, - // >(&subject_identity_commitment, proof.did.leaves) - // .map_err(DipParachainStateProofVerifierError::DipProof)?; - - // // 4. Verify call is signed by one of the DID keys revealed at - // step 3. verify_did_signature_for_call::<_, _, _, _, - // LocalContextProvider, _, _, _, LocalDidCallVerifier>( call, - // submitter, - // identity_details, - // RevealedDidKeysAndSignature { - // merkle_leaves: proof_leaves.borrow(), - // did_signature: proof.did.signature, - // }, - // ) - // .map_err(DipParachainStateProofVerifierError::DidSignature)?; - - // Ok(proof_leaves) + .expect("Proof verification failed"); + + // 2. Verify commitment is included in provider parachain. + let dip_commitment_storage_key = + StorageKey(pallet_dip_provider::IdentityCommitments::::hashed_key_for(subject, 0)); + let dip_commitment = + verify_storage_value_proof::<_, ProviderRuntime::Hashing, IdentityCommitmentOf>( + &dip_commitment_storage_key, + *provider_parachain_header.state_root(), + proof.dip_identity_commitment, + ) + .expect("Failed to verify DIP Merkle proof."); + + let dip_proof = proof.did.leaves; + + // 3. Verify DIP merkle proof. + dip_proof + .verify_against_commitment::(&dip_commitment.into(), MAX_LEAVES_REVEALED) + .unwrap_or_else(|_| panic!("Failed to verify DIP Merkle proof")); + + // 4. Verify call is signed by one of the DID keys revealed at step 3. + let current_block_number = frame_system::Pallet::::block_number(); + let did_signature = proof + .did + .signature + .verify_time_bounds(current_block_number, SIGNATURE_VALIDITY.into()) + .unwrap_or_else(|_| panic!("Signature is not fresh.")); + + // Block number removed from the signature + let consumer_genesis_hash = + frame_system::Pallet::::block_hash(BlockNumberFor::::zero()); + let signed_extra = SignedExtra::get(); + let encoded_payload = (call, &identity_details, submitter, consumer_genesis_hash, signed_extra).encode(); + let revealed_leaves = dip_proof.revealed; + + let mut revealed_did_verification_keys = revealed_leaves.iter().filter_map(|leaf| { + // Skip if the leaf is not a DID key leaf. + let RevealedDidMerkleProofLeaf::DidKey(did_key) = leaf else { + return None; + }; + // Skip if the DID key is not a verification key. + let DidPublicKey::PublicVerificationKey(ref verification_key) = did_key.details.key else { return None }; + let Ok(verification_relationship) = DidVerificationKeyRelationship::try_from(did_key.relationship) else { + log::error!("Should never fail to build a VerificationRelationship from the given DidKeyRelationship because we have already made sure the conditions hold."); + panic!("Should never fail to build a VerificationRelationship from the given DidKeyRelationship because we have already made sure the conditions hold."); + }; + // Returns (key ID, the verified verification relationship, the verified public verification key). + Some((did_key.id, verification_relationship, verification_key)) + }); + + let signing_key_details = revealed_did_verification_keys.find(|(_, _, public_verification_key)| { + public_verification_key + .verify_signature(&encoded_payload, &did_signature) + .is_ok() + }); + + let Some((_, key_relationship, key_details)) = signing_key_details else { + panic!("Did not find a valid signing key in the Merkle proof."); + }; + + // Increment the local details + if let Some(details) = identity_details { + details.increment(); + } else { + *identity_details = Some(Default::default()); + }; + + DidCallVerifier::check_call_origin_info(call, &(key_details.clone(), key_relationship)) + .unwrap_or_else(|_| panic!("Failed to verify DID call info.")); + + Ok(()) } } } diff --git a/nodes/parachain/src/chain_spec/clone.rs b/nodes/parachain/src/chain_spec/clone.rs index 0330ec5452..60562c444d 100644 --- a/nodes/parachain/src/chain_spec/clone.rs +++ b/nodes/parachain/src/chain_spec/clone.rs @@ -22,14 +22,12 @@ use cumulus_primitives_core::ParaId; use hex_literal::hex; use runtime_common::constants::KILT; use sc_chain_spec::ChainType; -use sp_core::crypto::UncheckedInto; -use sp_core::sr25519; +use sp_core::{crypto::UncheckedInto, sr25519}; use clone_runtime::{ - BalancesConfig, ParachainInfoConfig, PolkadotXcmConfig, RuntimeGenesisConfig, SessionConfig, SudoConfig, - SystemConfig, + BalancesConfig, CollatorSelectionConfig, ParachainInfoConfig, PolkadotXcmConfig, RuntimeGenesisConfig, + SessionConfig, SudoConfig, SystemConfig, WASM_BINARY, }; -use clone_runtime::{CollatorSelectionConfig, WASM_BINARY}; use runtime_common::{AccountId, AuthorityId, Balance}; use super::{get_account_id_from_seed, get_from_seed, get_properties, DEFAULT_PARA_ID}; diff --git a/runtimes/clone/src/lib.rs b/runtimes/clone/src/lib.rs index 4b17ae160f..a0a04bd79a 100644 --- a/runtimes/clone/src/lib.rs +++ b/runtimes/clone/src/lib.rs @@ -26,11 +26,11 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; -use frame_support::PalletId; use frame_support::{ construct_runtime, parameter_types, traits::Everything, weights::{ConstantMultiplier, Weight}, + PalletId, }; use frame_system::EnsureRoot; use pallet_transaction_payment::CurrencyAdapter; From 470dd5347d863c43a6d02a761efb8a59529f0f00 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 11 Jan 2024 12:13:24 +0100 Subject: [PATCH 05/45] A lot of progress --- crates/kilt-dip-primitives/src/did.rs | 42 +++------- crates/kilt-dip-primitives/src/merkle.rs | 18 ++-- .../src/verifier/common.rs | 84 ++++++++++++++++++- .../src/verifier/parachain.rs | 4 +- 4 files changed, 102 insertions(+), 46 deletions(-) diff --git a/crates/kilt-dip-primitives/src/did.rs b/crates/kilt-dip-primitives/src/did.rs index 1d033174fe..b0ee3ed88b 100644 --- a/crates/kilt-dip-primitives/src/did.rs +++ b/crates/kilt-dip-primitives/src/did.rs @@ -23,40 +23,30 @@ use frame_support::ensure; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_core::RuntimeDebug; -use sp_runtime::traits::CheckedSub; /// A DID signature anchored to a specific block height. #[derive(Encode, Decode, RuntimeDebug, Clone, Eq, PartialEq, TypeInfo)] pub struct TimeBoundDidSignature { /// The signature. pub signature: DidSignature, - /// The block number, in the context of the local executor, to which the - /// signature is anchored. - pub block_number: BlockNumber, + /// The block number until the signature is to be considered valid. + pub valid_until: BlockNumber, } impl TimeBoundDidSignature where - BlockNumber: CheckedSub + Ord, + BlockNumber: PartialOrd, { - /// Verifies the time bounds of the DID signatures and returns the signature + /// Verifies if the DID signature is expired and returns the signature /// information after stripping time-related information. - pub fn verify_time_bounds( + pub fn extract_signature_if_not_expired( self, current_block_number: BlockNumber, - max_offset: BlockNumber, ) -> Result { - let signature_block_number = self.block_number; - - let is_signature_fresh = - if let Some(blocks_ago_from_now) = current_block_number.checked_sub(&signature_block_number) { - // False if the signature is too old. - blocks_ago_from_now <= max_offset - } else { - // Signature generated for a future time, not possible to verify. - false - }; - ensure!(is_signature_fresh, DidSignatureVerificationError::SignatureNotFresh); + ensure!( + self.valid_until >= current_block_number, + DidSignatureVerificationError::SignatureExpired + ); Ok(self.signature) } @@ -71,21 +61,11 @@ where fn worst_case(context: Context) -> Self { Self { signature: DidSignature::worst_case(context), - block_number: BlockNumber::default(), + valid_until: BlockNumber::default(), } } } pub enum DidSignatureVerificationError { - SignatureNotFresh, - SignatureUnverifiable, -} - -impl From for u8 { - fn from(value: DidSignatureVerificationError) -> Self { - match value { - DidSignatureVerificationError::SignatureNotFresh => 1, - DidSignatureVerificationError::SignatureUnverifiable => 2, - } - } + SignatureExpired, } diff --git a/crates/kilt-dip-primitives/src/merkle.rs b/crates/kilt-dip-primitives/src/merkle.rs index 367ca69db3..a0e5fb06b2 100644 --- a/crates/kilt-dip-primitives/src/merkle.rs +++ b/crates/kilt-dip-primitives/src/merkle.rs @@ -68,10 +68,13 @@ where /// * `Hasher`: The hasher used by the producer to hash the Merkle leaves /// and produce the identity commitment. pub fn verify_against_commitment( - &self, + self, commitment: &OutputOf, max_leaves_revealed: usize, - ) -> Result<(), DidMerkleProofVerificationError> + ) -> Result< + impl IntoIterator>, + DidMerkleProofVerificationError, + > where Hasher: Hash, { @@ -89,7 +92,7 @@ where verify_trie_proof::, _, _, _>(commitment, &self.blinded, &proof_leaves_key_value_pairs) .map_err(|_| DidMerkleProofVerificationError::InvalidMerkleProof)?; - Ok(()) + Ok(self.revealed) } } @@ -236,12 +239,3 @@ pub enum DidMerkleProofVerificationError { InvalidMerkleProof, TooManyLeaves, } - -impl From for u8 { - fn from(value: DidMerkleProofVerificationError) -> Self { - match value { - DidMerkleProofVerificationError::InvalidMerkleProof => 1, - DidMerkleProofVerificationError::TooManyLeaves => 2, - } - } -} diff --git a/crates/kilt-dip-primitives/src/verifier/common.rs b/crates/kilt-dip-primitives/src/verifier/common.rs index bc4fce0911..79ca04c18d 100644 --- a/crates/kilt-dip-primitives/src/verifier/common.rs +++ b/crates/kilt-dip-primitives/src/verifier/common.rs @@ -21,11 +21,24 @@ pub mod latest { } pub mod v0 { + use did::{ + did_details::{DidPublicKey, DidVerificationKey}, + DidVerificationKeyRelationship, + }; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_core::RuntimeDebug; + use sp_runtime::traits::Hash; - use crate::{did::TimeBoundDidSignature, merkle::DidMerkleProof, BoundedBlindedValue}; + use crate::{ + did::{DidSignatureVerificationError, TimeBoundDidSignature}, + merkle::{ + DidKeyRelationship, DidMerkleProof, DidMerkleProofVerificationError, RevealedDidKey, + RevealedDidMerkleProofLeaf, + }, + utils::OutputOf, + BoundedBlindedValue, + }; #[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, Clone)] pub struct ParachainRootStateProof { @@ -57,4 +70,73 @@ pub mod v0 { /// The cross-chain DID signature. pub(crate) signature: TimeBoundDidSignature, } + + impl + DipMerkleProofAndDidSignature + where + KeyId: Encode, + AccountId: Encode, + BlockNumber: Encode, + Web3Name: Encode, + LinkedAccountId: Encode, + { + pub fn verify_against_commitment( + self, + commitment: &OutputOf, + max_leaves_revealed: usize, + ) -> Result< + impl IntoIterator>, + DidMerkleProofVerificationError, + > + where + Hasher: Hash, + { + self.leaves + .verify_against_commitment::(commitment, max_leaves_revealed) + } + } + + pub struct RevealedLeavesAndDidSignature { + pub(crate) leaves: Vec>, + pub(crate) signature: TimeBoundDidSignature, + } + + impl + RevealedLeavesAndDidSignature + where + BlockNumber: PartialOrd, + { + pub fn extract_signing_key_for_payload( + &self, + payload: &[u8], + current_block_number: BlockNumber, + ) -> Result>, DidSignatureVerificationError> { + let signature = self.signature.extract_signature_if_not_expired(current_block_number)?; + + let mut revealed_did_verification_keys = self.leaves.iter().filter_map(|leaf| { + // Skip if the leaf is not a DID key leaf. + let RevealedDidMerkleProofLeaf::DidKey(did_key) = leaf else { + return None; + }; + // Skip if the DID key is not a verification key. + let DidPublicKey::PublicVerificationKey(_) = did_key.details.key else { + return None; + }; + // Skip if the verification relationship is not for signatures (should never + // fail, but we check just to be sure). + let DidKeyRelationship::Verification(_) = did_key.relationship else { + return None; + }; + Some(did_key) + }); + + let maybe_signing_key_details = revealed_did_verification_keys.find(|did_key| { + let DidPublicKey::PublicVerificationKey(ref mapped_key) = did_key.details.key else { + return false; + }; + mapped_key.verify_signature(payload, &signature).is_ok() + }); + Ok(maybe_signing_key_details) + } + } } diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index a0b2ec1dea..2c182f317b 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -255,7 +255,7 @@ impl< } pub mod latest { - // pub use super::v0::ParachainDipStateProof; + pub use super::v0::ParachainDipStateProof; } pub mod v0 { @@ -415,7 +415,7 @@ pub mod v0 { let did_signature = proof .did .signature - .verify_time_bounds(current_block_number, SIGNATURE_VALIDITY.into()) + .extract_signature_if_not_expired(current_block_number) .unwrap_or_else(|_| panic!("Signature is not fresh.")); // Block number removed from the signature From 147ffbc22f4db3b5a2b37695e5592f9978db5afb Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 11 Jan 2024 15:01:25 +0100 Subject: [PATCH 06/45] Compiling again --- .../src/verifier/common.rs | 43 +++++----- .../src/verifier/parachain.rs | 78 +++++++------------ 2 files changed, 54 insertions(+), 67 deletions(-) diff --git a/crates/kilt-dip-primitives/src/verifier/common.rs b/crates/kilt-dip-primitives/src/verifier/common.rs index 79ca04c18d..753a9a8e2a 100644 --- a/crates/kilt-dip-primitives/src/verifier/common.rs +++ b/crates/kilt-dip-primitives/src/verifier/common.rs @@ -21,10 +21,7 @@ pub mod latest { } pub mod v0 { - use did::{ - did_details::{DidPublicKey, DidVerificationKey}, - DidVerificationKeyRelationship, - }; + use did::did_details::DidPublicKey; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_core::RuntimeDebug; @@ -63,16 +60,16 @@ pub mod v0 { } #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)] - pub struct DipMerkleProofAndDidSignature { + pub struct DipMerkleProofAndDidSignature { /// The DIP Merkle proof revealing some leaves about the DID subject's /// identity. pub(crate) leaves: DidMerkleProof, /// The cross-chain DID signature. - pub(crate) signature: TimeBoundDidSignature, + pub(crate) signature: TimeBoundDidSignature, } - impl - DipMerkleProofAndDidSignature + impl + DipMerkleProofAndDidSignature where KeyId: Encode, AccountId: Encode, @@ -80,38 +77,46 @@ pub mod v0 { Web3Name: Encode, LinkedAccountId: Encode, { - pub fn verify_against_commitment( + pub fn verify_merkle_proof_against_commitment( self, commitment: &OutputOf, max_leaves_revealed: usize, ) -> Result< - impl IntoIterator>, + RevealedLeavesAndDidSignature, DidMerkleProofVerificationError, > where Hasher: Hash, { - self.leaves - .verify_against_commitment::(commitment, max_leaves_revealed) + let revealed_leaves = self + .leaves + .verify_against_commitment::(commitment, max_leaves_revealed)?; + Ok(RevealedLeavesAndDidSignature { + signature: self.signature, + leaves: revealed_leaves.into_iter().collect(), + }) } } - pub struct RevealedLeavesAndDidSignature { + pub struct RevealedLeavesAndDidSignature { pub(crate) leaves: Vec>, - pub(crate) signature: TimeBoundDidSignature, + pub(crate) signature: TimeBoundDidSignature, } - impl - RevealedLeavesAndDidSignature + impl + RevealedLeavesAndDidSignature where - BlockNumber: PartialOrd, + LocalBlockNumber: PartialOrd + Clone, { pub fn extract_signing_key_for_payload( &self, payload: &[u8], - current_block_number: BlockNumber, + current_block_number: LocalBlockNumber, ) -> Result>, DidSignatureVerificationError> { - let signature = self.signature.extract_signature_if_not_expired(current_block_number)?; + let signature = self + .signature + .clone() + .extract_signature_if_not_expired(current_block_number)?; let mut revealed_did_verification_keys = self.leaves.iter().filter_map(|leaf| { // Skip if the leaf is not a DID key leaf. diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 2c182f317b..63490ed9e9 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -16,7 +16,7 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -use did::{did_details::DidVerificationKey, DidVerificationKeyRelationship, KeyIdOf}; +use did::KeyIdOf; use frame_system::pallet_prelude::BlockNumberFor; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_consumer::{traits::IdentityProofVerifier, RuntimeCallOf}; @@ -28,7 +28,7 @@ use sp_core::RuntimeDebug; use sp_std::marker::PhantomData; use crate::{ - merkle::RevealedDidMerkleProofLeaf, + merkle::RevealedDidKey, traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, BoundedBlindedValue, @@ -44,6 +44,7 @@ pub enum VersionedDipParachainStateProof< ProviderKeyId, ProviderAccountId, ProviderWeb3Name, + ProviderBlockNumber, ProviderLinkedAccountId, LocalBlockNumber, > { @@ -53,6 +54,7 @@ pub enum VersionedDipParachainStateProof< ProviderKeyId, ProviderAccountId, ProviderWeb3Name, + ProviderBlockNumber, ProviderLinkedAccountId, LocalBlockNumber, >, @@ -209,10 +211,7 @@ impl< SignedExtra::Result: Encode, DidCallVerifier: DipCallOriginFilter< RuntimeCallOf, - OriginInfo = ( - DidVerificationKey, - DidVerificationKeyRelationship, - ), + OriginInfo = RevealedDidKey, BlockNumberFor, KiltRuntime::AccountId>, >, { type Error = u16; @@ -220,6 +219,7 @@ impl< BlockNumberFor, KeyIdOf, KiltRuntime::AccountId, + BlockNumberFor, Web3NameOf, LinkableAccountId, BlockNumberFor, @@ -261,13 +261,13 @@ pub mod latest { pub mod v0 { use super::*; - use did::did_details::DidPublicKey; use frame_system::pallet_prelude::HeaderFor; use pallet_web3_names::Web3NameOf; use sp_core::storage::StorageKey; use sp_runtime::traits::{Header, Zero}; use crate::{ + merkle::RevealedDidKey, state_proofs::verify_storage_value_proof, verifier::common::v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof}, }; @@ -281,6 +281,7 @@ pub mod v0 { RelayBlockHeight, ProviderKeyId, ProviderAccountId, + ProviderBlockNumber, ProviderWeb3Name, ProviderLinkedAccountId, LocalBlockNumber, @@ -290,9 +291,10 @@ pub mod v0 { pub(crate) did: DipMerkleProofAndDidSignature< ProviderKeyId, ProviderAccountId, - LocalBlockNumber, + ProviderBlockNumber, ProviderWeb3Name, ProviderLinkedAccountId, + LocalBlockNumber, >, } @@ -349,10 +351,11 @@ pub mod v0 { SignedExtra::Result: Encode, DidCallVerifier: DipCallOriginFilter< RuntimeCallOf, - OriginInfo = ( - DidVerificationKey, - DidVerificationKeyRelationship, - ), + OriginInfo = RevealedDidKey< + KeyIdOf, + BlockNumberFor, + ProviderRuntime::AccountId, + >, >, { type Error = u16; @@ -360,10 +363,12 @@ pub mod v0 { BlockNumberFor, KeyIdOf, ProviderRuntime::AccountId, + BlockNumberFor, Web3NameOf, LinkableAccountId, BlockNumberFor, >; + type VerificationResult = (); fn verify_proof_for_call_against_details( @@ -403,51 +408,28 @@ pub mod v0 { ) .expect("Failed to verify DIP Merkle proof."); - let dip_proof = proof.did.leaves; + let did_proof = proof.did; - // 3. Verify DIP merkle proof. - dip_proof - .verify_against_commitment::(&dip_commitment.into(), MAX_LEAVES_REVEALED) + // 3. Verify DIP Merkle proof. + let verified_proof = did_proof + .verify_merkle_proof_against_commitment::( + &dip_commitment.into(), + MAX_LEAVES_REVEALED, + ) .unwrap_or_else(|_| panic!("Failed to verify DIP Merkle proof")); // 4. Verify call is signed by one of the DID keys revealed at step 3. let current_block_number = frame_system::Pallet::::block_number(); - let did_signature = proof - .did - .signature - .extract_signature_if_not_expired(current_block_number) - .unwrap_or_else(|_| panic!("Signature is not fresh.")); - - // Block number removed from the signature let consumer_genesis_hash = frame_system::Pallet::::block_hash(BlockNumberFor::::zero()); let signed_extra = SignedExtra::get(); let encoded_payload = (call, &identity_details, submitter, consumer_genesis_hash, signed_extra).encode(); - let revealed_leaves = dip_proof.revealed; - - let mut revealed_did_verification_keys = revealed_leaves.iter().filter_map(|leaf| { - // Skip if the leaf is not a DID key leaf. - let RevealedDidMerkleProofLeaf::DidKey(did_key) = leaf else { - return None; - }; - // Skip if the DID key is not a verification key. - let DidPublicKey::PublicVerificationKey(ref verification_key) = did_key.details.key else { return None }; - let Ok(verification_relationship) = DidVerificationKeyRelationship::try_from(did_key.relationship) else { - log::error!("Should never fail to build a VerificationRelationship from the given DidKeyRelationship because we have already made sure the conditions hold."); - panic!("Should never fail to build a VerificationRelationship from the given DidKeyRelationship because we have already made sure the conditions hold."); - }; - // Returns (key ID, the verified verification relationship, the verified public verification key). - Some((did_key.id, verification_relationship, verification_key)) - }); - - let signing_key_details = revealed_did_verification_keys.find(|(_, _, public_verification_key)| { - public_verification_key - .verify_signature(&encoded_payload, &did_signature) - .is_ok() - }); + let signing_key = verified_proof + .extract_signing_key_for_payload(&encoded_payload[..], current_block_number) + .unwrap_or_else(|_| panic!("Signature is not fresh.")); - let Some((_, key_relationship, key_details)) = signing_key_details else { - panic!("Did not find a valid signing key in the Merkle proof."); + let Some(signing_key) = signing_key else { + panic!("No key found."); }; // Increment the local details @@ -457,7 +439,7 @@ pub mod v0 { *identity_details = Some(Default::default()); }; - DidCallVerifier::check_call_origin_info(call, &(key_details.clone(), key_relationship)) + DidCallVerifier::check_call_origin_info(call, signing_key) .unwrap_or_else(|_| panic!("Failed to verify DID call info.")); Ok(()) From b1b660dd18efb46bc15506769b0b6b24f5f38dca Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 11 Jan 2024 15:27:06 +0100 Subject: [PATCH 07/45] Compiling again --- .../src/verifier/common.rs | 27 +++++++++++++++++++ .../src/verifier/parachain.rs | 17 +++++------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/crates/kilt-dip-primitives/src/verifier/common.rs b/crates/kilt-dip-primitives/src/verifier/common.rs index 753a9a8e2a..17137c0ec2 100644 --- a/crates/kilt-dip-primitives/src/verifier/common.rs +++ b/crates/kilt-dip-primitives/src/verifier/common.rs @@ -16,6 +16,10 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org +use pallet_dip_provider::IdentityCommitmentVersion; +use parity_scale_codec::Encode; +use sp_core::storage::StorageKey; + pub mod latest { pub use super::v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof}; } @@ -145,3 +149,26 @@ pub mod v0 { } } } + +pub(crate) fn calculate_parachain_head_storage_key(para_id: u32) -> StorageKey { + StorageKey( + [ + frame_support::storage::storage_prefix(b"Paras", b"Heads").as_slice(), + sp_io::hashing::twox_64(para_id.encode().as_ref()).as_slice(), + para_id.encode().as_slice(), + ] + .concat(), + ) +} + +pub(crate) fn calculate_dip_identity_commitment_storage_key_for_runtime( + subject: &Runtime::Identifier, + version: IdentityCommitmentVersion, +) -> StorageKey +where + Runtime: pallet_dip_provider::Config, +{ + StorageKey(pallet_dip_provider::IdentityCommitments::::hashed_key_for( + subject, version, + )) +} diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 63490ed9e9..662df74e83 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -263,13 +263,15 @@ pub mod v0 { use frame_system::pallet_prelude::HeaderFor; use pallet_web3_names::Web3NameOf; - use sp_core::storage::StorageKey; use sp_runtime::traits::{Header, Zero}; use crate::{ merkle::RevealedDidKey, state_proofs::verify_storage_value_proof, - verifier::common::v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof}, + verifier::common::{ + calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key, + v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof}, + }, }; /// The expected format of a cross-chain DIP identity proof when the @@ -379,14 +381,7 @@ pub mod v0 { proof: Self::Proof, ) -> Result { // 1. Verify parachain state is finalized by relay chain and fresh. - let provider_head_storage_key = StorageKey( - [ - frame_support::storage::storage_prefix(b"Paras", b"Heads").as_slice(), - sp_io::hashing::twox_64(PROVIDER_PARA_ID.encode().as_ref()).as_slice(), - PROVIDER_PARA_ID.encode().as_slice(), - ] - .concat(), - ); + let provider_head_storage_key = calculate_parachain_head_storage_key(PROVIDER_PARA_ID); let relaychain_root_at_proof_block = RelaychainStateRoot::get(&proof.para_state_root.relay_block_height) .expect("No relaychain block found for given height."); let provider_parachain_header = @@ -399,7 +394,7 @@ pub mod v0 { // 2. Verify commitment is included in provider parachain. let dip_commitment_storage_key = - StorageKey(pallet_dip_provider::IdentityCommitments::::hashed_key_for(subject, 0)); + calculate_dip_identity_commitment_storage_key_for_runtime::(subject, 0); let dip_commitment = verify_storage_value_proof::<_, ProviderRuntime::Hashing, IdentityCommitmentOf>( &dip_commitment_storage_key, From 37ffe78b7f5e0667158a983aff190b59f25e8abd Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 11 Jan 2024 15:47:58 +0100 Subject: [PATCH 08/45] Wip --- .../src/verifier/parachain.rs | 6 +++--- .../src/verifier/relaychain.rs | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 662df74e83..de6710194b 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -234,7 +234,7 @@ impl< proof: Self::Proof, ) -> Result { match proof { - VersionedDipParachainStateProof::V0(v0_proof) => , } - pub struct Verifier< + pub struct ParachainVerifier< RelaychainRuntime, RelaychainStateRoot, const PROVIDER_PARA_ID: u32, @@ -330,7 +330,7 @@ pub mod v0 { const MAX_LEAVES_REVEALED: usize, const SIGNATURE_VALIDITY: u32, > IdentityProofVerifier - for Verifier< + for ParachainVerifier< RelaychainRuntime, RelaychainStateRoot, PROVIDER_PARA_ID, diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index 32989c6e51..e8553cf234 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -521,8 +521,11 @@ pub mod v0 { pub struct RelaychainDipStateProof< ParentBlockHeight: Copy + Into + TryFrom, ParentBlockHasher: Hash, - DipMerkleProofBlindedValues, - DipMerkleProofRevealedLeaf, + ProviderKeyId, + ProviderAccountId, + ProviderBlockNumber, + ProviderWeb3Name, + ProviderLinkedAccountId, > { /// The state proof for the given parachain head. para_state_root: ParachainRootStateProof, @@ -530,9 +533,16 @@ pub mod v0 { /// `para_state_root`. relay_header: Header, /// The raw state proof for the DIP commitment of the given subject. - dip_identity_commitment: Vec>, + dip_identity_commitment: BoundedBlindedValue, /// The cross-chain DID signature. - did: DipMerkleProofAndDidSignature, + did: DipMerkleProofAndDidSignature< + ProviderKeyId, + ProviderAccountId, + ProviderBlockNumber, + ProviderWeb3Name, + ProviderLinkedAccountId, + ParentBlockHeight, + >, } /// Generic proof verifier for KILT-specific DIP identity proofs coming from From bcdaa98b548c39995281efbf760589225efa79db Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 12 Jan 2024 11:52:41 +0100 Subject: [PATCH 09/45] kilt-dip-primitives compiling --- crates/kilt-dip-primitives/src/did.rs | 10 + crates/kilt-dip-primitives/src/merkle.rs | 9 + .../src/verifier/common.rs | 18 +- .../kilt-dip-primitives/src/verifier/mod.rs | 10 +- .../src/verifier/parachain.rs | 287 ++++--- .../src/verifier/relaychain.rs | 761 ++++++------------ 6 files changed, 400 insertions(+), 695 deletions(-) diff --git a/crates/kilt-dip-primitives/src/did.rs b/crates/kilt-dip-primitives/src/did.rs index b0ee3ed88b..f426ee63ae 100644 --- a/crates/kilt-dip-primitives/src/did.rs +++ b/crates/kilt-dip-primitives/src/did.rs @@ -68,4 +68,14 @@ where pub enum DidSignatureVerificationError { SignatureExpired, + SignerNotFound, +} + +impl From for u8 { + fn from(value: DidSignatureVerificationError) -> Self { + match value { + DidSignatureVerificationError::SignatureExpired => 1, + DidSignatureVerificationError::SignerNotFound => 2, + } + } } diff --git a/crates/kilt-dip-primitives/src/merkle.rs b/crates/kilt-dip-primitives/src/merkle.rs index a0e5fb06b2..71a40afd62 100644 --- a/crates/kilt-dip-primitives/src/merkle.rs +++ b/crates/kilt-dip-primitives/src/merkle.rs @@ -239,3 +239,12 @@ pub enum DidMerkleProofVerificationError { InvalidMerkleProof, TooManyLeaves, } + +impl From for u8 { + fn from(value: DidMerkleProofVerificationError) -> Self { + match value { + DidMerkleProofVerificationError::InvalidMerkleProof => 1, + DidMerkleProofVerificationError::TooManyLeaves => 2, + } + } +} diff --git a/crates/kilt-dip-primitives/src/verifier/common.rs b/crates/kilt-dip-primitives/src/verifier/common.rs index 17137c0ec2..925981ad9a 100644 --- a/crates/kilt-dip-primitives/src/verifier/common.rs +++ b/crates/kilt-dip-primitives/src/verifier/common.rs @@ -116,7 +116,7 @@ pub mod v0 { &self, payload: &[u8], current_block_number: LocalBlockNumber, - ) -> Result>, DidSignatureVerificationError> { + ) -> Result<&RevealedDidKey, DidSignatureVerificationError> { let signature = self .signature .clone() @@ -139,13 +139,15 @@ pub mod v0 { Some(did_key) }); - let maybe_signing_key_details = revealed_did_verification_keys.find(|did_key| { - let DidPublicKey::PublicVerificationKey(ref mapped_key) = did_key.details.key else { - return false; - }; - mapped_key.verify_signature(payload, &signature).is_ok() - }); - Ok(maybe_signing_key_details) + let signing_key_details = revealed_did_verification_keys + .find(|did_key| { + let DidPublicKey::PublicVerificationKey(ref mapped_key) = did_key.details.key else { + return false; + }; + mapped_key.verify_signature(payload, &signature).is_ok() + }) + .ok_or(DidSignatureVerificationError::SignerNotFound)?; + Ok(signing_key_details) } } } diff --git a/crates/kilt-dip-primitives/src/verifier/mod.rs b/crates/kilt-dip-primitives/src/verifier/mod.rs index 88c86fcd04..f98576991d 100644 --- a/crates/kilt-dip-primitives/src/verifier/mod.rs +++ b/crates/kilt-dip-primitives/src/verifier/mod.rs @@ -21,14 +21,16 @@ mod common; /// Verification logic to integrate a sibling chain as a DIP provider. pub mod parachain; +/// Verification logic to integrate a child chain as a DIP provider. +pub mod relaychain; pub use parachain::{ DipParachainStateProofVerifierError, KiltVersionedParachainVerifier, VersionedDipParachainStateProof, }; -// pub use relaychain::{ -// DipRelaychainStateProofVerifierError, KiltVersionedRelaychainVerifier, -// VersionedRelaychainStateProof, }; +pub use relaychain::{ + DipRelaychainStateProofVerifierError, KiltVersionedRelaychainVerifier, VersionedRelaychainStateProof, +}; pub mod latest { - pub use super::{common::latest::*, parachain::latest::*}; + pub use super::{common::latest::*, parachain::latest::*, relaychain::latest::*}; } diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index de6710194b..c676f2681b 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -24,11 +24,14 @@ use pallet_dip_provider::IdentityCommitmentOf; use pallet_web3_names::Web3NameOf; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_core::RuntimeDebug; +use sp_core::{ConstU32, RuntimeDebug}; +use sp_runtime::BoundedVec; use sp_std::marker::PhantomData; use crate::{ - merkle::RevealedDidKey, + did::DidSignatureVerificationError, + merkle::{DidMerkleProofVerificationError, RevealedDidKey, RevealedDidMerkleProofLeaf}, + state_proofs::MerkleProofError, traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, BoundedBlindedValue, @@ -40,78 +43,56 @@ use crate::{ /// For more info, refer to the version-specific proofs. #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)] pub enum VersionedDipParachainStateProof< - RelayBlockHeight, - ProviderKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderBlockNumber, - ProviderLinkedAccountId, - LocalBlockNumber, + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltWeb3Name, + KiltBlockNumber, + KiltLinkableAccountId, + ConsumerBlockNumber, > { V0( v0::ParachainDipStateProof< - RelayBlockHeight, - ProviderKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderBlockNumber, - ProviderLinkedAccountId, - LocalBlockNumber, + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltWeb3Name, + KiltBlockNumber, + KiltLinkableAccountId, + ConsumerBlockNumber, >, ), } -pub enum DipParachainStateProofVerifierError< - ParachainHeadMerkleProofVerificationError, - IdentityCommitmentMerkleProofVerificationError, - DipProofVerificationError, - DidSignatureVerificationError, -> { +pub enum DipParachainStateProofVerifierError { UnsupportedVersion, - ParachainHeadMerkleProof(ParachainHeadMerkleProofVerificationError), - IdentityCommitmentMerkleProof(IdentityCommitmentMerkleProofVerificationError), - DipProof(DipProofVerificationError), + RelaychainStateRootNotFound, + ParachainHeadMerkleProof(MerkleProofError), + IdentityCommitmentMerkleProof(MerkleProofError), + DipProof(DidMerkleProofVerificationError), DidSignature(DidSignatureVerificationError), + DidOriginError(DidOriginError), + Internal, } -impl< - ParachainHeadMerkleProofVerificationError, - IdentityCommitmentMerkleProofVerificationError, - DipProofVerificationError, - DidSignatureVerificationError, - > - From< - DipParachainStateProofVerifierError< - ParachainHeadMerkleProofVerificationError, - IdentityCommitmentMerkleProofVerificationError, - DipProofVerificationError, - DidSignatureVerificationError, - >, - > for u16 +impl From> for u16 where - ParachainHeadMerkleProofVerificationError: Into, - IdentityCommitmentMerkleProofVerificationError: Into, - DipProofVerificationError: Into, - DidSignatureVerificationError: Into, + DidOriginError: Into, { - fn from( - value: DipParachainStateProofVerifierError< - ParachainHeadMerkleProofVerificationError, - IdentityCommitmentMerkleProofVerificationError, - DipProofVerificationError, - DidSignatureVerificationError, - >, - ) -> Self { + fn from(value: DipParachainStateProofVerifierError) -> Self { match value { DipParachainStateProofVerifierError::UnsupportedVersion => 1, + DipParachainStateProofVerifierError::RelaychainStateRootNotFound => 2, DipParachainStateProofVerifierError::ParachainHeadMerkleProof(error) => { - u8::MAX as u16 + error.into() as u16 + u8::MAX as u16 + u8::from(error) as u16 } DipParachainStateProofVerifierError::IdentityCommitmentMerkleProof(error) => { - u8::MAX as u16 * 2 + error.into() as u16 + u8::MAX as u16 * 2 + u8::from(error) as u16 } - DipParachainStateProofVerifierError::DipProof(error) => u8::MAX as u16 * 3 + error.into() as u16, - DipParachainStateProofVerifierError::DidSignature(error) => u8::MAX as u16 * 4 + error.into() as u16, + DipParachainStateProofVerifierError::DipProof(error) => u8::MAX as u16 * 3 + u8::from(error) as u16, + DipParachainStateProofVerifierError::DidSignature(error) => u8::MAX as u16 * 4 + u8::from(error) as u16, + DipParachainStateProofVerifierError::DidOriginError(error) => u8::MAX as u16 * 5 + error.into() as u16, + DipParachainStateProofVerifierError::Internal => u16::MAX, } } } @@ -151,9 +132,9 @@ where /// * `ProviderDipMerkleHasher`: The provided `KiltDipMerkleHasher`. /// * `ProviderDidKeyId`: The [`KeyIdOf`] type configured with the provided /// `KiltRuntime`. -/// * `ProviderAccountId`: The `KiltRuntime::AccountId` type. -/// * `ProviderWeb3Name`: The `KiltRuntime::Web3Name` type. -/// * `ProviderLinkedAccountId`: The [`LinkableAccountId`] type. +/// * `KiltAccountId`: The `KiltRuntime::AccountId` type. +/// * `KiltWeb3Name`: The `KiltRuntime::Web3Name` type. +/// * `KiltLinkableAccountId`: The [`LinkableAccountId`] type. /// * `MAX_REVEALED_KEYS_COUNT`: The provided `MAX_REVEALED_KEYS_COUNT`. /// * `MAX_REVEALED_ACCOUNTS_COUNT`: The provided `MAX_REVEALED_ACCOUNTS_COUNT`. /// * `LocalContextProvider`: The [`FrameSystemDidSignatureContext`] type @@ -162,18 +143,17 @@ where /// * `LocalDidCallVerifier`: The provided `LocalDidCallVerifier`. pub struct KiltVersionedParachainVerifier< RelaychainRuntime, - RelaychainStateRoot, - const PROVIDER_PARA_ID: u32, - ProviderRuntime, + RelaychainStateRootStore, + const KILT_PARA_ID: u32, + KiltRuntime, SignedExtra, DidCallVerifier, - const MAX_LEAVES_REVEALED: usize, - const SIGNATURE_VALIDITY: u32, + const MAX_LEAVES_REVEALED: u32, >( PhantomData<( RelaychainRuntime, - RelaychainStateRoot, - ProviderRuntime, + RelaychainStateRootStore, + KiltRuntime, SignedExtra, DidCallVerifier, )>, @@ -182,28 +162,26 @@ pub struct KiltVersionedParachainVerifier< impl< ConsumerRuntime, RelaychainRuntime, - RelaychainStateRoot, - const PROVIDER_PARA_ID: u32, + RelaychainStateRootStore, + const KILT_PARA_ID: u32, KiltRuntime, SignedExtra, DidCallVerifier, - const MAX_LEAVES_REVEALED: usize, - const SIGNATURE_VALIDITY: u32, + const MAX_LEAVES_REVEALED: u32, > IdentityProofVerifier for KiltVersionedParachainVerifier< RelaychainRuntime, - RelaychainStateRoot, - PROVIDER_PARA_ID, + RelaychainStateRootStore, + KILT_PARA_ID, KiltRuntime, SignedExtra, DidCallVerifier, MAX_LEAVES_REVEALED, - SIGNATURE_VALIDITY, > where - ConsumerRuntime: pallet_dip_consumer::Config + pallet_relay_store::Config, + ConsumerRuntime: pallet_dip_consumer::Config, ConsumerRuntime::LocalIdentityInfo: Incrementable + Default, RelaychainRuntime: frame_system::Config, - RelaychainStateRoot: + RelaychainStateRootStore: GetWithArg, Result = Option>>, KiltRuntime: pallet_dip_provider::Config + did::Config + pallet_web3_names::Config + pallet_did_lookup::Config, IdentityCommitmentOf: Into, @@ -213,8 +191,9 @@ impl< RuntimeCallOf, OriginInfo = RevealedDidKey, BlockNumberFor, KiltRuntime::AccountId>, >, + DidCallVerifier::Error: Into, { - type Error = u16; + type Error = DipParachainStateProofVerifierError; type Proof = VersionedDipParachainStateProof< BlockNumberFor, KeyIdOf, @@ -224,7 +203,16 @@ impl< LinkableAccountId, BlockNumberFor, >; - type VerificationResult = (); + type VerificationResult = BoundedVec< + RevealedDidMerkleProofLeaf< + KeyIdOf, + KiltRuntime::AccountId, + BlockNumberFor, + Web3NameOf, + LinkableAccountId, + >, + ConstU32, + >; fn verify_proof_for_call_against_details( call: &RuntimeCallOf, @@ -236,13 +224,12 @@ impl< match proof { VersionedDipParachainStateProof::V0(v0_proof) => as IdentityProofVerifier>::verify_proof_for_call_against_details( call, subject, @@ -262,11 +249,12 @@ pub mod v0 { use super::*; use frame_system::pallet_prelude::HeaderFor; - use pallet_web3_names::Web3NameOf; - use sp_runtime::traits::{Header, Zero}; + use sp_runtime::{ + traits::{Header, Zero}, + SaturatedConversion, + }; use crate::{ - merkle::RevealedDidKey, state_proofs::verify_storage_value_proof, verifier::common::{ calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key, @@ -280,40 +268,39 @@ pub mod v0 { /// chain). #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)] pub struct ParachainDipStateProof< - RelayBlockHeight, - ProviderKeyId, - ProviderAccountId, - ProviderBlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, - LocalBlockNumber, + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, > { - pub(crate) para_state_root: ParachainRootStateProof, + pub(crate) para_state_root: ParachainRootStateProof, pub(crate) dip_identity_commitment: BoundedBlindedValue, pub(crate) did: DipMerkleProofAndDidSignature< - ProviderKeyId, - ProviderAccountId, - ProviderBlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, - LocalBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, >, } pub struct ParachainVerifier< RelaychainRuntime, - RelaychainStateRoot, - const PROVIDER_PARA_ID: u32, - ProviderRuntime, + RelaychainStateRootStore, + const KILT_PARA_ID: u32, + KiltRuntime, SignedExtra, DidCallVerifier, - const MAX_LEAVES_REVEALED: usize, - const SIGNATURE_VALIDITY: u32, + const MAX_LEAVES_REVEALED: u32, >( PhantomData<( RelaychainRuntime, - RelaychainStateRoot, - ProviderRuntime, + RelaychainStateRootStore, + KiltRuntime, SignedExtra, DidCallVerifier, )>, @@ -322,56 +309,58 @@ pub mod v0 { impl< ConsumerRuntime, RelaychainRuntime, - RelaychainStateRoot, - const PROVIDER_PARA_ID: u32, - ProviderRuntime, + RelaychainStateRootStore, + const KILT_PARA_ID: u32, + KiltRuntime, SignedExtra, DidCallVerifier, - const MAX_LEAVES_REVEALED: usize, - const SIGNATURE_VALIDITY: u32, + const MAX_LEAVES_REVEALED: u32, > IdentityProofVerifier for ParachainVerifier< RelaychainRuntime, - RelaychainStateRoot, - PROVIDER_PARA_ID, - ProviderRuntime, + RelaychainStateRootStore, + KILT_PARA_ID, + KiltRuntime, SignedExtra, DidCallVerifier, MAX_LEAVES_REVEALED, - SIGNATURE_VALIDITY, > where - ConsumerRuntime: - pallet_dip_consumer::Config + pallet_relay_store::Config, + ConsumerRuntime: pallet_dip_consumer::Config, ConsumerRuntime::LocalIdentityInfo: Incrementable + Default, RelaychainRuntime: frame_system::Config, - RelaychainStateRoot: + RelaychainStateRootStore: GetWithArg, Result = Option>>, - ProviderRuntime: - pallet_dip_provider::Config + did::Config + pallet_web3_names::Config + pallet_did_lookup::Config, - IdentityCommitmentOf: Into, + KiltRuntime: pallet_dip_provider::Config + did::Config + pallet_web3_names::Config + pallet_did_lookup::Config, + IdentityCommitmentOf: Into, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, DidCallVerifier: DipCallOriginFilter< RuntimeCallOf, - OriginInfo = RevealedDidKey< - KeyIdOf, - BlockNumberFor, - ProviderRuntime::AccountId, - >, + OriginInfo = RevealedDidKey, BlockNumberFor, KiltRuntime::AccountId>, >, + DidCallVerifier::Error: Into, { - type Error = u16; + type Error = DipParachainStateProofVerifierError; type Proof = ParachainDipStateProof< BlockNumberFor, - KeyIdOf, - ProviderRuntime::AccountId, - BlockNumberFor, - Web3NameOf, + KeyIdOf, + KiltRuntime::AccountId, + BlockNumberFor, + Web3NameOf, LinkableAccountId, BlockNumberFor, >; - type VerificationResult = (); + type VerificationResult = BoundedVec< + RevealedDidMerkleProofLeaf< + KeyIdOf, + KiltRuntime::AccountId, + BlockNumberFor, + Web3NameOf, + LinkableAccountId, + >, + ConstU32, + >; fn verify_proof_for_call_against_details( call: &RuntimeCallOf, @@ -381,37 +370,38 @@ pub mod v0 { proof: Self::Proof, ) -> Result { // 1. Verify parachain state is finalized by relay chain and fresh. - let provider_head_storage_key = calculate_parachain_head_storage_key(PROVIDER_PARA_ID); - let relaychain_root_at_proof_block = RelaychainStateRoot::get(&proof.para_state_root.relay_block_height) - .expect("No relaychain block found for given height."); + let provider_head_storage_key = calculate_parachain_head_storage_key(KILT_PARA_ID); + let relaychain_root_at_proof_block = + RelaychainStateRootStore::get(&proof.para_state_root.relay_block_height) + .ok_or(DipParachainStateProofVerifierError::RelaychainStateRootNotFound)?; let provider_parachain_header = - verify_storage_value_proof::<_, RelaychainRuntime::Hashing, HeaderFor>( + verify_storage_value_proof::<_, RelaychainRuntime::Hashing, HeaderFor>( &provider_head_storage_key, relaychain_root_at_proof_block, proof.para_state_root.proof, ) - .expect("Proof verification failed"); + .map_err(DipParachainStateProofVerifierError::ParachainHeadMerkleProof)?; - // 2. Verify commitment is included in provider parachain. + // 2. Verify commitment is included in provider parachain state. let dip_commitment_storage_key = - calculate_dip_identity_commitment_storage_key_for_runtime::(subject, 0); + calculate_dip_identity_commitment_storage_key_for_runtime::(subject, 0); let dip_commitment = - verify_storage_value_proof::<_, ProviderRuntime::Hashing, IdentityCommitmentOf>( + verify_storage_value_proof::<_, KiltRuntime::Hashing, IdentityCommitmentOf>( &dip_commitment_storage_key, *provider_parachain_header.state_root(), proof.dip_identity_commitment, ) - .expect("Failed to verify DIP Merkle proof."); + .map_err(DipParachainStateProofVerifierError::IdentityCommitmentMerkleProof)?; let did_proof = proof.did; // 3. Verify DIP Merkle proof. let verified_proof = did_proof - .verify_merkle_proof_against_commitment::( + .verify_merkle_proof_against_commitment::( &dip_commitment.into(), - MAX_LEAVES_REVEALED, + MAX_LEAVES_REVEALED.saturated_into(), ) - .unwrap_or_else(|_| panic!("Failed to verify DIP Merkle proof")); + .map_err(DipParachainStateProofVerifierError::DipProof)?; // 4. Verify call is signed by one of the DID keys revealed at step 3. let current_block_number = frame_system::Pallet::::block_number(); @@ -421,11 +411,7 @@ pub mod v0 { let encoded_payload = (call, &identity_details, submitter, consumer_genesis_hash, signed_extra).encode(); let signing_key = verified_proof .extract_signing_key_for_payload(&encoded_payload[..], current_block_number) - .unwrap_or_else(|_| panic!("Signature is not fresh.")); - - let Some(signing_key) = signing_key else { - panic!("No key found."); - }; + .map_err(DipParachainStateProofVerifierError::DidSignature)?; // Increment the local details if let Some(details) = identity_details { @@ -435,9 +421,14 @@ pub mod v0 { }; DidCallVerifier::check_call_origin_info(call, signing_key) - .unwrap_or_else(|_| panic!("Failed to verify DID call info.")); + .map_err(DipParachainStateProofVerifierError::DidOriginError)?; + + let result = verified_proof.leaves.try_into().map_err(|_| { + log::error!("Failed to convert vector of revealed leaves into BoundedVec. This should never happen since the bound checks were checked earlier on."); + DipParachainStateProofVerifierError::Internal + })?; - Ok(()) + Ok(result) } } } diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index e8553cf234..af068ea51b 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -16,29 +16,25 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -use cumulus_primitives_core::ParaId; -use did::{did_details::DidVerificationKey, DidVerificationKeyRelationship, KeyIdOf}; -use frame_support::Parameter; +use did::KeyIdOf; use frame_system::pallet_prelude::BlockNumberFor; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_consumer::{traits::IdentityProofVerifier, RuntimeCallOf}; use pallet_dip_provider::IdentityCommitmentOf; -use parity_scale_codec::{Codec, Decode, Encode, HasCompact}; +use pallet_web3_names::Web3NameOf; +use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_core::{RuntimeDebug, U256}; -use sp_runtime::traits::{AtLeast32BitUnsigned, Get, Hash, MaybeDisplay, Member, SimpleBitOps}; +use sp_core::{ConstU32, RuntimeDebug, U256}; +use sp_runtime::{traits::Hash, BoundedVec}; use sp_std::marker::PhantomData; use crate::{ - did::RevealedDidKeysSignatureAndCallVerifierError, - merkle::{DidMerkleProofVerifierError, RevealedDidMerkleProofLeaf, RevealedDidMerkleProofLeaves}, - state_proofs::{relaychain::ParachainHeadProofVerifierError, MerkleProofError}, - traits::{ - DidSignatureVerifierContext, DipCallOriginFilter, HistoricalBlockRegistry, Incrementable, - ProviderParachainStorageInfo, RelayChainStorageInfo, - }, + did::DidSignatureVerificationError, + merkle::{DidMerkleProofVerificationError, RevealedDidKey, RevealedDidMerkleProofLeaf}, + state_proofs::MerkleProofError, + traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, - BoundedBlindedValue, FrameSystemDidSignatureContext, ProviderParachainStateInfoViaProviderPallet, + BoundedBlindedValue, }; /// A KILT-specific DIP identity proof for a parent consumer that supports @@ -47,76 +43,58 @@ use crate::{ /// For more info, refer to the version-specific proofs. #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)] pub enum VersionedRelaychainStateProof< - ParentBlockHeight: Copy + Into + TryFrom, - ParentBlockHasher: Hash, - DipMerkleProofBlindedValues, - DipMerkleProofRevealedLeaf, + ConsumerBlockNumber: Copy + Into + TryFrom, + ConsumerBlockHasher: Hash, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, > { V0( v0::RelaychainDipStateProof< - ParentBlockHeight, - ParentBlockHasher, - DipMerkleProofBlindedValues, - DipMerkleProofRevealedLeaf, + ConsumerBlockNumber, + ConsumerBlockHasher, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, >, ), } -pub enum DipRelaychainStateProofVerifierError< - ParachainHeadMerkleProofVerificationError, - IdentityCommitmentMerkleProofVerificationError, - DipProofVerificationError, - DidSignatureVerificationError, -> { +pub enum DipRelaychainStateProofVerifierError { UnsupportedVersion, - InvalidBlockHeight, - InvalidBlockHash, - ParachainHeadMerkleProof(ParachainHeadMerkleProofVerificationError), - IdentityCommitmentMerkleProof(IdentityCommitmentMerkleProofVerificationError), - DipProof(DipProofVerificationError), + BlockHashNotFound, + InvalidBlockHeader, + ParachainHeadMerkleProof(MerkleProofError), + IdentityCommitmentMerkleProof(MerkleProofError), + DipProof(DidMerkleProofVerificationError), DidSignature(DidSignatureVerificationError), + DidOriginError(DidOriginError), + Internal, } -impl< - ParachainHeadMerkleProofVerificationError, - IdentityCommitmentMerkleProofVerificationError, - DipProofVerificationError, - DidSignatureVerificationError, - > - From< - DipRelaychainStateProofVerifierError< - ParachainHeadMerkleProofVerificationError, - IdentityCommitmentMerkleProofVerificationError, - DipProofVerificationError, - DidSignatureVerificationError, - >, - > for u16 +impl From> for u16 where - ParachainHeadMerkleProofVerificationError: Into, - IdentityCommitmentMerkleProofVerificationError: Into, - DipProofVerificationError: Into, - DidSignatureVerificationError: Into, + DidOriginError: Into, { - fn from( - value: DipRelaychainStateProofVerifierError< - ParachainHeadMerkleProofVerificationError, - IdentityCommitmentMerkleProofVerificationError, - DipProofVerificationError, - DidSignatureVerificationError, - >, - ) -> Self { + fn from(value: DipRelaychainStateProofVerifierError) -> Self { match value { - DipRelaychainStateProofVerifierError::UnsupportedVersion => 0, - DipRelaychainStateProofVerifierError::InvalidBlockHeight => 1, - DipRelaychainStateProofVerifierError::InvalidBlockHash => 2, + DipRelaychainStateProofVerifierError::UnsupportedVersion => 1, + DipRelaychainStateProofVerifierError::BlockHashNotFound => 2, + DipRelaychainStateProofVerifierError::InvalidBlockHeader => 3, DipRelaychainStateProofVerifierError::ParachainHeadMerkleProof(error) => { - u8::MAX as u16 + error.into() as u16 + u8::MAX as u16 + u8::from(error) as u16 } DipRelaychainStateProofVerifierError::IdentityCommitmentMerkleProof(error) => { - u8::MAX as u16 * 2 + error.into() as u16 + u8::MAX as u16 * 2 + u8::from(error) as u16 } - DipRelaychainStateProofVerifierError::DipProof(error) => u8::MAX as u16 * 3 + error.into() as u16, - DipRelaychainStateProofVerifierError::DidSignature(error) => u8::MAX as u16 * 4 + error.into() as u16, + DipRelaychainStateProofVerifierError::DipProof(error) => u8::MAX as u16 * 3 + u8::from(error) as u16, + DipRelaychainStateProofVerifierError::DidSignature(error) => u8::MAX as u16 * 4 + u8::from(error) as u16, + DipRelaychainStateProofVerifierError::DidOriginError(error) => u8::MAX as u16 * 5 + error.into() as u16, + DipRelaychainStateProofVerifierError::Internal => u16::MAX, } } } @@ -156,9 +134,9 @@ where /// * `ProviderDipMerkleHasher`: The provided `KiltDipMerkleHasher`. /// * `ProviderDidKeyId`: The [`KeyIdOf`] type configured with the provided /// `KiltRuntime`. -/// * `ProviderAccountId`: The `KiltRuntime::AccountId` type. -/// * `ProviderWeb3Name`: The `KiltRuntime::Web3Name` type. -/// * `ProviderLinkedAccountId`: The [`LinkableAccountId`] type. +/// * `KiltAccountId`: The `KiltRuntime::AccountId` type. +/// * `KiltWeb3Name`: The `KiltRuntime::Web3Name` type. +/// * `KiltLinkableAccountId`: The [`LinkableAccountId`] type. /// * `MAX_REVEALED_KEYS_COUNT`: The provided `MAX_REVEALED_KEYS_COUNT`. /// * `MAX_REVEALED_ACCOUNTS_COUNT`: The provided `MAX_REVEALED_ACCOUNTS_COUNT`. /// * `LocalContextProvider`: The [`FrameSystemDidSignatureContext`] type @@ -166,285 +144,65 @@ where /// `MAX_DID_SIGNATURE_DURATION`. /// * `LocalDidCallVerifier`: The provided `LocalDidCallVerifier`. pub struct KiltVersionedRelaychainVerifier< + ConsumerBlockHashStore, + const KILT_PARA_ID: u32, KiltRuntime, - KiltParachainId, - RelayChainInfo, - KiltDipMerkleHasher, - LocalDidCallVerifier, - const MAX_REVEALED_KEYS_COUNT: u32 = 10, - const MAX_REVEALED_ACCOUNTS_COUNT: u32 = 10, - const MAX_DID_SIGNATURE_DURATION: u16 = 50, ->( - PhantomData<( - KiltRuntime, - KiltParachainId, - RelayChainInfo, - KiltDipMerkleHasher, - LocalDidCallVerifier, - )>, -); + SignedExtra, + DidCallVerifier, + const MAX_LEAVES_REVEALED: u32, +>(#[allow(clippy::type_complexity)] PhantomData<(ConsumerBlockHashStore, KiltRuntime, SignedExtra, DidCallVerifier)>); impl< ConsumerRuntime, + ConsumerBlockHashStore, + const KILT_PARA_ID: u32, KiltRuntime, - KiltParachainId, - RelayChainInfo, - KiltDipMerkleHasher, - LocalDidCallVerifier, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, - const MAX_DID_SIGNATURE_DURATION: u16, + SignedExtra, + DidCallVerifier, + const MAX_LEAVES_REVEALED: u32, > IdentityProofVerifier for KiltVersionedRelaychainVerifier< + ConsumerBlockHashStore, + KILT_PARA_ID, KiltRuntime, - KiltParachainId, - RelayChainInfo, - KiltDipMerkleHasher, - LocalDidCallVerifier, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - MAX_DID_SIGNATURE_DURATION, + SignedExtra, + DidCallVerifier, + MAX_LEAVES_REVEALED, > where - KiltRuntime: did::Config - + pallet_web3_names::Config - + pallet_did_lookup::Config - + parachain_info::Config - + pallet_dip_provider::Config, - KiltParachainId: Get, - OutputOf: Ord + From::Hasher>>, - KeyIdOf: Into, - KiltDipMerkleHasher: sp_core::Hasher>, - ConsumerRuntime: pallet_dip_consumer::Config, - ConsumerRuntime::LocalIdentityInfo: Incrementable + Default + Encode, - RelayChainInfo: RelayChainStorageInfo> - + HistoricalBlockRegistry< - BlockNumber = ::BlockNumber, - Hasher = ::Hasher, - >, - RelayChainInfo::ParaId: From, - OutputOf<::Hasher>: - Ord + Default + sp_std::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, - ::Hasher: Parameter + 'static, - ::BlockNumber: Copy - + Into - + TryFrom - + HasCompact - + Member - + sp_std::hash::Hash - + MaybeDisplay - + AtLeast32BitUnsigned - + Codec - + Parameter - + 'static, - RelayChainInfo::Key: AsRef<[u8]>, - LocalDidCallVerifier: DipCallOriginFilter< + ConsumerRuntime: pallet_dip_consumer::Config, + ConsumerRuntime::LocalIdentityInfo: Incrementable + Default, + BlockNumberFor: Into + TryFrom, + ConsumerBlockHashStore: + GetWithArg, Result = Option>>, + KiltRuntime: pallet_dip_provider::Config + did::Config + pallet_web3_names::Config + pallet_did_lookup::Config, + IdentityCommitmentOf: Into, + SignedExtra: GetWithoutArg, + SignedExtra::Result: Encode, + DidCallVerifier: DipCallOriginFilter< RuntimeCallOf, - OriginInfo = ( - DidVerificationKey, - DidVerificationKeyRelationship, - ), + OriginInfo = RevealedDidKey, BlockNumberFor, KiltRuntime::AccountId>, >, + DidCallVerifier::Error: Into, { - type Error = DipRelaychainStateProofVerifierError< - ParachainHeadProofVerifierError, - MerkleProofError, - DidMerkleProofVerifierError, - RevealedDidKeysSignatureAndCallVerifierError, - >; + type Error = DipRelaychainStateProofVerifierError; type Proof = VersionedRelaychainStateProof< - ::BlockNumber, - ::Hasher, - BoundedBlindedValue, - RevealedDidMerkleProofLeaf< - KeyIdOf, - KiltRuntime::AccountId, - BlockNumberFor, - KiltRuntime::Web3Name, - LinkableAccountId, - >, - >; - type VerificationResult = RevealedDidMerkleProofLeaves< + BlockNumberFor, + ConsumerRuntime::Hashing, KeyIdOf, KiltRuntime::AccountId, BlockNumberFor, - KiltRuntime::Web3Name, + Web3NameOf, LinkableAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, >; - - fn verify_proof_for_call_against_details( - call: &RuntimeCallOf, - subject: &ConsumerRuntime::Identifier, - submitter: &ConsumerRuntime::AccountId, - identity_details: &mut Option, - proof: Self::Proof, - ) -> Result { - , - KiltDipMerkleHasher, + type VerificationResult = BoundedVec< + RevealedDidMerkleProofLeaf< KeyIdOf, KiltRuntime::AccountId, - KiltRuntime::Web3Name, + BlockNumberFor, + Web3NameOf, LinkableAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - FrameSystemDidSignatureContext, - LocalDidCallVerifier, - > as IdentityProofVerifier>::verify_proof_for_call_against_details( - call, - subject, - submitter, - identity_details, - proof, - ) - } -} - -/// Generic proof verifier for KILT-specific DIP identity proofs of different -/// versions coming from a child provider running one of the available KILT -/// runtimes. -/// -/// It expects the DIP proof to be a [`VersionedRelaychainStateProof`], -/// and returns [`RevealedDidMerkleProofLeaves`] if the proof is successfully -/// verified. -/// -/// For more info, refer to the version-specific proof identifiers. -pub struct GenericVersionedRelaychainVerifier< - RelayChainInfo, - ChildProviderParachainId, - ChildProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, - LocalContextProvider, - LocalDidCallVerifier, ->( - #[allow(clippy::type_complexity)] - PhantomData<( - RelayChainInfo, - ChildProviderParachainId, - ChildProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - LocalContextProvider, - LocalDidCallVerifier, - )>, -); - -impl< - ConsumerRuntime, - RelayChainInfo, - ChildProviderParachainId, - ChildProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, - LocalContextProvider, - LocalDidCallVerifier, - > IdentityProofVerifier - for GenericVersionedRelaychainVerifier< - RelayChainInfo, - ChildProviderParachainId, - ChildProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - LocalContextProvider, - LocalDidCallVerifier, - > where - ConsumerRuntime: pallet_dip_consumer::Config, - ConsumerRuntime::LocalIdentityInfo: Incrementable + Default, - - RelayChainInfo: RelayChainStorageInfo> - + HistoricalBlockRegistry< - BlockNumber = ::BlockNumber, - Hasher = ::Hasher, - >, - OutputOf<::Hasher>: - Ord + Default + sp_std::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, - ::Hasher: Parameter + 'static, - ::BlockNumber: Copy - + Into - + TryFrom - + HasCompact - + Member - + sp_std::hash::Hash - + MaybeDisplay - + AtLeast32BitUnsigned - + Codec - + Parameter - + 'static, - RelayChainInfo::Key: AsRef<[u8]>, - - ChildProviderParachainId: Get, - - ChildProviderStateInfo: ProviderParachainStorageInfo< - Identifier = ConsumerRuntime::Identifier, - Commitment = ProviderDipMerkleHasher::Out, - >, - OutputOf: Ord + From::Hasher>>, - ChildProviderStateInfo::BlockNumber: Parameter + 'static, - ChildProviderStateInfo::Commitment: Decode, - ChildProviderStateInfo::Key: AsRef<[u8]>, - - LocalContextProvider: - DidSignatureVerifierContext, Hash = ConsumerRuntime::Hash>, - LocalContextProvider::SignedExtra: Encode, - LocalDidCallVerifier: DipCallOriginFilter< - RuntimeCallOf, - OriginInfo = (DidVerificationKey, DidVerificationKeyRelationship), - >, - - ProviderDipMerkleHasher: sp_core::Hasher, - ProviderDidKeyId: Parameter + 'static + Into, - ProviderAccountId: Parameter + 'static, - ProviderLinkedAccountId: Parameter + 'static, - ProviderWeb3Name: Parameter + 'static, -{ - type Error = DipRelaychainStateProofVerifierError< - ParachainHeadProofVerifierError, - MerkleProofError, - DidMerkleProofVerifierError, - RevealedDidKeysSignatureAndCallVerifierError, - >; - type Proof = VersionedRelaychainStateProof< - ::BlockNumber, - ::Hasher, - BoundedBlindedValue, - RevealedDidMerkleProofLeaf< - ProviderDidKeyId, - ProviderAccountId, - ChildProviderStateInfo::BlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, >, - >; - type VerificationResult = RevealedDidMerkleProofLeaves< - ProviderDidKeyId, - ProviderAccountId, - ChildProviderStateInfo::BlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, + ConstU32, >; fn verify_proof_for_call_against_details( @@ -456,18 +214,12 @@ impl< ) -> Result { match proof { VersionedRelaychainStateProof::V0(v0_proof) => as IdentityProofVerifier>::verify_proof_for_call_against_details( call, subject, @@ -486,31 +238,20 @@ pub mod latest { pub mod v0 { use super::*; - use parity_scale_codec::Codec; + use frame_system::pallet_prelude::HeaderFor; use sp_runtime::{ generic::Header, - traits::{AtLeast32BitUnsigned, Hash, MaybeDisplay, Member, SimpleBitOps}, + traits::{Hash, Header as HeaderT, Zero}, + SaturatedConversion, }; - use sp_std::{borrow::Borrow, vec::Vec}; use crate::{ - did::{ - verify_did_signature_for_call, RevealedDidKeysAndSignature, RevealedDidKeysSignatureAndCallVerifierError, + latest::ParachainDipStateProof, + state_proofs::verify_storage_value_proof, + verifier::common::{ + calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key, + v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof}, }, - merkle::{ - verify_dip_merkle_proof, DidMerkleProofVerifierError, RevealedDidMerkleProofLeaf, - RevealedDidMerkleProofLeaves, - }, - state_proofs::{ - relaychain::{ParachainHeadProofVerifier, ParachainHeadProofVerifierError}, - MerkleProofError, - }, - traits::{ - DidSignatureVerifierContext, DipCallOriginFilter, HistoricalBlockRegistry, Incrementable, - ProviderParachainStorageInfo, RelayChainStorageInfo, - }, - utils::OutputOf, - verifier::common::v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof}, }; /// The expected format of a cross-chain DIP identity proof when the @@ -519,29 +260,29 @@ pub mod v0 { /// chain). #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub struct RelaychainDipStateProof< - ParentBlockHeight: Copy + Into + TryFrom, - ParentBlockHasher: Hash, - ProviderKeyId, - ProviderAccountId, - ProviderBlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, + ConsumerBlockNumber: Copy + Into + TryFrom, + ConsumerBlockHasher: Hash, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, > { /// The state proof for the given parachain head. - para_state_root: ParachainRootStateProof, + para_state_root: ParachainRootStateProof, /// The relaychain header for the relaychain block specified in the /// `para_state_root`. - relay_header: Header, + relay_header: Header, /// The raw state proof for the DIP commitment of the given subject. dip_identity_commitment: BoundedBlindedValue, /// The cross-chain DID signature. did: DipMerkleProofAndDidSignature< - ProviderKeyId, - ProviderAccountId, - ProviderBlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, - ParentBlockHeight, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, >, } @@ -596,11 +337,11 @@ pub mod v0 { /// parachain for the generation of the DIP identity commitment. /// * `ProviderDidKeyId`: The runtime type of a DID key ID as defined by the /// KILT child parachain. - /// * `ProviderAccountId`: The runtime type of an account ID as defined by - /// the KILT child parachain. - /// * `ProviderWeb3Name`: The runtime type of a web3name as defined by the + /// * `KiltAccountId`: The runtime type of an account ID as defined by the /// KILT child parachain. - /// * `ProviderLinkedAccountId`: The runtime type of a linked account ID as + /// * `KiltWeb3Name`: The runtime type of a web3name as defined by the KILT + /// child parachain. + /// * `KiltLinkableAccountId`: The runtime type of a linked account ID as /// defined by the KILT child parachain. /// * `MAX_REVEALED_KEYS_COUNT`: Max number of DID keys that the verifier /// will accept revealed as part of the DIP identity proof. @@ -614,139 +355,68 @@ pub mod v0 { /// verified, to filter only the revealed keys that match the provided /// relationship. pub struct RelaychainVerifier< - RelayChainInfo, - ChildProviderParachainId, - ChildProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, - LocalContextProvider, - LocalDidCallVerifier, + ConsumerBlockHashStore, + const KILT_PARA_ID: u32, + KiltRuntime, + SignedExtra, + DidCallVerifier, + const MAX_LEAVES_REVEALED: u32, >( #[allow(clippy::type_complexity)] - PhantomData<( - RelayChainInfo, - ChildProviderParachainId, - ChildProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - LocalContextProvider, - LocalDidCallVerifier, - )>, + PhantomData<(ConsumerBlockHashStore, KiltRuntime, SignedExtra, DidCallVerifier)>, ); impl< ConsumerRuntime, - RelayChainInfo, - ChildProviderParachainId, - ChildProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - const MAX_REVEALED_KEYS_COUNT: u32, - const MAX_REVEALED_ACCOUNTS_COUNT: u32, - LocalContextProvider, - LocalDidCallVerifier, + ConsumerBlockHashStore, + const KILT_PARA_ID: u32, + KiltRuntime, + SignedExtra, + DidCallVerifier, + const MAX_LEAVES_REVEALED: u32, > IdentityProofVerifier for RelaychainVerifier< - RelayChainInfo, - ChildProviderParachainId, - ChildProviderStateInfo, - ProviderDipMerkleHasher, - ProviderDidKeyId, - ProviderAccountId, - ProviderWeb3Name, - ProviderLinkedAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, - LocalContextProvider, - LocalDidCallVerifier, + ConsumerBlockHashStore, + KILT_PARA_ID, + KiltRuntime, + SignedExtra, + DidCallVerifier, + MAX_LEAVES_REVEALED, > where - ConsumerRuntime: pallet_dip_consumer::Config, + ConsumerRuntime: pallet_dip_consumer::Config, ConsumerRuntime::LocalIdentityInfo: Incrementable + Default, - - RelayChainInfo: RelayChainStorageInfo> - + HistoricalBlockRegistry< - BlockNumber = ::BlockNumber, - Hasher = ::Hasher, - >, - ::Hasher: Parameter + 'static, - OutputOf<::Hasher>: - Ord + Default + sp_std::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, - ::BlockNumber: Copy - + Into - + TryFrom - + HasCompact - + Member - + sp_std::hash::Hash - + MaybeDisplay - + AtLeast32BitUnsigned - + Codec - + Parameter - + 'static, - RelayChainInfo::Key: AsRef<[u8]>, - - ChildProviderParachainId: Get, - - ChildProviderStateInfo: ProviderParachainStorageInfo< - Identifier = ConsumerRuntime::Identifier, - Commitment = ProviderDipMerkleHasher::Out, - >, - OutputOf: - Ord + From::Hasher>>, - ChildProviderStateInfo::BlockNumber: Parameter + 'static, - ChildProviderStateInfo::Commitment: Decode, - ChildProviderStateInfo::Key: AsRef<[u8]>, - - LocalContextProvider: - DidSignatureVerifierContext, Hash = ConsumerRuntime::Hash>, - LocalContextProvider::SignedExtra: Encode, - LocalDidCallVerifier: DipCallOriginFilter< + BlockNumberFor: Into + TryFrom, + ConsumerBlockHashStore: + GetWithArg, Result = Option>>, + KiltRuntime: pallet_dip_provider::Config + did::Config + pallet_web3_names::Config + pallet_did_lookup::Config, + IdentityCommitmentOf: Into, + SignedExtra: GetWithoutArg, + SignedExtra::Result: Encode, + DidCallVerifier: DipCallOriginFilter< RuntimeCallOf, - OriginInfo = (DidVerificationKey, DidVerificationKeyRelationship), + OriginInfo = RevealedDidKey, BlockNumberFor, KiltRuntime::AccountId>, >, - - ProviderDipMerkleHasher: sp_core::Hasher, - ProviderDidKeyId: Parameter + 'static + Into, - ProviderAccountId: Parameter + 'static, - ProviderLinkedAccountId: Parameter + 'static, - ProviderWeb3Name: Parameter + 'static, + DidCallVerifier::Error: Into, { - type Error = DipRelaychainStateProofVerifierError< - ParachainHeadProofVerifierError, - MerkleProofError, - DidMerkleProofVerifierError, - RevealedDidKeysSignatureAndCallVerifierError, - >; + type Error = DipRelaychainStateProofVerifierError; type Proof = RelaychainDipStateProof< - ::BlockNumber, - ::Hasher, - BoundedBlindedValue, + BlockNumberFor, + ConsumerRuntime::Hashing, + KeyIdOf, + KiltRuntime::AccountId, + BlockNumberFor, + Web3NameOf, + LinkableAccountId, + >; + type VerificationResult = BoundedVec< RevealedDidMerkleProofLeaf< - ProviderDidKeyId, - ProviderAccountId, - ChildProviderStateInfo::BlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, + KeyIdOf, + KiltRuntime::AccountId, + BlockNumberFor, + Web3NameOf, + LinkableAccountId, >, - >; - type VerificationResult = RevealedDidMerkleProofLeaves< - ProviderDidKeyId, - ProviderAccountId, - ChildProviderStateInfo::BlockNumber, - ProviderWeb3Name, - ProviderLinkedAccountId, - MAX_REVEALED_KEYS_COUNT, - MAX_REVEALED_ACCOUNTS_COUNT, + ConstU32, >; fn verify_proof_for_call_against_details( @@ -757,60 +427,81 @@ pub mod v0 { proof: Self::Proof, ) -> Result { // 1. Retrieve block hash from provider at the proof height - let block_hash_at_height = RelayChainInfo::block_hash_for(&proof.para_state_root.relay_block_height) - .ok_or(DipRelaychainStateProofVerifierError::InvalidBlockHeight)?; + let block_hash_at_height = ConsumerBlockHashStore::get(&proof.para_state_root.relay_block_height) + .ok_or(DipRelaychainStateProofVerifierError::BlockHashNotFound)?; - // 1.1 Verify that the provided header hashes to the same block has retrieved + // 1.1 Verify that the provided header hashes to the same block hash retrieved if block_hash_at_height != proof.relay_header.hash() { - return Err(DipRelaychainStateProofVerifierError::InvalidBlockHash); + return Err(DipRelaychainStateProofVerifierError::InvalidBlockHeader); } // 1.2 If so, extract the state root from the header let state_root_at_height = proof.relay_header.state_root; - // 2. Verify relay chain proof + // Remove the header from the proof and verify the rest using the parachain + // verifier logic. + let parachain_proof = ParachainDipStateProof { + para_state_root: proof.para_state_root, + dip_identity_commitment: proof.dip_identity_commitment, + did: proof.did, + }; + + // 2. Verify parachain state is finalized by relay chain and fresh. + let provider_head_storage_key = calculate_parachain_head_storage_key(KILT_PARA_ID); let provider_parachain_header = - ParachainHeadProofVerifier::::verify_proof_for_parachain_with_root( - &ChildProviderParachainId::get(), - &state_root_at_height, - proof.para_state_root.proof, + verify_storage_value_proof::<_, ConsumerRuntime::Hashing, HeaderFor>( + &provider_head_storage_key, + state_root_at_height, + parachain_proof.para_state_root.proof, ) .map_err(DipRelaychainStateProofVerifierError::ParachainHeadMerkleProof)?; - // // 3. Verify parachain state proof. - // let subject_identity_commitment = - // DipIdentityCommitmentProofVerifier::::verify_proof_for_identifier( - // subject, - // provider_parachain_header.state_root.into(), - // proof.dip_identity_commitment, - // ) - // .map_err(DipRelaychainStateProofVerifierError::IdentityCommitmentMerkleProof)?; + // 3. Verify commitment is included in provider parachain state. + let dip_commitment_storage_key = + calculate_dip_identity_commitment_storage_key_for_runtime::(subject, 0); + let dip_commitment = + verify_storage_value_proof::<_, KiltRuntime::Hashing, IdentityCommitmentOf>( + &dip_commitment_storage_key, + *provider_parachain_header.state_root(), + parachain_proof.dip_identity_commitment, + ) + .map_err(DipRelaychainStateProofVerifierError::IdentityCommitmentMerkleProof)?; - // // 4. Verify DIP merkle proof. - // let proof_leaves = verify_dip_merkle_proof::< - // ProviderDipMerkleHasher, - // _, - // _, - // _, - // _, - // _, - // MAX_REVEALED_KEYS_COUNT, - // MAX_REVEALED_ACCOUNTS_COUNT, - // >(&subject_identity_commitment, proof.did.leaves) - // .map_err(DipRelaychainStateProofVerifierError::DipProof)?; + let did_proof = parachain_proof.did; - // // 5. Verify DID signature. - // verify_did_signature_for_call::<_, _, _, _, LocalContextProvider, _, _, _, - // LocalDidCallVerifier>( call, - // submitter, - // identity_details, - // RevealedDidKeysAndSignature { - // merkle_leaves: proof_leaves.borrow(), - // did_signature: proof.did.signature, - // }, - // ) - // .map_err(DipRelaychainStateProofVerifierError::DidSignature)?; - // Ok(proof_leaves) - Ok(Default::default()) + // 4. Verify DIP Merkle proof. + let verified_proof = did_proof + .verify_merkle_proof_against_commitment::( + &dip_commitment.into(), + MAX_LEAVES_REVEALED.saturated_into(), + ) + .map_err(DipRelaychainStateProofVerifierError::DipProof)?; + + // 5. Verify call is signed by one of the DID keys revealed at step 3. + let current_block_number = frame_system::Pallet::::block_number(); + let consumer_genesis_hash = + frame_system::Pallet::::block_hash(BlockNumberFor::::zero()); + let signed_extra = SignedExtra::get(); + let encoded_payload = (call, &identity_details, submitter, consumer_genesis_hash, signed_extra).encode(); + let signing_key = verified_proof + .extract_signing_key_for_payload(&encoded_payload[..], current_block_number) + .map_err(DipRelaychainStateProofVerifierError::DidSignature)?; + + // Increment the local details + if let Some(details) = identity_details { + details.increment(); + } else { + *identity_details = Some(Default::default()); + }; + + DidCallVerifier::check_call_origin_info(call, signing_key) + .map_err(DipRelaychainStateProofVerifierError::DidOriginError)?; + + let result = verified_proof.leaves.try_into().map_err(|_| { + log::error!("Failed to convert vector of revealed leaves into BoundedVec. This should never happen since the bound checks were checked earlier on."); + DipRelaychainStateProofVerifierError::Internal + })?; + + Ok(result) } } } From dca993077538f4b535a28ff12bfbc9bea06ae75c Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 12 Jan 2024 11:59:03 +0100 Subject: [PATCH 10/45] Kilt provider template compiling --- crates/kilt-dip-primitives/src/verifier/common.rs | 1 + .../src/verifier/relaychain.rs | 4 ++++ runtimes/common/src/dip/merkle.rs | 15 ++++++--------- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/crates/kilt-dip-primitives/src/verifier/common.rs b/crates/kilt-dip-primitives/src/verifier/common.rs index 925981ad9a..8afd41fa06 100644 --- a/crates/kilt-dip-primitives/src/verifier/common.rs +++ b/crates/kilt-dip-primitives/src/verifier/common.rs @@ -30,6 +30,7 @@ pub mod v0 { use scale_info::TypeInfo; use sp_core::RuntimeDebug; use sp_runtime::traits::Hash; + use sp_std::vec::Vec; use crate::{ did::{DidSignatureVerificationError, TimeBoundDidSignature}, diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index af068ea51b..084382cb8f 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -445,6 +445,10 @@ pub mod v0 { did: proof.did, }; + // TODO: Can we re-use the verification logic for the parachain verification? + // Current issue is implementing the expected `RelaychainStateRootStore` trait + // to return the state root we calculated above. + // 2. Verify parachain state is finalized by relay chain and fresh. let provider_head_storage_key = calculate_parachain_head_storage_key(KILT_PARA_ID); let provider_parachain_header = diff --git a/runtimes/common/src/dip/merkle.rs b/runtimes/common/src/dip/merkle.rs index 05078521b1..5c1f2c5bcd 100644 --- a/runtimes/common/src/dip/merkle.rs +++ b/runtimes/common/src/dip/merkle.rs @@ -37,14 +37,11 @@ pub type BlindedValue = Vec; /// Type of the Merkle proof revealing parts of the DIP identity of a given DID /// subject. pub type DidMerkleProofOf = DidMerkleProof< - Vec, - RevealedDidMerkleProofLeaf< - KeyIdOf, - ::AccountId, - BlockNumberFor, - ::Web3Name, - LinkableAccountId, - >, + KeyIdOf, + ::AccountId, + BlockNumberFor, + ::Web3Name, + LinkableAccountId, >; /// Type of a complete DIP Merkle proof. @@ -329,7 +326,7 @@ pub mod v0 { Ok(CompleteMerkleProof { root, proof: DidMerkleProofOf:: { - blinded: proof, + blinded: proof.into_iter().into(), revealed: leaves.into_iter().collect(), }, }) From 2f8e779dae027b4ae7cb01c052f37e15285d0ac2 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 12 Jan 2024 12:35:06 +0100 Subject: [PATCH 11/45] Consumer template compiling --- Cargo.lock | 1 + crates/kilt-dip-primitives/src/lib.rs | 3 +- crates/kilt-dip-primitives/src/merkle.rs | 2 +- crates/kilt-dip-primitives/src/traits.rs | 168 ++---------------- dip-template/runtimes/dip-consumer/Cargo.toml | 3 + dip-template/runtimes/dip-consumer/src/dip.rs | 47 +++-- .../dip-consumer/src/origin_adapter.rs | 13 +- 7 files changed, 67 insertions(+), 170 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ba4cd2766..09458d85f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2518,6 +2518,7 @@ dependencies = [ "parachain-info", "parity-scale-codec", "polkadot-parachain", + "rococo-runtime", "runtime-common", "scale-info", "sp-api", diff --git a/crates/kilt-dip-primitives/src/lib.rs b/crates/kilt-dip-primitives/src/lib.rs index 359d858c21..5ecf1b6008 100644 --- a/crates/kilt-dip-primitives/src/lib.rs +++ b/crates/kilt-dip-primitives/src/lib.rs @@ -33,6 +33,7 @@ pub mod traits; pub mod utils; pub mod verifier; -pub use traits::{FrameSystemDidSignatureContext, ProviderParachainStateInfoViaProviderPallet}; +pub use merkle::RevealedDidMerkleProofLeaf; +pub use traits::RelayStateRootsViaRelayStorePallet; pub use utils::BoundedBlindedValue; pub use verifier::*; diff --git a/crates/kilt-dip-primitives/src/merkle.rs b/crates/kilt-dip-primitives/src/merkle.rs index 71a40afd62..974cf33c4b 100644 --- a/crates/kilt-dip-primitives/src/merkle.rs +++ b/crates/kilt-dip-primitives/src/merkle.rs @@ -123,7 +123,7 @@ impl TryFrom for DidVerificationKeyRelationship { /// All possible Merkle leaf types that can be revealed as part of a DIP /// identity Merkle proof. -#[derive(Clone, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] +#[derive(Clone, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub enum RevealedDidMerkleProofLeaf { DidKey(RevealedDidKey), Web3Name(RevealedWeb3Name), diff --git a/crates/kilt-dip-primitives/src/traits.rs b/crates/kilt-dip-primitives/src/traits.rs index 483fc00bce..9ac817ea82 100644 --- a/crates/kilt-dip-primitives/src/traits.rs +++ b/crates/kilt-dip-primitives/src/traits.rs @@ -16,14 +16,10 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -use frame_system::pallet_prelude::BlockNumberFor; -use pallet_dip_provider::{IdentityCommitmentOf, IdentityCommitmentVersion}; -use sp_core::storage::StorageKey; +use sp_core::H256; use sp_runtime::traits::{CheckedAdd, One, Zero}; use sp_std::marker::PhantomData; -use crate::utils::OutputOf; - // TODO: Switch to the `Incrementable` trait once it's added to the root of // `frame_support`. /// A trait for "incrementable" types, i.e., types that have some notion of @@ -61,166 +57,34 @@ pub trait DipCallOriginFilter { fn check_call_origin_info(call: &Call, info: &Self::OriginInfo) -> Result; } -/// A trait that provides context (e.g., runtime type definitions, storage keys) -/// about the relaychain that is relevant for cross-chain state proofs. -pub trait RelayChainStorageInfo { - /// The type of relaychain block numbers. - type BlockNumber; - /// The type of the relaychain hashing algorithm. - type Hasher: sp_runtime::traits::Hash; - /// The type of the relaychain storage key. - type Key; - /// The type of parachain IDs. - type ParaId; - - /// Return the storage key pointing to the head of the parachain - /// identified by the provided ID. - fn parachain_head_storage_key(para_id: &Self::ParaId) -> Self::Key; -} - -/// A trait that provides state information about specific relaychain blocks. -pub trait RelayChainStateInfo: RelayChainStorageInfo { - /// Return the relaychain state root at a given block height. - fn state_root_for_block(block_height: &Self::BlockNumber) -> Option>; -} - -/// A trait that provides context (e.g., runtime type definitions, storage keys) -/// about the DIP provider parachain that is relevant for cross-chain state -/// proofs. -pub trait ProviderParachainStorageInfo { - /// The type of the provider chain's block numbers. - type BlockNumber; - /// The type of the provider chain's identity commitments. - type Commitment; - /// The type of the provider chain's storage keys. - type Key; - /// The type of the provider chain's hashing algorithm. - type Hasher: sp_runtime::traits::Hash; - /// The type of the provider chain's identity subject identifiers. - type Identifier; - - /// Return the storage key pointing to the identity commitment for the given - /// identifier and version. - fn dip_subject_storage_key(identifier: &Self::Identifier, version: IdentityCommitmentVersion) -> Self::Key; -} - -/// Implementation of the [`ProviderParachainStorageInfo`] trait that builds on -/// the definitions of a runtime that includes the DIP provider pallet (e.g., -/// KILT runtimes). -/// The generic types are the following: -/// * `T`: The runtime including the [`pallet_dip_provider::Pallet`] pallet. -pub struct ProviderParachainStateInfoViaProviderPallet(PhantomData); - -impl ProviderParachainStorageInfo for ProviderParachainStateInfoViaProviderPallet -where - T: pallet_dip_provider::Config, -{ - type BlockNumber = BlockNumberFor; - type Commitment = IdentityCommitmentOf; - type Hasher = T::Hashing; - type Identifier = T::Identifier; - type Key = StorageKey; - - fn dip_subject_storage_key(identifier: &Self::Identifier, version: IdentityCommitmentVersion) -> Self::Key { - StorageKey(pallet_dip_provider::IdentityCommitments::::hashed_key_for( - identifier, version, - )) - } -} +pub trait GetWithArg { + type Result; -/// A trait that provides the consumer parachain runtime additional context to -/// verify cross-chain DID signatures by subjects of the provider parachain. -pub trait DidSignatureVerifierContext { - /// Max number of blocks a cross-chain DID signature can have to be - /// considered fresh. - const SIGNATURE_VALIDITY: u16; - - /// The type of consumer parachain's block numbers. - type BlockNumber; - /// The type of consumer parachain's hashes. - type Hash; - /// Additional information that must be included in the payload being - /// DID-signed by the subject. - type SignedExtra; - - /// Returns the block number of the consumer's chain in which the DID - /// signature is being evaluated. - fn current_block_number() -> Self::BlockNumber; - /// Returns the genesis hash of the consumer's chain. - fn genesis_hash() -> Self::Hash; - /// Returns any additional info that must be appended to the payload before - /// verifying a cross-chain DID signature. - fn signed_extra() -> Self::SignedExtra; + fn get(arg: &Arg) -> Self::Result; } -/// Implementation of the [`DidSignatureVerifierContext`] trait that draws -/// information dynamically from the consumer's runtime using its system pallet. -/// The generic types are the following: -/// * `T`: The runtime including the [`frame_system::Pallet`] pallet. -/// * `SIGNATURE_VALIDITY`: The max number of blocks DID signatures can have to -/// be considered valid. -pub struct FrameSystemDidSignatureContext(PhantomData); +pub struct RelayStateRootsViaRelayStorePallet(PhantomData); -impl DidSignatureVerifierContext - for FrameSystemDidSignatureContext +impl GetWithArg for RelayStateRootsViaRelayStorePallet where - T: frame_system::Config, + Runtime: pallet_relay_store::Config, { - const SIGNATURE_VALIDITY: u16 = SIGNATURE_VALIDITY; - - type BlockNumber = BlockNumberFor; - type Hash = T::Hash; - type SignedExtra = (); + type Result = Option; - fn current_block_number() -> Self::BlockNumber { - frame_system::Pallet::::block_number() - } - - fn genesis_hash() -> Self::Hash { - frame_system::Pallet::::block_hash(Self::BlockNumber::zero()) - } - - fn signed_extra() -> Self::SignedExtra {} -} - -/// A trait that provides access to information on historical blocks. -pub trait HistoricalBlockRegistry { - /// The runtime definition of block numbers. - type BlockNumber; - /// The runtime hashing algorithm. - type Hasher: sp_runtime::traits::Hash; - - /// Retrieve a block hash given its number. - fn block_hash_for(block: &Self::BlockNumber) -> Option>; -} - -impl HistoricalBlockRegistry for T -where - T: frame_system::Config, -{ - type BlockNumber = BlockNumberFor; - type Hasher = T::Hashing; - - fn block_hash_for(block: &Self::BlockNumber) -> Option> { - let retrieved_block = frame_system::Pallet::::block_hash(block); - let default_block_hash_value = ::default(); - - if retrieved_block == default_block_hash_value { - None - } else { - Some(retrieved_block) - } + fn get(arg: &u32) -> Self::Result { + pallet_relay_store::Pallet::::latest_relay_head_for_block(arg) + .map(|relay_header| relay_header.relay_parent_storage_root) } } -pub trait GetWithArg { +pub trait GetWithoutArg { type Result; - fn get(arg: &Arg) -> Self::Result; + fn get() -> Self::Result; } -pub trait GetWithoutArg { - type Result; +impl GetWithoutArg for () { + type Result = (); - fn get() -> Self::Result; + fn get() -> Self::Result {} } diff --git a/dip-template/runtimes/dip-consumer/Cargo.toml b/dip-template/runtimes/dip-consumer/Cargo.toml index f6b7d428d4..2e9041158b 100644 --- a/dip-template/runtimes/dip-consumer/Cargo.toml +++ b/dip-template/runtimes/dip-consumer/Cargo.toml @@ -65,6 +65,9 @@ cumulus-primitives-utility.workspace = true pallet-collator-selection.workspace = true parachain-info.workspace = true +# Polkadot +rococo-runtime.workspace = true + # Benchmarks frame-benchmarking = {workspace = true, optional = true} frame-system-benchmarking = {workspace = true, optional = true} diff --git a/dip-template/runtimes/dip-consumer/src/dip.rs b/dip-template/runtimes/dip-consumer/src/dip.rs index 00868b9028..203a1f580d 100644 --- a/dip-template/runtimes/dip-consumer/src/dip.rs +++ b/dip-template/runtimes/dip-consumer/src/dip.rs @@ -16,16 +16,18 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -use did::{did_details::DidVerificationKey, DidVerificationKeyRelationship}; +use did::{DidVerificationKeyRelationship, KeyIdOf}; use dip_provider_runtime_template::{AccountId as ProviderAccountId, Runtime as ProviderRuntime}; use frame_support::traits::Contains; -use frame_system::EnsureSigned; +use frame_system::{pallet_prelude::BlockNumberFor, EnsureSigned}; use kilt_dip_primitives::{ - traits::DipCallOriginFilter, KiltVersionedParachainVerifier, RelayStateRootsViaRelayStorePallet, + merkle::RevealedDidKey, traits::DipCallOriginFilter, KiltVersionedParachainVerifier, + RelayStateRootsViaRelayStorePallet, }; use pallet_dip_consumer::traits::IdentityProofVerifier; +use rococo_runtime::Runtime as RelaychainRuntime; use sp_core::ConstU32; -use sp_runtime::traits::BlakeTwo256; +use sp_std::marker::PhantomData; use crate::{weights, AccountId, DidIdentifier, Runtime, RuntimeCall, RuntimeOrigin}; @@ -36,11 +38,13 @@ pub type MerkleProofVerifierOutput = , + RelaychainRuntime, RelayStateRootsViaRelayStorePallet, - BlakeTwo256, - DipCallFilter, + 2_000, + ProviderRuntime, + (), + DipCallFilter, BlockNumberFor, ProviderAccountId>, + 100, >; impl pallet_dip_consumer::Config for Runtime { @@ -126,21 +130,38 @@ pub enum DipCallFilterError { WrongVerificationRelationship, } +impl From for u8 { + fn from(value: DipCallFilterError) -> Self { + match value { + DipCallFilterError::BadOrigin => 1, + DipCallFilterError::WrongVerificationRelationship => 2, + } + } +} + /// A call filter that requires calls to the [`pallet_postit::Pallet`] pallet to /// be authorized with a DID signature generated with a key of a given /// verification relationship. -pub struct DipCallFilter; +pub struct DipCallFilter( + PhantomData<(ProviderDidKeyId, ProviderBlockNumber, ProviderAccountId)>, +); -impl DipCallOriginFilter for DipCallFilter { +impl DipCallOriginFilter + for DipCallFilter +{ type Error = DipCallFilterError; - type OriginInfo = (DidVerificationKey, DidVerificationKeyRelationship); + type OriginInfo = RevealedDidKey; type Success = (); // Accepts only a DipOrigin for the DidLookup pallet calls. fn check_call_origin_info(call: &RuntimeCall, info: &Self::OriginInfo) -> Result { - let key_relationship = + let revealed_key_relationship: DidVerificationKeyRelationship = info + .relationship + .try_into() + .map_err(|_| DipCallFilterError::WrongVerificationRelationship)?; + let expected_key_relationship = single_key_relationship([call].into_iter()).map_err(|_| DipCallFilterError::BadOrigin)?; - if info.1 == key_relationship { + if revealed_key_relationship == expected_key_relationship { Ok(()) } else { Err(DipCallFilterError::WrongVerificationRelationship) diff --git a/dip-template/runtimes/dip-consumer/src/origin_adapter.rs b/dip-template/runtimes/dip-consumer/src/origin_adapter.rs index 18d720c1f0..ad3e9153ac 100644 --- a/dip-template/runtimes/dip-consumer/src/origin_adapter.rs +++ b/dip-template/runtimes/dip-consumer/src/origin_adapter.rs @@ -18,6 +18,7 @@ use crate::{AccountId, DidIdentifier, MerkleProofVerifierOutput, RuntimeOrigin, Web3Name}; use frame_support::traits::EnsureOrigin; +use kilt_dip_primitives::RevealedDidMerkleProofLeaf; use pallet_dip_consumer::{DipOrigin, EnsureDipOrigin}; use pallet_postit::traits::GetUsername; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; @@ -52,12 +53,18 @@ pub struct DipOriginAdapter(DipOrigin Result { self.0 .details - .web3_name - .as_ref() - .map(|leaf| leaf.web3_name.clone()) + .iter() + .find_map(|revealed_leaf| { + if let RevealedDidMerkleProofLeaf::Web3Name(revealed_web3name_leaf) = revealed_leaf { + Some(revealed_web3name_leaf.web3_name.clone()) + } else { + None + } + }) .ok_or("No username for the subject.") } } From be28412cf66ae6c34cab6f4049719be950e3db83 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 12 Jan 2024 12:40:28 +0100 Subject: [PATCH 12/45] Whole project compiling --- .../src/verifier/parachain.rs | 20 +++++++++---------- .../src/verifier/relaychain.rs | 20 +++++++++---------- dip-template/runtimes/dip-consumer/src/dip.rs | 2 -- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index c676f2681b..7b595aa769 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -146,16 +146,16 @@ pub struct KiltVersionedParachainVerifier< RelaychainStateRootStore, const KILT_PARA_ID: u32, KiltRuntime, - SignedExtra, DidCallVerifier, - const MAX_LEAVES_REVEALED: u32, + SignedExtra = (), + const MAX_LEAVES_REVEALED: u32 = 50, >( PhantomData<( RelaychainRuntime, RelaychainStateRootStore, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, )>, ); @@ -165,8 +165,8 @@ impl< RelaychainStateRootStore, const KILT_PARA_ID: u32, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, const MAX_LEAVES_REVEALED: u32, > IdentityProofVerifier for KiltVersionedParachainVerifier< @@ -174,8 +174,8 @@ impl< RelaychainStateRootStore, KILT_PARA_ID, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, MAX_LEAVES_REVEALED, > where ConsumerRuntime: pallet_dip_consumer::Config, @@ -227,8 +227,8 @@ impl< RelaychainStateRootStore, KILT_PARA_ID, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, MAX_LEAVES_REVEALED, > as IdentityProofVerifier>::verify_proof_for_call_against_details( call, @@ -293,16 +293,16 @@ pub mod v0 { RelaychainStateRootStore, const KILT_PARA_ID: u32, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, const MAX_LEAVES_REVEALED: u32, >( PhantomData<( RelaychainRuntime, RelaychainStateRootStore, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, )>, ); @@ -312,8 +312,8 @@ pub mod v0 { RelaychainStateRootStore, const KILT_PARA_ID: u32, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, const MAX_LEAVES_REVEALED: u32, > IdentityProofVerifier for ParachainVerifier< @@ -321,8 +321,8 @@ pub mod v0 { RelaychainStateRootStore, KILT_PARA_ID, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, MAX_LEAVES_REVEALED, > where ConsumerRuntime: pallet_dip_consumer::Config, diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index 084382cb8f..9b5ac13302 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -147,26 +147,26 @@ pub struct KiltVersionedRelaychainVerifier< ConsumerBlockHashStore, const KILT_PARA_ID: u32, KiltRuntime, - SignedExtra, DidCallVerifier, - const MAX_LEAVES_REVEALED: u32, ->(#[allow(clippy::type_complexity)] PhantomData<(ConsumerBlockHashStore, KiltRuntime, SignedExtra, DidCallVerifier)>); + SignedExtra = (), + const MAX_LEAVES_REVEALED: u32 = 50, +>(#[allow(clippy::type_complexity)] PhantomData<(ConsumerBlockHashStore, KiltRuntime, DidCallVerifier, SignedExtra)>); impl< ConsumerRuntime, ConsumerBlockHashStore, const KILT_PARA_ID: u32, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, const MAX_LEAVES_REVEALED: u32, > IdentityProofVerifier for KiltVersionedRelaychainVerifier< ConsumerBlockHashStore, KILT_PARA_ID, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, MAX_LEAVES_REVEALED, > where ConsumerRuntime: pallet_dip_consumer::Config, @@ -217,8 +217,8 @@ impl< ConsumerBlockHashStore, KILT_PARA_ID, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, MAX_LEAVES_REVEALED, > as IdentityProofVerifier>::verify_proof_for_call_against_details( call, @@ -358,12 +358,12 @@ pub mod v0 { ConsumerBlockHashStore, const KILT_PARA_ID: u32, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, const MAX_LEAVES_REVEALED: u32, >( #[allow(clippy::type_complexity)] - PhantomData<(ConsumerBlockHashStore, KiltRuntime, SignedExtra, DidCallVerifier)>, + PhantomData<(ConsumerBlockHashStore, KiltRuntime, DidCallVerifier, SignedExtra)>, ); impl< @@ -371,16 +371,16 @@ pub mod v0 { ConsumerBlockHashStore, const KILT_PARA_ID: u32, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, const MAX_LEAVES_REVEALED: u32, > IdentityProofVerifier for RelaychainVerifier< ConsumerBlockHashStore, KILT_PARA_ID, KiltRuntime, - SignedExtra, DidCallVerifier, + SignedExtra, MAX_LEAVES_REVEALED, > where ConsumerRuntime: pallet_dip_consumer::Config, diff --git a/dip-template/runtimes/dip-consumer/src/dip.rs b/dip-template/runtimes/dip-consumer/src/dip.rs index 203a1f580d..ea1835f2b4 100644 --- a/dip-template/runtimes/dip-consumer/src/dip.rs +++ b/dip-template/runtimes/dip-consumer/src/dip.rs @@ -42,9 +42,7 @@ pub type ProofVerifier = KiltVersionedParachainVerifier< RelayStateRootsViaRelayStorePallet, 2_000, ProviderRuntime, - (), DipCallFilter, BlockNumberFor, ProviderAccountId>, - 100, >; impl pallet_dip_consumer::Config for Runtime { From 91e9f461747a828e71c054bf07e8da31c89989db Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 12 Jan 2024 16:58:52 +0100 Subject: [PATCH 13/45] New design in progress --- crates/kilt-dip-primitives/src/lib.rs | 2 + crates/kilt-dip-primitives/src/test.rs | 543 ++++++++++++++++++ .../kilt-dip-primitives/src/verifier/mod.rs | 2 +- 3 files changed, 546 insertions(+), 1 deletion(-) create mode 100644 crates/kilt-dip-primitives/src/test.rs diff --git a/crates/kilt-dip-primitives/src/lib.rs b/crates/kilt-dip-primitives/src/lib.rs index 5ecf1b6008..15a1c3d10b 100644 --- a/crates/kilt-dip-primitives/src/lib.rs +++ b/crates/kilt-dip-primitives/src/lib.rs @@ -33,6 +33,8 @@ pub mod traits; pub mod utils; pub mod verifier; +mod test; + pub use merkle::RevealedDidMerkleProofLeaf; pub use traits::RelayStateRootsViaRelayStorePallet; pub use utils::BoundedBlindedValue; diff --git a/crates/kilt-dip-primitives/src/test.rs b/crates/kilt-dip-primitives/src/test.rs new file mode 100644 index 0000000000..fedfa8f05f --- /dev/null +++ b/crates/kilt-dip-primitives/src/test.rs @@ -0,0 +1,543 @@ +use did::{ + did_details::{DidPublicKey, DidPublicKeyDetails}, + DidSignature, +}; +use frame_support::ensure; +use parity_scale_codec::{Decode, Encode}; +use sp_core::ConstU32; +use sp_runtime::{ + traits::{Hash, Header}, + BoundedVec, SaturatedConversion, +}; +use sp_trie::{verify_trie_proof, LayoutV1}; + +use crate::{ + common::{calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key}, + did::TimeBoundDidSignature, + merkle::{DidKeyRelationship, RevealedDidKey}, + state_proofs::{verify_storage_value_proof, MerkleProofError}, + traits::GetWithArg, + utils::OutputOf, + RevealedDidMerkleProofLeaf, +}; + +pub struct ProviderHeadProof { + pub(crate) relay_block_number: RelayBlockNumber, + pub(crate) proof: BoundedVec>, ConstU32>, +} + +pub struct DipCommitmentProof( + BoundedVec>, ConstU32>, +); + +pub struct DidMerkleProof< + ProviderDidKeyId, + ProviderAccountId, + ProviderBlockNumber, + ProviderWeb3Name, + ProviderLinkableAccountId, + const MAX_BLINDED_LEAVE_COUNT: u32, + const MAX_BLINDED_LEAVE_SIZE: u32, + const MAX_LEAVES_REVEALED: u32, +> { + pub blinded: BoundedVec>, ConstU32>, + pub revealed: BoundedVec< + RevealedDidMerkleProofLeaf< + ProviderDidKeyId, + ProviderAccountId, + ProviderBlockNumber, + ProviderWeb3Name, + ProviderLinkableAccountId, + >, + ConstU32, + >, +} + +pub enum Error { + ProviderHeadProof(MerkleProofError), + RelayStateRootNotFound, +} + +pub struct DipDidProof< + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_LEAVE_COUNT: u32, + const MAX_LEAVE_SIZE: u32, + const MAX_DIP_LEAVES_REVEALED: u32, +> { + pub(crate) provider_head_proof: ProviderHeadProof, + pub(crate) dip_commitment_proof: DipCommitmentProof, + pub(crate) dip_proof: DidMerkleProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_LEAVE_COUNT, + MAX_LEAVE_SIZE, + MAX_DIP_LEAVES_REVEALED, + >, + pub(crate) signature: TimeBoundDidSignature, +} + +impl< + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_LEAVE_COUNT: u32, + const MAX_LEAVE_SIZE: u32, + const MAX_DIP_LEAVES_REVEALED: u32, + > + DipDidProof< + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_LEAVE_COUNT, + MAX_LEAVE_SIZE, + MAX_DIP_LEAVES_REVEALED, + > +{ + fn verify_top_level_head_proof_for_provider_and_state_root( + self, + provider_para_id: u32, + relay_state_root: &OutputOf, + ) -> Result< + RelayVerifiedDipProof< + OutputOf, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_LEAVE_COUNT, + MAX_LEAVE_SIZE, + MAX_DIP_LEAVES_REVEALED, + >, + Error, + > + where + RelayHasher: Hash, + ProviderHeader: Decode + Header, + { + let provider_head_storage_key = calculate_parachain_head_storage_key(provider_para_id); + let provider_header = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( + &provider_head_storage_key, + *relay_state_root, + self.provider_head_proof.proof.into_iter().map(|i| i.into()), + ) + .map_err(Error::ProviderHeadProof)?; + Ok(RelayVerifiedDipProof { + state_root: *provider_header.state_root(), + dip_commitment_proof: self.dip_commitment_proof, + dip_proof: self.dip_proof, + signature: self.signature, + }) + } + + fn verify_top_level_head_proof_for_provider( + self, + provider_para_id: u32, + ) -> Result< + RelayVerifiedDipProof< + OutputOf, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_LEAVE_COUNT, + MAX_LEAVE_SIZE, + MAX_DIP_LEAVES_REVEALED, + >, + Error, + > + where + RelayHasher: Hash, + StateRootStore: GetWithArg>>, + ProviderHeader: Decode + Header, + { + let relay_state_root = + StateRootStore::get(&self.provider_head_proof.relay_block_number).ok_or(Error::RelayStateRootNotFound)?; + self.verify_top_level_head_proof_for_provider_and_state_root::( + provider_para_id, + &relay_state_root, + ) + } +} + +pub struct RelayVerifiedDipProof< + StateRoot, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_LEAVE_COUNT: u32, + const MAX_LEAVE_SIZE: u32, + const MAX_DIP_LEAVES_REVEALED: u32, +> { + pub(crate) state_root: StateRoot, + pub(crate) dip_commitment_proof: DipCommitmentProof, + pub(crate) dip_proof: DidMerkleProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_LEAVE_COUNT, + MAX_LEAVE_SIZE, + MAX_DIP_LEAVES_REVEALED, + >, + pub(crate) signature: TimeBoundDidSignature, +} + +impl< + StateRoot, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_LEAVE_COUNT: u32, + const MAX_LEAVE_SIZE: u32, + const MAX_DIP_LEAVES_REVEALED: u32, + > + RelayVerifiedDipProof< + StateRoot, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_LEAVE_COUNT, + MAX_LEAVE_SIZE, + MAX_DIP_LEAVES_REVEALED, + > +{ + fn verify_dip_commitment_proof_for_subject( + self, + subject: &ProviderRuntime::Identifier, + ) -> Result< + CommitmentVerifiedProof< + Commitment, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_LEAVE_COUNT, + MAX_LEAVE_SIZE, + MAX_DIP_LEAVES_REVEALED, + >, + Error, + > + where + MerkleHasher: Hash, + StateRoot: Into>, + ProviderRuntime: pallet_dip_provider::Config, + Commitment: Decode, + OutputOf: Into, + { + let dip_commitment_storage_key = + calculate_dip_identity_commitment_storage_key_for_runtime::(subject, 0); + let dip_commitment = verify_storage_value_proof::<_, MerkleHasher, Commitment>( + &dip_commitment_storage_key, + self.state_root.into(), + self.dip_commitment_proof.0.into_iter().map(|i| i.into()), + ) + .map_err(Error::ProviderHeadProof)?; + Ok(CommitmentVerifiedProof { + dip_commitment, + dip_proof: self.dip_proof, + signature: self.signature, + }) + } +} + +pub(crate) struct CommitmentVerifiedProof< + Commitment, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_LEAVE_COUNT: u32, + const MAX_LEAVE_SIZE: u32, + const MAX_DIP_LEAVES_REVEALED: u32, +> { + pub(crate) dip_commitment: Commitment, + pub(crate) dip_proof: DidMerkleProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_LEAVE_COUNT, + MAX_LEAVE_SIZE, + MAX_DIP_LEAVES_REVEALED, + >, + pub(crate) signature: TimeBoundDidSignature, +} + +impl< + Commitment, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_LEAVE_COUNT: u32, + const MAX_LEAVE_SIZE: u32, + const MAX_DIP_LEAVES_REVEALED: u32, + > + CommitmentVerifiedProof< + Commitment, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_LEAVE_COUNT, + MAX_LEAVE_SIZE, + MAX_DIP_LEAVES_REVEALED, + > where + KiltDidKeyId: Encode, + KiltAccountId: Encode, + KiltBlockNumber: Encode, + KiltWeb3Name: Encode, + KiltLinkableAccountId: Encode, +{ + fn verify_dip_proof( + self, + ) -> Result< + DipVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_DIP_LEAVES_REVEALED, + >, + Error, + > + where + MerkleHasher: Hash, + { + let mut revealed_keys = self + .dip_proof + .revealed + .iter() + .take(MAX_DIP_LEAVES_REVEALED.saturated_into()); + + // If there are more keys than MAX_LEAVES_REVEALED, bail out. + ensure!( + revealed_keys.next().is_none(), + // TODO: Change + Error::RelayStateRootNotFound, + ); + + let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = revealed_keys + .by_ref() + .map(|revealed_leaf| (revealed_leaf.encoded_key(), Some(revealed_leaf.encoded_value()))) + .collect(); + + verify_trie_proof::, _, _, _>( + &self.dip_commitment, + self.dip_proof + .blinded + .into_iter() + .map(|l| l.into_inner()) + .collect::>() + .as_slice(), + &proof_leaves_key_value_pairs, + ) + // TODO: Change + .map_err(|_| Error::RelayStateRootNotFound)?; + + Ok(DipVerifiedProof { + revealed_leaves: self.dip_proof.revealed, + signature: self.signature, + }) + } +} + +pub(crate) struct DipVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_DIP_LEAVES_REVEALED: u32, +> { + pub(crate) revealed_leaves: BoundedVec< + RevealedDidMerkleProofLeaf, + ConstU32, + >, + pub(crate) signature: TimeBoundDidSignature, +} + +impl< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_DIP_LEAVES_REVEALED: u32, + > + DipVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_DIP_LEAVES_REVEALED, + > where + ConsumerBlockNumber: PartialOrd, +{ + fn verify_signature_time( + self, + block_number: &ConsumerBlockNumber, + ) -> Result< + DipSignatureTimeVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_DIP_LEAVES_REVEALED, + >, + Error, + > { + ensure!( + self.signature.valid_until >= *block_number, + Error::RelayStateRootNotFound + ); + Ok(DipSignatureTimeVerifiedProof { + revealed_leaves: self.revealed_leaves, + signature: self.signature.signature, + }) + } +} + +pub(crate) struct DipSignatureTimeVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + const MAX_DIP_LEAVES_REVEALED: u32, +> { + pub(crate) revealed_leaves: BoundedVec< + RevealedDidMerkleProofLeaf, + ConstU32, + >, + pub(crate) signature: DidSignature, +} + +impl< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + const MAX_DIP_LEAVES_REVEALED: u32, + > + DipSignatureTimeVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_DIP_LEAVES_REVEALED, + > +{ + fn retrieve_signing_leaf_for_payload<'a>( + self, + payload: &[u8], + ) -> Result< + DipSignatureVerifiedProof< + 'a, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_DIP_LEAVES_REVEALED, + >, + Error, + > { + let revealed_verification_keys = self.revealed_leaves.iter().filter(|leaf| { + matches!( + leaf, + RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { + relationship: DidKeyRelationship::Verification(verification_relationship), + .. + }) + ) + }); + let signing_key = revealed_verification_keys + .find(|revealed_verification_key| { + let RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { + details: + DidPublicKeyDetails { + key: DidPublicKey::PublicVerificationKey(verification_key), + .. + }, + .. + }) = revealed_verification_key + else { + return false; + }; + verification_key.verify_signature(payload, &self.signature).is_ok() + // TODO: Change + }) + .ok_or(Error::RelayStateRootNotFound)?; + Ok(DipSignatureVerifiedProof { + revealed_leaves: self.revealed_leaves, + // TODO: Fix this compilation issue, and then we are golden! + signing_leaf: RevealedDidMerkleProofLeaf::DidKey(signing_key), + }) + } +} + +pub(crate) struct DipSignatureVerifiedProof< + 'a, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + const MAX_DIP_LEAVES_REVEALED: u32, +> { + pub(crate) revealed_leaves: BoundedVec< + RevealedDidMerkleProofLeaf, + ConstU32, + >, + pub(crate) signing_leaf: &'a RevealedDidKey, +} diff --git a/crates/kilt-dip-primitives/src/verifier/mod.rs b/crates/kilt-dip-primitives/src/verifier/mod.rs index f98576991d..663d7c889e 100644 --- a/crates/kilt-dip-primitives/src/verifier/mod.rs +++ b/crates/kilt-dip-primitives/src/verifier/mod.rs @@ -18,7 +18,7 @@ /// Verification logic to integrate a child chain as a DIP provider. // pub mod relaychain; -mod common; +pub(crate) mod common; /// Verification logic to integrate a sibling chain as a DIP provider. pub mod parachain; /// Verification logic to integrate a child chain as a DIP provider. From b5398d1165760018c77a7d22af547f16ccebbd31 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Mon, 15 Jan 2024 08:38:39 +0100 Subject: [PATCH 14/45] Refactor --- crates/kilt-dip-primitives/src/did.rs | 81 -- crates/kilt-dip-primitives/src/merkle.rs | 250 ------ .../kilt-dip-primitives/src/merkle_proof.rs | 735 ++++++++++++++++++ crates/kilt-dip-primitives/src/test.rs | 543 ------------- 4 files changed, 735 insertions(+), 874 deletions(-) delete mode 100644 crates/kilt-dip-primitives/src/did.rs delete mode 100644 crates/kilt-dip-primitives/src/merkle.rs create mode 100644 crates/kilt-dip-primitives/src/merkle_proof.rs delete mode 100644 crates/kilt-dip-primitives/src/test.rs diff --git a/crates/kilt-dip-primitives/src/did.rs b/crates/kilt-dip-primitives/src/did.rs deleted file mode 100644 index f426ee63ae..0000000000 --- a/crates/kilt-dip-primitives/src/did.rs +++ /dev/null @@ -1,81 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 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 - -//! Module to deal with cross-chain KILT DIDs. - -use did::DidSignature; -use frame_support::ensure; -use parity_scale_codec::{Decode, Encode}; -use scale_info::TypeInfo; -use sp_core::RuntimeDebug; - -/// A DID signature anchored to a specific block height. -#[derive(Encode, Decode, RuntimeDebug, Clone, Eq, PartialEq, TypeInfo)] -pub struct TimeBoundDidSignature { - /// The signature. - pub signature: DidSignature, - /// The block number until the signature is to be considered valid. - pub valid_until: BlockNumber, -} - -impl TimeBoundDidSignature -where - BlockNumber: PartialOrd, -{ - /// Verifies if the DID signature is expired and returns the signature - /// information after stripping time-related information. - pub fn extract_signature_if_not_expired( - self, - current_block_number: BlockNumber, - ) -> Result { - ensure!( - self.valid_until >= current_block_number, - DidSignatureVerificationError::SignatureExpired - ); - - Ok(self.signature) - } -} - -#[cfg(feature = "runtime-benchmarks")] -impl kilt_support::traits::GetWorstCase for TimeBoundDidSignature -where - DidSignature: kilt_support::traits::GetWorstCase, - BlockNumber: Default, -{ - fn worst_case(context: Context) -> Self { - Self { - signature: DidSignature::worst_case(context), - valid_until: BlockNumber::default(), - } - } -} - -pub enum DidSignatureVerificationError { - SignatureExpired, - SignerNotFound, -} - -impl From for u8 { - fn from(value: DidSignatureVerificationError) -> Self { - match value { - DidSignatureVerificationError::SignatureExpired => 1, - DidSignatureVerificationError::SignerNotFound => 2, - } - } -} diff --git a/crates/kilt-dip-primitives/src/merkle.rs b/crates/kilt-dip-primitives/src/merkle.rs deleted file mode 100644 index 974cf33c4b..0000000000 --- a/crates/kilt-dip-primitives/src/merkle.rs +++ /dev/null @@ -1,250 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 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 - -//! Module to deal with cross-chain Merkle proof as generated by the KILT chain. - -use did::{did_details::DidPublicKeyDetails, DidVerificationKeyRelationship}; -use frame_support::{ensure, RuntimeDebug}; -use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; -use sp_runtime::traits::Hash; -use sp_std::vec::Vec; -use sp_trie::{verify_trie_proof, LayoutV1}; - -use crate::{utils::OutputOf, BoundedBlindedValue}; - -/// Type of a Merkle proof containing DID-related information. -/// The generic types are the following: -/// * `KeyId`: The type of a DID key ID according to the producer's definition. -/// * `AccountId`: The type of an account ID according to the producer's -/// definition. -/// * `BlockNumber`: The type of a block number according to the producer's -/// definition. -/// * `Web3Name`: The type of a web3names according to the producer's -/// definition. -/// * `LinkedAccountId`: The type of a DID-linked account ID according to the -/// producer's definition. -#[derive(Encode, Decode, RuntimeDebug, Clone, Eq, PartialEq, TypeInfo)] -pub struct DidMerkleProof { - pub blinded: BoundedBlindedValue, - pub revealed: Vec>, -} - -impl - DidMerkleProof -where - KeyId: Encode, - AccountId: Encode, - BlockNumber: Encode, - Web3Name: Encode, - LinkedAccountId: Encode, -{ - /// Verifies the DIP Merkle proof revealing some leaves - /// representing parts of a KILT DID identity stored on the KILT chain - /// against a given identity commitment. If cross-chain DID signatures are - /// not required for the specific use case, this verifier can also be used - /// on its own, without any DID signature verification. - /// The Merkle proof is assumed to have been generated using one of the - /// versioned identity commitment generators, as shown in the [KILT runtime - /// definitions](../../../runtimes/common/src/dip/README.md). The function - /// returns the revealed leaves if the Merkle proof is correct and if the - /// number of leaves does not exceed the maximum configured. The generic - /// types are the following: - /// * `Hasher`: The hasher used by the producer to hash the Merkle leaves - /// and produce the identity commitment. - pub fn verify_against_commitment( - self, - commitment: &OutputOf, - max_leaves_revealed: usize, - ) -> Result< - impl IntoIterator>, - DidMerkleProofVerificationError, - > - where - Hasher: Hash, - { - let mut revealed_keys = self.revealed.iter().take(max_leaves_revealed); - // If there are more keys than MAX_LEAVES_REVEALED, bail out. - ensure!( - revealed_keys.next().is_none(), - DidMerkleProofVerificationError::TooManyLeaves, - ); - let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = revealed_keys - .by_ref() - .map(|revealed_leaf| (revealed_leaf.encoded_key(), Some(revealed_leaf.encoded_value()))) - .collect(); - - verify_trie_proof::, _, _, _>(commitment, &self.blinded, &proof_leaves_key_value_pairs) - .map_err(|_| DidMerkleProofVerificationError::InvalidMerkleProof)?; - - Ok(self.revealed) - } -} - -/// Relationship of a key to a DID Document. -#[derive(Clone, Copy, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, PartialOrd, Ord, MaxEncodedLen)] -pub enum DidKeyRelationship { - Encryption, - Verification(DidVerificationKeyRelationship), -} - -impl From for DidKeyRelationship { - fn from(value: DidVerificationKeyRelationship) -> Self { - Self::Verification(value) - } -} - -impl TryFrom for DidVerificationKeyRelationship { - type Error = (); - - fn try_from(value: DidKeyRelationship) -> Result { - if let DidKeyRelationship::Verification(rel) = value { - Ok(rel) - } else { - Err(()) - } - } -} - -/// All possible Merkle leaf types that can be revealed as part of a DIP -/// identity Merkle proof. -#[derive(Clone, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub enum RevealedDidMerkleProofLeaf { - DidKey(RevealedDidKey), - Web3Name(RevealedWeb3Name), - LinkedAccount(RevealedAccountId), -} - -impl From> - for RevealedDidMerkleProofLeaf -{ - fn from(value: RevealedDidKey) -> Self { - Self::DidKey(value) - } -} - -impl From> - for RevealedDidMerkleProofLeaf -{ - fn from(value: RevealedWeb3Name) -> Self { - Self::Web3Name(value) - } -} - -impl From> - for RevealedDidMerkleProofLeaf -{ - fn from(value: RevealedAccountId) -> Self { - Self::LinkedAccount(value) - } -} - -#[cfg(feature = "runtime-benchmarks")] -impl Default - for RevealedDidMerkleProofLeaf -where - KeyId: Default, - BlockNumber: Default, -{ - fn default() -> Self { - RevealedDidKey { - id: KeyId::default(), - relationship: DidVerificationKeyRelationship::Authentication.into(), - details: DidPublicKeyDetails { - key: did::did_details::DidVerificationKey::Ed25519(sp_core::ed25519::Public::from_raw([0u8; 32])) - .into(), - block_number: BlockNumber::default(), - }, - } - .into() - } -} - -impl - RevealedDidMerkleProofLeaf -where - KeyId: Encode, - Web3Name: Encode, - LinkedAccountId: Encode, -{ - pub fn encoded_key(&self) -> Vec { - match self { - RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { id, relationship, .. }) => (id, relationship).encode(), - RevealedDidMerkleProofLeaf::Web3Name(RevealedWeb3Name { web3_name, .. }) => web3_name.encode(), - RevealedDidMerkleProofLeaf::LinkedAccount(RevealedAccountId(account_id)) => account_id.encode(), - } - } -} - -impl - RevealedDidMerkleProofLeaf -where - AccountId: Encode, - BlockNumber: Encode, -{ - pub fn encoded_value(&self) -> Vec { - match self { - RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { details, .. }) => details.encode(), - RevealedDidMerkleProofLeaf::Web3Name(RevealedWeb3Name { claimed_at, .. }) => claimed_at.encode(), - RevealedDidMerkleProofLeaf::LinkedAccount(_) => ().encode(), - } - } -} - -/// The details of a DID key after it has been successfully verified in a Merkle -/// proof. -#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] -pub struct RevealedDidKey { - /// The key ID, according to the provider's definition. - pub id: KeyId, - /// The key relationship to the subject's DID Document. - pub relationship: DidKeyRelationship, - /// The details of the DID Key, including its creation block number on the - /// provider chain. - pub details: DidPublicKeyDetails, -} - -/// The details of a web3name after it has been successfully verified in a -/// Merkle proof. -#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] -pub struct RevealedWeb3Name { - /// The web3name. - pub web3_name: Web3Name, - /// The block number on the provider chain in which it was linked to the DID - /// subject. - pub claimed_at: BlockNumber, -} - -/// The details of an account after it has been successfully verified in a -/// Merkle proof. -#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] -pub struct RevealedAccountId(pub AccountId); - -pub enum DidMerkleProofVerificationError { - InvalidMerkleProof, - TooManyLeaves, -} - -impl From for u8 { - fn from(value: DidMerkleProofVerificationError) -> Self { - match value { - DidMerkleProofVerificationError::InvalidMerkleProof => 1, - DidMerkleProofVerificationError::TooManyLeaves => 2, - } - } -} diff --git a/crates/kilt-dip-primitives/src/merkle_proof.rs b/crates/kilt-dip-primitives/src/merkle_proof.rs new file mode 100644 index 0000000000..0a405db7b3 --- /dev/null +++ b/crates/kilt-dip-primitives/src/merkle_proof.rs @@ -0,0 +1,735 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 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 + +//! Module to deal with cross-chain Merkle proof as generated by the KILT chain. + +use did::{ + did_details::{DidPublicKey, DidPublicKeyDetails}, + DidSignature, DidVerificationKeyRelationship, +}; +use frame_support::{ensure, RuntimeDebug}; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_core::ConstU32; +use sp_runtime::{ + traits::{Hash, Header}, + BoundedVec, SaturatedConversion, +}; +use sp_std::vec::Vec; +use sp_trie::{verify_trie_proof, LayoutV1}; + +use crate::{ + common::{calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key}, + state_proofs::{verify_storage_value_proof, MerkleProofError}, + traits::GetWithArg, + utils::OutputOf, +}; + +pub struct ProviderHeadProof { + pub(crate) relay_block_number: RelayBlockNumber, + pub(crate) proof: BoundedVec>, ConstU32>, +} + +pub struct DipCommitmentProof( + pub(crate) BoundedVec>, ConstU32>, +); + +pub struct DidMerkleProof< + ProviderDidKeyId, + ProviderAccountId, + ProviderBlockNumber, + ProviderWeb3Name, + ProviderLinkableAccountId, + const MAX_BLINDED_LEAVE_COUNT: u32, + const MAX_BLINDED_LEAVE_SIZE: u32, + const MAX_LEAVES_REVEALED: u32, +> { + pub(crate) blinded: BoundedVec>, ConstU32>, + pub(crate) revealed: BoundedVec< + RevealedDidMerkleProofLeaf< + ProviderDidKeyId, + ProviderAccountId, + ProviderBlockNumber, + ProviderWeb3Name, + ProviderLinkableAccountId, + >, + ConstU32, + >, +} + +/// A DID signature anchored to a specific block height. +#[derive(Encode, Decode, RuntimeDebug, Clone, Eq, PartialEq, TypeInfo)] +pub struct TimeBoundDidSignature { + /// The signature. + pub(crate) signature: DidSignature, + /// The block number until the signature is to be considered valid. + pub(crate) valid_until: BlockNumber, +} + +pub struct DipDidProof< + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, +> { + pub(crate) provider_head_proof: + ProviderHeadProof, + pub(crate) dip_commitment_proof: + DipCommitmentProof, + pub(crate) dip_proof: DidMerkleProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + pub(crate) signature: TimeBoundDidSignature, +} + +pub enum Error { + ProviderHeadProof(MerkleProofError), + RelayStateRootNotFound, +} + +impl< + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, + > + DipDidProof< + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + > +{ + pub fn verify_top_level_head_proof_for_provider_and_state_root( + self, + provider_para_id: u32, + relay_state_root: &OutputOf, + ) -> Result< + RelayVerifiedDipProof< + OutputOf, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + Error, + > + where + RelayHasher: Hash, + ProviderHeader: Decode + Header, + { + let provider_head_storage_key = calculate_parachain_head_storage_key(provider_para_id); + let provider_header = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( + &provider_head_storage_key, + *relay_state_root, + self.provider_head_proof.proof.into_iter().map(|i| i.into()), + ) + .map_err(Error::ProviderHeadProof)?; + Ok(RelayVerifiedDipProof { + state_root: *provider_header.state_root(), + dip_commitment_proof: self.dip_commitment_proof, + dip_proof: self.dip_proof, + signature: self.signature, + }) + } + + pub fn verify_top_level_head_proof_for_provider( + self, + provider_para_id: u32, + ) -> Result< + RelayVerifiedDipProof< + OutputOf, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + Error, + > + where + RelayHasher: Hash, + StateRootStore: GetWithArg>>, + ProviderHeader: Decode + Header, + { + let relay_state_root = + StateRootStore::get(&self.provider_head_proof.relay_block_number).ok_or(Error::RelayStateRootNotFound)?; + self.verify_top_level_head_proof_for_provider_and_state_root::( + provider_para_id, + &relay_state_root, + ) + } +} + +pub struct RelayVerifiedDipProof< + StateRoot, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, +> { + pub(crate) state_root: StateRoot, + pub(crate) dip_commitment_proof: + DipCommitmentProof, + pub(crate) dip_proof: DidMerkleProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + pub(crate) signature: TimeBoundDidSignature, +} + +impl< + StateRoot, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, + > + RelayVerifiedDipProof< + StateRoot, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + > +{ + pub fn verify_dip_commitment_proof_for_subject( + self, + subject: &ProviderRuntime::Identifier, + ) -> Result< + CommitmentVerifiedProof< + Commitment, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + Error, + > + where + MerkleHasher: Hash, + StateRoot: Into>, + ProviderRuntime: pallet_dip_provider::Config, + Commitment: Decode, + OutputOf: Into, + { + let dip_commitment_storage_key = + calculate_dip_identity_commitment_storage_key_for_runtime::(subject, 0); + let dip_commitment = verify_storage_value_proof::<_, MerkleHasher, Commitment>( + &dip_commitment_storage_key, + self.state_root.into(), + self.dip_commitment_proof.0.into_iter().map(|i| i.into()), + ) + .map_err(Error::ProviderHeadProof)?; + Ok(CommitmentVerifiedProof { + dip_commitment, + dip_proof: self.dip_proof, + signature: self.signature, + }) + } +} + +pub(crate) struct CommitmentVerifiedProof< + Commitment, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, +> { + pub(crate) dip_commitment: Commitment, + pub(crate) dip_proof: DidMerkleProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + pub(crate) signature: TimeBoundDidSignature, +} + +impl< + Commitment, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, + > + CommitmentVerifiedProof< + Commitment, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + > where + KiltDidKeyId: Encode, + KiltAccountId: Encode, + KiltBlockNumber: Encode, + KiltWeb3Name: Encode, + KiltLinkableAccountId: Encode, +{ + pub fn verify_dip_proof( + self, + ) -> Result< + DipVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + Error, + > + where + MerkleHasher: Hash, + { + let mut revealed_keys = self + .dip_proof + .revealed + .iter() + .take(MAX_DID_MERKLE_LEAVES_REVEALED.saturated_into()); + + // If there are more keys than MAX_LEAVES_REVEALED, bail out. + ensure!( + revealed_keys.next().is_none(), + // TODO: Change + Error::RelayStateRootNotFound, + ); + + let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = revealed_keys + .by_ref() + .map(|revealed_leaf| (revealed_leaf.encoded_key(), Some(revealed_leaf.encoded_value()))) + .collect(); + + verify_trie_proof::, _, _, _>( + &self.dip_commitment, + self.dip_proof + .blinded + .into_iter() + .map(|l| l.into_inner()) + .collect::>() + .as_slice(), + &proof_leaves_key_value_pairs, + ) + // TODO: Change + .map_err(|_| Error::RelayStateRootNotFound)?; + + Ok(DipVerifiedProof { + revealed_leaves: self.dip_proof.revealed, + signature: self.signature, + }) + } +} + +pub(crate) struct DipVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, +> { + pub(crate) revealed_leaves: BoundedVec< + RevealedDidMerkleProofLeaf, + ConstU32, + >, + pub(crate) signature: TimeBoundDidSignature, +} + +impl< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, + > + DipVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_DID_MERKLE_LEAVES_REVEALED, + > where + ConsumerBlockNumber: PartialOrd, +{ + pub fn verify_signature_time( + self, + block_number: &ConsumerBlockNumber, + ) -> Result< + DipSignatureTimeVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + Error, + > { + ensure!( + self.signature.valid_until >= *block_number, + Error::RelayStateRootNotFound + ); + Ok(DipSignatureTimeVerifiedProof { + revealed_leaves: self.revealed_leaves, + signature: self.signature.signature, + }) + } +} + +pub(crate) struct DipSignatureTimeVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, +> { + pub(crate) revealed_leaves: BoundedVec< + RevealedDidMerkleProofLeaf, + ConstU32, + >, + pub(crate) signature: DidSignature, +} + +impl< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, + > + DipSignatureTimeVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_DID_MERKLE_LEAVES_REVEALED, + > +{ + pub fn retrieve_signing_leaf_for_payload<'a>( + self, + payload: &[u8], + ) -> Result< + DipSignatureVerifiedProof< + 'a, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + Error, + > { + let revealed_verification_keys = self.revealed_leaves.iter().filter(|leaf| { + matches!( + leaf, + RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { + relationship: DidKeyRelationship::Verification(verification_relationship), + .. + }) + ) + }); + let signing_key = revealed_verification_keys + .find(|revealed_verification_key| { + let RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { + details: + DidPublicKeyDetails { + key: DidPublicKey::PublicVerificationKey(verification_key), + .. + }, + .. + }) = revealed_verification_key + else { + return false; + }; + verification_key.verify_signature(payload, &self.signature).is_ok() + // TODO: Change + }) + .ok_or(Error::RelayStateRootNotFound)?; + Ok(DipSignatureVerifiedProof { + revealed_leaves: self.revealed_leaves, + // TODO: Fix this compilation issue, and then we are golden! + signing_leaf: RevealedDidMerkleProofLeaf::DidKey(signing_key), + }) + } +} + +pub(crate) struct DipSignatureVerifiedProof< + 'a, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, +> { + pub revealed_leaves: BoundedVec< + RevealedDidMerkleProofLeaf, + ConstU32, + >, + pub signing_leaf: &'a RevealedDidKey, +} + +/// Relationship of a key to a DID Document. +#[derive(Clone, Copy, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, PartialOrd, Ord, MaxEncodedLen)] +pub enum DidKeyRelationship { + Encryption, + Verification(DidVerificationKeyRelationship), +} + +impl From for DidKeyRelationship { + fn from(value: DidVerificationKeyRelationship) -> Self { + Self::Verification(value) + } +} + +impl TryFrom for DidVerificationKeyRelationship { + type Error = (); + + fn try_from(value: DidKeyRelationship) -> Result { + if let DidKeyRelationship::Verification(rel) = value { + Ok(rel) + } else { + Err(()) + } + } +} + +/// All possible Merkle leaf types that can be revealed as part of a DIP +/// identity Merkle proof. +#[derive(Clone, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum RevealedDidMerkleProofLeaf { + DidKey(RevealedDidKey), + Web3Name(RevealedWeb3Name), + LinkedAccount(RevealedAccountId), +} + +impl From> + for RevealedDidMerkleProofLeaf +{ + fn from(value: RevealedDidKey) -> Self { + Self::DidKey(value) + } +} + +impl From> + for RevealedDidMerkleProofLeaf +{ + fn from(value: RevealedWeb3Name) -> Self { + Self::Web3Name(value) + } +} + +impl From> + for RevealedDidMerkleProofLeaf +{ + fn from(value: RevealedAccountId) -> Self { + Self::LinkedAccount(value) + } +} + +#[cfg(feature = "runtime-benchmarks")] +impl Default + for RevealedDidMerkleProofLeaf +where + KeyId: Default, + BlockNumber: Default, +{ + fn default() -> Self { + RevealedDidKey { + id: KeyId::default(), + relationship: DidVerificationKeyRelationship::Authentication.into(), + details: DidPublicKeyDetails { + key: did::did_details::DidVerificationKey::Ed25519(sp_core::ed25519::Public::from_raw([0u8; 32])) + .into(), + block_number: BlockNumber::default(), + }, + } + .into() + } +} + +impl + RevealedDidMerkleProofLeaf +where + KeyId: Encode, + Web3Name: Encode, + LinkedAccountId: Encode, +{ + pub fn encoded_key(&self) -> Vec { + match self { + RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { id, relationship, .. }) => (id, relationship).encode(), + RevealedDidMerkleProofLeaf::Web3Name(RevealedWeb3Name { web3_name, .. }) => web3_name.encode(), + RevealedDidMerkleProofLeaf::LinkedAccount(RevealedAccountId(account_id)) => account_id.encode(), + } + } +} + +impl + RevealedDidMerkleProofLeaf +where + AccountId: Encode, + BlockNumber: Encode, +{ + pub fn encoded_value(&self) -> Vec { + match self { + RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { details, .. }) => details.encode(), + RevealedDidMerkleProofLeaf::Web3Name(RevealedWeb3Name { claimed_at, .. }) => claimed_at.encode(), + RevealedDidMerkleProofLeaf::LinkedAccount(_) => ().encode(), + } + } +} + +/// The details of a DID key after it has been successfully verified in a Merkle +/// proof. +#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] +pub struct RevealedDidKey { + /// The key ID, according to the provider's definition. + pub id: KeyId, + /// The key relationship to the subject's DID Document. + pub relationship: DidKeyRelationship, + /// The details of the DID Key, including its creation block number on the + /// provider chain. + pub details: DidPublicKeyDetails, +} + +/// The details of a web3name after it has been successfully verified in a +/// Merkle proof. +#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] +pub struct RevealedWeb3Name { + /// The web3name. + pub web3_name: Web3Name, + /// The block number on the provider chain in which it was linked to the DID + /// subject. + pub claimed_at: BlockNumber, +} + +/// The details of an account after it has been successfully verified in a +/// Merkle proof. +#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] +pub struct RevealedAccountId(pub AccountId); diff --git a/crates/kilt-dip-primitives/src/test.rs b/crates/kilt-dip-primitives/src/test.rs deleted file mode 100644 index fedfa8f05f..0000000000 --- a/crates/kilt-dip-primitives/src/test.rs +++ /dev/null @@ -1,543 +0,0 @@ -use did::{ - did_details::{DidPublicKey, DidPublicKeyDetails}, - DidSignature, -}; -use frame_support::ensure; -use parity_scale_codec::{Decode, Encode}; -use sp_core::ConstU32; -use sp_runtime::{ - traits::{Hash, Header}, - BoundedVec, SaturatedConversion, -}; -use sp_trie::{verify_trie_proof, LayoutV1}; - -use crate::{ - common::{calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key}, - did::TimeBoundDidSignature, - merkle::{DidKeyRelationship, RevealedDidKey}, - state_proofs::{verify_storage_value_proof, MerkleProofError}, - traits::GetWithArg, - utils::OutputOf, - RevealedDidMerkleProofLeaf, -}; - -pub struct ProviderHeadProof { - pub(crate) relay_block_number: RelayBlockNumber, - pub(crate) proof: BoundedVec>, ConstU32>, -} - -pub struct DipCommitmentProof( - BoundedVec>, ConstU32>, -); - -pub struct DidMerkleProof< - ProviderDidKeyId, - ProviderAccountId, - ProviderBlockNumber, - ProviderWeb3Name, - ProviderLinkableAccountId, - const MAX_BLINDED_LEAVE_COUNT: u32, - const MAX_BLINDED_LEAVE_SIZE: u32, - const MAX_LEAVES_REVEALED: u32, -> { - pub blinded: BoundedVec>, ConstU32>, - pub revealed: BoundedVec< - RevealedDidMerkleProofLeaf< - ProviderDidKeyId, - ProviderAccountId, - ProviderBlockNumber, - ProviderWeb3Name, - ProviderLinkableAccountId, - >, - ConstU32, - >, -} - -pub enum Error { - ProviderHeadProof(MerkleProofError), - RelayStateRootNotFound, -} - -pub struct DipDidProof< - RelayBlockNumber, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - const MAX_LEAVE_COUNT: u32, - const MAX_LEAVE_SIZE: u32, - const MAX_DIP_LEAVES_REVEALED: u32, -> { - pub(crate) provider_head_proof: ProviderHeadProof, - pub(crate) dip_commitment_proof: DipCommitmentProof, - pub(crate) dip_proof: DidMerkleProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_LEAVE_COUNT, - MAX_LEAVE_SIZE, - MAX_DIP_LEAVES_REVEALED, - >, - pub(crate) signature: TimeBoundDidSignature, -} - -impl< - RelayBlockNumber, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - const MAX_LEAVE_COUNT: u32, - const MAX_LEAVE_SIZE: u32, - const MAX_DIP_LEAVES_REVEALED: u32, - > - DipDidProof< - RelayBlockNumber, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - MAX_LEAVE_COUNT, - MAX_LEAVE_SIZE, - MAX_DIP_LEAVES_REVEALED, - > -{ - fn verify_top_level_head_proof_for_provider_and_state_root( - self, - provider_para_id: u32, - relay_state_root: &OutputOf, - ) -> Result< - RelayVerifiedDipProof< - OutputOf, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - MAX_LEAVE_COUNT, - MAX_LEAVE_SIZE, - MAX_DIP_LEAVES_REVEALED, - >, - Error, - > - where - RelayHasher: Hash, - ProviderHeader: Decode + Header, - { - let provider_head_storage_key = calculate_parachain_head_storage_key(provider_para_id); - let provider_header = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( - &provider_head_storage_key, - *relay_state_root, - self.provider_head_proof.proof.into_iter().map(|i| i.into()), - ) - .map_err(Error::ProviderHeadProof)?; - Ok(RelayVerifiedDipProof { - state_root: *provider_header.state_root(), - dip_commitment_proof: self.dip_commitment_proof, - dip_proof: self.dip_proof, - signature: self.signature, - }) - } - - fn verify_top_level_head_proof_for_provider( - self, - provider_para_id: u32, - ) -> Result< - RelayVerifiedDipProof< - OutputOf, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - MAX_LEAVE_COUNT, - MAX_LEAVE_SIZE, - MAX_DIP_LEAVES_REVEALED, - >, - Error, - > - where - RelayHasher: Hash, - StateRootStore: GetWithArg>>, - ProviderHeader: Decode + Header, - { - let relay_state_root = - StateRootStore::get(&self.provider_head_proof.relay_block_number).ok_or(Error::RelayStateRootNotFound)?; - self.verify_top_level_head_proof_for_provider_and_state_root::( - provider_para_id, - &relay_state_root, - ) - } -} - -pub struct RelayVerifiedDipProof< - StateRoot, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - const MAX_LEAVE_COUNT: u32, - const MAX_LEAVE_SIZE: u32, - const MAX_DIP_LEAVES_REVEALED: u32, -> { - pub(crate) state_root: StateRoot, - pub(crate) dip_commitment_proof: DipCommitmentProof, - pub(crate) dip_proof: DidMerkleProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_LEAVE_COUNT, - MAX_LEAVE_SIZE, - MAX_DIP_LEAVES_REVEALED, - >, - pub(crate) signature: TimeBoundDidSignature, -} - -impl< - StateRoot, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - const MAX_LEAVE_COUNT: u32, - const MAX_LEAVE_SIZE: u32, - const MAX_DIP_LEAVES_REVEALED: u32, - > - RelayVerifiedDipProof< - StateRoot, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - MAX_LEAVE_COUNT, - MAX_LEAVE_SIZE, - MAX_DIP_LEAVES_REVEALED, - > -{ - fn verify_dip_commitment_proof_for_subject( - self, - subject: &ProviderRuntime::Identifier, - ) -> Result< - CommitmentVerifiedProof< - Commitment, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - MAX_LEAVE_COUNT, - MAX_LEAVE_SIZE, - MAX_DIP_LEAVES_REVEALED, - >, - Error, - > - where - MerkleHasher: Hash, - StateRoot: Into>, - ProviderRuntime: pallet_dip_provider::Config, - Commitment: Decode, - OutputOf: Into, - { - let dip_commitment_storage_key = - calculate_dip_identity_commitment_storage_key_for_runtime::(subject, 0); - let dip_commitment = verify_storage_value_proof::<_, MerkleHasher, Commitment>( - &dip_commitment_storage_key, - self.state_root.into(), - self.dip_commitment_proof.0.into_iter().map(|i| i.into()), - ) - .map_err(Error::ProviderHeadProof)?; - Ok(CommitmentVerifiedProof { - dip_commitment, - dip_proof: self.dip_proof, - signature: self.signature, - }) - } -} - -pub(crate) struct CommitmentVerifiedProof< - Commitment, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - const MAX_LEAVE_COUNT: u32, - const MAX_LEAVE_SIZE: u32, - const MAX_DIP_LEAVES_REVEALED: u32, -> { - pub(crate) dip_commitment: Commitment, - pub(crate) dip_proof: DidMerkleProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_LEAVE_COUNT, - MAX_LEAVE_SIZE, - MAX_DIP_LEAVES_REVEALED, - >, - pub(crate) signature: TimeBoundDidSignature, -} - -impl< - Commitment, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - const MAX_LEAVE_COUNT: u32, - const MAX_LEAVE_SIZE: u32, - const MAX_DIP_LEAVES_REVEALED: u32, - > - CommitmentVerifiedProof< - Commitment, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - MAX_LEAVE_COUNT, - MAX_LEAVE_SIZE, - MAX_DIP_LEAVES_REVEALED, - > where - KiltDidKeyId: Encode, - KiltAccountId: Encode, - KiltBlockNumber: Encode, - KiltWeb3Name: Encode, - KiltLinkableAccountId: Encode, -{ - fn verify_dip_proof( - self, - ) -> Result< - DipVerifiedProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - MAX_DIP_LEAVES_REVEALED, - >, - Error, - > - where - MerkleHasher: Hash, - { - let mut revealed_keys = self - .dip_proof - .revealed - .iter() - .take(MAX_DIP_LEAVES_REVEALED.saturated_into()); - - // If there are more keys than MAX_LEAVES_REVEALED, bail out. - ensure!( - revealed_keys.next().is_none(), - // TODO: Change - Error::RelayStateRootNotFound, - ); - - let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = revealed_keys - .by_ref() - .map(|revealed_leaf| (revealed_leaf.encoded_key(), Some(revealed_leaf.encoded_value()))) - .collect(); - - verify_trie_proof::, _, _, _>( - &self.dip_commitment, - self.dip_proof - .blinded - .into_iter() - .map(|l| l.into_inner()) - .collect::>() - .as_slice(), - &proof_leaves_key_value_pairs, - ) - // TODO: Change - .map_err(|_| Error::RelayStateRootNotFound)?; - - Ok(DipVerifiedProof { - revealed_leaves: self.dip_proof.revealed, - signature: self.signature, - }) - } -} - -pub(crate) struct DipVerifiedProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - const MAX_DIP_LEAVES_REVEALED: u32, -> { - pub(crate) revealed_leaves: BoundedVec< - RevealedDidMerkleProofLeaf, - ConstU32, - >, - pub(crate) signature: TimeBoundDidSignature, -} - -impl< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - const MAX_DIP_LEAVES_REVEALED: u32, - > - DipVerifiedProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - MAX_DIP_LEAVES_REVEALED, - > where - ConsumerBlockNumber: PartialOrd, -{ - fn verify_signature_time( - self, - block_number: &ConsumerBlockNumber, - ) -> Result< - DipSignatureTimeVerifiedProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_DIP_LEAVES_REVEALED, - >, - Error, - > { - ensure!( - self.signature.valid_until >= *block_number, - Error::RelayStateRootNotFound - ); - Ok(DipSignatureTimeVerifiedProof { - revealed_leaves: self.revealed_leaves, - signature: self.signature.signature, - }) - } -} - -pub(crate) struct DipSignatureTimeVerifiedProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - const MAX_DIP_LEAVES_REVEALED: u32, -> { - pub(crate) revealed_leaves: BoundedVec< - RevealedDidMerkleProofLeaf, - ConstU32, - >, - pub(crate) signature: DidSignature, -} - -impl< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - const MAX_DIP_LEAVES_REVEALED: u32, - > - DipSignatureTimeVerifiedProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_DIP_LEAVES_REVEALED, - > -{ - fn retrieve_signing_leaf_for_payload<'a>( - self, - payload: &[u8], - ) -> Result< - DipSignatureVerifiedProof< - 'a, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_DIP_LEAVES_REVEALED, - >, - Error, - > { - let revealed_verification_keys = self.revealed_leaves.iter().filter(|leaf| { - matches!( - leaf, - RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { - relationship: DidKeyRelationship::Verification(verification_relationship), - .. - }) - ) - }); - let signing_key = revealed_verification_keys - .find(|revealed_verification_key| { - let RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { - details: - DidPublicKeyDetails { - key: DidPublicKey::PublicVerificationKey(verification_key), - .. - }, - .. - }) = revealed_verification_key - else { - return false; - }; - verification_key.verify_signature(payload, &self.signature).is_ok() - // TODO: Change - }) - .ok_or(Error::RelayStateRootNotFound)?; - Ok(DipSignatureVerifiedProof { - revealed_leaves: self.revealed_leaves, - // TODO: Fix this compilation issue, and then we are golden! - signing_leaf: RevealedDidMerkleProofLeaf::DidKey(signing_key), - }) - } -} - -pub(crate) struct DipSignatureVerifiedProof< - 'a, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - const MAX_DIP_LEAVES_REVEALED: u32, -> { - pub(crate) revealed_leaves: BoundedVec< - RevealedDidMerkleProofLeaf, - ConstU32, - >, - pub(crate) signing_leaf: &'a RevealedDidKey, -} From 8c147c444e0bc7da4f0efdebc02ba0c96c44027f Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Mon, 15 Jan 2024 11:57:39 +0100 Subject: [PATCH 15/45] Compiling --- crates/kilt-dip-primitives/src/lib.rs | 14 +- .../src/{merkle_proof.rs => merkle.rs} | 346 ++++++++++++++++-- crates/kilt-dip-primitives/src/utils.rs | 75 +--- .../src/verifier/common.rs | 177 --------- .../kilt-dip-primitives/src/verifier/mod.rs | 5 +- 5 files changed, 344 insertions(+), 273 deletions(-) rename crates/kilt-dip-primitives/src/{merkle_proof.rs => merkle.rs} (68%) delete mode 100644 crates/kilt-dip-primitives/src/verifier/common.rs diff --git a/crates/kilt-dip-primitives/src/lib.rs b/crates/kilt-dip-primitives/src/lib.rs index 15a1c3d10b..a574e9acea 100644 --- a/crates/kilt-dip-primitives/src/lib.rs +++ b/crates/kilt-dip-primitives/src/lib.rs @@ -26,16 +26,16 @@ #![cfg_attr(not(feature = "std"), no_std)] -pub mod did; pub mod merkle; pub mod state_proofs; pub mod traits; pub mod utils; -pub mod verifier; +// pub mod verifier; -mod test; - -pub use merkle::RevealedDidMerkleProofLeaf; +pub use merkle::{ + DidKeyRelationship, DidMerkleProof, DipCommitmentProof, Error, ParachainDipDidProof, ProviderHeadProof, + RelayDipDidProof, RevealedAccountId, RevealedDidKey, RevealedDidMerkleProofLeaf, RevealedWeb3Name, + TimeBoundDidSignature, +}; pub use traits::RelayStateRootsViaRelayStorePallet; -pub use utils::BoundedBlindedValue; -pub use verifier::*; +// pub use verifier::*; diff --git a/crates/kilt-dip-primitives/src/merkle_proof.rs b/crates/kilt-dip-primitives/src/merkle.rs similarity index 68% rename from crates/kilt-dip-primitives/src/merkle_proof.rs rename to crates/kilt-dip-primitives/src/merkle.rs index 0a405db7b3..299173f87e 100644 --- a/crates/kilt-dip-primitives/src/merkle_proof.rs +++ b/crates/kilt-dip-primitives/src/merkle.rs @@ -17,27 +17,28 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org //! Module to deal with cross-chain Merkle proof as generated by the KILT chain. - use did::{ did_details::{DidPublicKey, DidPublicKeyDetails}, DidSignature, DidVerificationKeyRelationship, }; use frame_support::{ensure, RuntimeDebug}; -use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use parity_scale_codec::{Codec, Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; -use sp_core::ConstU32; +use sp_core::{ConstU32, U256}; use sp_runtime::{ - traits::{Hash, Header}, + generic::Header, + traits::{AtLeast32BitUnsigned, Hash, Header as HeaderT, MaybeDisplay, Member}, BoundedVec, SaturatedConversion, }; use sp_std::vec::Vec; use sp_trie::{verify_trie_proof, LayoutV1}; use crate::{ - common::{calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key}, state_proofs::{verify_storage_value_proof, MerkleProofError}, traits::GetWithArg, - utils::OutputOf, + utils::{ + calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key, OutputOf, + }, }; pub struct ProviderHeadProof { @@ -81,7 +82,154 @@ pub struct TimeBoundDidSignature { pub(crate) valid_until: BlockNumber, } -pub struct DipDidProof< +pub enum Error { + ProviderHeadProof(MerkleProofError), + RelayStateRootNotFound, +} + +pub struct RelayDipDidProof< + RelayBlockNumber: Copy + Into + TryFrom, + RelayBlockHasher: Hash, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, +> { + pub(crate) relay_header: Header, + pub(crate) provider_head_proof: + ProviderHeadProof, + pub(crate) dip_commitment_proof: + DipCommitmentProof, + pub(crate) dip_proof: DidMerkleProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + pub(crate) signature: TimeBoundDidSignature, +} + +impl< + RelayBlockNumber: Member + sp_std::hash::Hash + Copy + MaybeDisplay + AtLeast32BitUnsigned + Codec + Into + TryFrom, + RelayBlockHasher: Hash, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, + > + RelayDipDidProof< + RelayBlockNumber, + RelayBlockHasher, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + > +{ + #[allow(clippy::type_complexity)] + pub fn verify_relay_header_with_block_hash( + self, + block_hash: &OutputOf, + ) -> Result< + RelayHeaderVerifiedParachainDipDidProof< + RelayBlockHasher, + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + Error, + > { + if block_hash != &self.relay_header.hash() { + // TODO: Change + return Err(Error::RelayStateRootNotFound); + } + + Ok(RelayHeaderVerifiedParachainDipDidProof { + relay_state_root: self.relay_header.state_root, + provider_head_proof: self.provider_head_proof, + dip_commitment_proof: self.dip_commitment_proof, + dip_proof: self.dip_proof, + signature: self.signature, + }) + } + + #[allow(clippy::type_complexity)] + pub fn verify_relay_header( + self, + ) -> Result< + RelayHeaderVerifiedParachainDipDidProof< + RelayBlockHasher, + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + Error, + > + where + RelayHashStore: GetWithArg>>, + { + // TODO: Change error + let relay_block_hash = RelayHashStore::get(&self.relay_header.number).ok_or(Error::RelayStateRootNotFound)?; + + self.verify_relay_header_with_block_hash(&relay_block_hash) + } +} + +pub struct RelayHeaderVerifiedParachainDipDidProof< + RelayHasher: Hash, RelayBlockNumber, KiltDidKeyId, KiltAccountId, @@ -97,6 +245,7 @@ pub struct DipDidProof< const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, > { + pub(crate) relay_state_root: OutputOf, pub(crate) provider_head_proof: ProviderHeadProof, pub(crate) dip_commitment_proof: @@ -114,9 +263,110 @@ pub struct DipDidProof< pub(crate) signature: TimeBoundDidSignature, } -pub enum Error { - ProviderHeadProof(MerkleProofError), - RelayStateRootNotFound, +impl< + RelayHasher: Hash, + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, + > + RelayHeaderVerifiedParachainDipDidProof< + RelayHasher, + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + > +{ + #[allow(clippy::type_complexity)] + pub fn verify_provider_head_proof( + self, + provider_para_id: u32, + ) -> Result< + RelayVerifiedDipProof< + OutputOf, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + Error, + > + where + ProviderHeader: Decode + HeaderT, + { + let parachain_dip_proof = ParachainDipDidProof { + provider_head_proof: self.provider_head_proof, + dip_commitment_proof: self.dip_commitment_proof, + dip_proof: self.dip_proof, + signature: self.signature, + }; + + parachain_dip_proof.verify_provider_head_proof_with_state_root::( + provider_para_id, + &self.relay_state_root, + ) + } +} + +pub struct ParachainDipDidProof< + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, +> { + pub(crate) provider_head_proof: + ProviderHeadProof, + pub(crate) dip_commitment_proof: + DipCommitmentProof, + pub(crate) dip_proof: DidMerkleProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, + >, + pub(crate) signature: TimeBoundDidSignature, } impl< @@ -135,7 +385,7 @@ impl< const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > - DipDidProof< + ParachainDipDidProof< RelayBlockNumber, KiltDidKeyId, KiltAccountId, @@ -152,7 +402,8 @@ impl< MAX_DID_MERKLE_LEAVES_REVEALED, > { - pub fn verify_top_level_head_proof_for_provider_and_state_root( + #[allow(clippy::type_complexity)] + pub fn verify_provider_head_proof_with_state_root( self, provider_para_id: u32, relay_state_root: &OutputOf, @@ -175,7 +426,7 @@ impl< > where RelayHasher: Hash, - ProviderHeader: Decode + Header, + ProviderHeader: Decode + HeaderT, { let provider_head_storage_key = calculate_parachain_head_storage_key(provider_para_id); let provider_header = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( @@ -192,7 +443,8 @@ impl< }) } - pub fn verify_top_level_head_proof_for_provider( + #[allow(clippy::type_complexity)] + pub fn verify_provider_head_proof( self, provider_para_id: u32, ) -> Result< @@ -215,11 +467,11 @@ impl< where RelayHasher: Hash, StateRootStore: GetWithArg>>, - ProviderHeader: Decode + Header, + ProviderHeader: Decode + HeaderT, { let relay_state_root = StateRootStore::get(&self.provider_head_proof.relay_block_number).ok_or(Error::RelayStateRootNotFound)?; - self.verify_top_level_head_proof_for_provider_and_state_root::( + self.verify_provider_head_proof_with_state_root::( provider_para_id, &relay_state_root, ) @@ -285,6 +537,7 @@ impl< MAX_DID_MERKLE_LEAVES_REVEALED, > { + #[allow(clippy::type_complexity)] pub fn verify_dip_commitment_proof_for_subject( self, subject: &ProviderRuntime::Identifier, @@ -326,7 +579,7 @@ impl< } } -pub(crate) struct CommitmentVerifiedProof< +pub struct CommitmentVerifiedProof< Commitment, KiltDidKeyId, KiltAccountId, @@ -437,7 +690,7 @@ impl< } } -pub(crate) struct DipVerifiedProof< +pub struct DipVerifiedProof< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -498,7 +751,7 @@ impl< } } -pub(crate) struct DipSignatureTimeVerifiedProof< +pub struct DipSignatureTimeVerifiedProof< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -530,12 +783,11 @@ impl< MAX_DID_MERKLE_LEAVES_REVEALED, > { - pub fn retrieve_signing_leaf_for_payload<'a>( + pub fn retrieve_signing_leaf_for_payload( self, payload: &[u8], ) -> Result< DipSignatureVerifiedProof< - 'a, KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -549,13 +801,14 @@ impl< matches!( leaf, RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { - relationship: DidKeyRelationship::Verification(verification_relationship), + relationship: DidKeyRelationship::Verification(_), .. }) ) }); - let signing_key = revealed_verification_keys - .find(|revealed_verification_key| { + let (index, _) = revealed_verification_keys + .enumerate() + .find(|(_, revealed_verification_key)| { let RevealedDidMerkleProofLeaf::DidKey(RevealedDidKey { details: DidPublicKeyDetails { @@ -571,16 +824,15 @@ impl< // TODO: Change }) .ok_or(Error::RelayStateRootNotFound)?; + Ok(DipSignatureVerifiedProof { revealed_leaves: self.revealed_leaves, - // TODO: Fix this compilation issue, and then we are golden! - signing_leaf: RevealedDidMerkleProofLeaf::DidKey(signing_key), + signing_leaf_index: index, }) } } -pub(crate) struct DipSignatureVerifiedProof< - 'a, +pub struct DipSignatureVerifiedProof< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -588,11 +840,45 @@ pub(crate) struct DipSignatureVerifiedProof< KiltLinkableAccountId, const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, > { - pub revealed_leaves: BoundedVec< + revealed_leaves: BoundedVec< RevealedDidMerkleProofLeaf, ConstU32, >, - pub signing_leaf: &'a RevealedDidKey, + signing_leaf_index: usize, +} + +impl< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, + > + DipSignatureVerifiedProof< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_DID_MERKLE_LEAVES_REVEALED, + > +{ + pub fn get_signing_leaf( + &self, + ) -> &RevealedDidMerkleProofLeaf + { + &self.revealed_leaves[self.signing_leaf_index] + } + + pub fn to_inner( + self, + ) -> BoundedVec< + RevealedDidMerkleProofLeaf, + ConstU32, + > { + self.revealed_leaves + } } /// Relationship of a key to a DID Document. diff --git a/crates/kilt-dip-primitives/src/utils.rs b/crates/kilt-dip-primitives/src/utils.rs index 184ea12e8a..6becba1a64 100644 --- a/crates/kilt-dip-primitives/src/utils.rs +++ b/crates/kilt-dip-primitives/src/utils.rs @@ -16,67 +16,32 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -use parity_scale_codec::{Decode, Encode}; -use scale_info::TypeInfo; -use sp_core::RuntimeDebug; -use sp_std::vec::Vec; +use pallet_dip_provider::IdentityCommitmentVersion; +use parity_scale_codec::Encode; +use sp_core::storage::StorageKey; /// The output of a type implementing the [`sp_runtime::traits::Hash`] trait. pub type OutputOf = ::Output; -/// The vector of vectors that implements a statically-configured maximum length -/// without requiring const generics, used in benchmarking worst cases. -#[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, Clone)] -pub struct BoundedBlindedValue(Vec>); - -impl BoundedBlindedValue { - pub fn into_inner(self) -> Vec> { - self.0 - } -} - -impl From for BoundedBlindedValue -where - C: Iterator>, -{ - fn from(value: C) -> Self { - Self(value.into_iter().collect()) - } -} - -impl sp_std::ops::Deref for BoundedBlindedValue { - type Target = Vec>; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl IntoIterator for BoundedBlindedValue { - type IntoIter = > as IntoIterator>::IntoIter; - type Item = > as IntoIterator>::Item; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -#[cfg(feature = "runtime-benchmarks")] -impl kilt_support::traits::GetWorstCase for BoundedBlindedValue -where - T: Default + Clone, -{ - fn worst_case(_context: Context) -> Self { - Self(sp_std::vec![sp_std::vec![T::default(); 128]; 64]) - } +pub(crate) fn calculate_parachain_head_storage_key(para_id: u32) -> StorageKey { + StorageKey( + [ + frame_support::storage::storage_prefix(b"Paras", b"Heads").as_slice(), + sp_io::hashing::twox_64(para_id.encode().as_ref()).as_slice(), + para_id.encode().as_slice(), + ] + .concat(), + ) } -#[cfg(feature = "runtime-benchmarks")] -impl Default for BoundedBlindedValue +pub(crate) fn calculate_dip_identity_commitment_storage_key_for_runtime( + subject: &Runtime::Identifier, + version: IdentityCommitmentVersion, +) -> StorageKey where - T: Default + Clone, + Runtime: pallet_dip_provider::Config, { - fn default() -> Self { - Self(sp_std::vec![sp_std::vec![T::default(); 128]; 64]) - } + StorageKey(pallet_dip_provider::IdentityCommitments::::hashed_key_for( + subject, version, + )) } diff --git a/crates/kilt-dip-primitives/src/verifier/common.rs b/crates/kilt-dip-primitives/src/verifier/common.rs deleted file mode 100644 index 8afd41fa06..0000000000 --- a/crates/kilt-dip-primitives/src/verifier/common.rs +++ /dev/null @@ -1,177 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 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 pallet_dip_provider::IdentityCommitmentVersion; -use parity_scale_codec::Encode; -use sp_core::storage::StorageKey; - -pub mod latest { - pub use super::v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof}; -} - -pub mod v0 { - use did::did_details::DidPublicKey; - use parity_scale_codec::{Decode, Encode}; - use scale_info::TypeInfo; - use sp_core::RuntimeDebug; - use sp_runtime::traits::Hash; - use sp_std::vec::Vec; - - use crate::{ - did::{DidSignatureVerificationError, TimeBoundDidSignature}, - merkle::{ - DidKeyRelationship, DidMerkleProof, DidMerkleProofVerificationError, RevealedDidKey, - RevealedDidMerkleProofLeaf, - }, - utils::OutputOf, - BoundedBlindedValue, - }; - - #[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, Clone)] - pub struct ParachainRootStateProof { - /// The relaychain block height for which the proof has been generated. - pub(crate) relay_block_height: RelayBlockHeight, - /// The raw state proof. - pub(crate) proof: BoundedBlindedValue, - } - - #[cfg(feature = "runtime-benchmarks")] - impl kilt_support::traits::GetWorstCase - for ParachainRootStateProof - where - RelayBlockHeight: Default, - { - fn worst_case(context: Context) -> Self { - Self { - relay_block_height: RelayBlockHeight::default(), - proof: BoundedBlindedValue::worst_case(context), - } - } - } - - #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)] - pub struct DipMerkleProofAndDidSignature { - /// The DIP Merkle proof revealing some leaves about the DID subject's - /// identity. - pub(crate) leaves: DidMerkleProof, - /// The cross-chain DID signature. - pub(crate) signature: TimeBoundDidSignature, - } - - impl - DipMerkleProofAndDidSignature - where - KeyId: Encode, - AccountId: Encode, - BlockNumber: Encode, - Web3Name: Encode, - LinkedAccountId: Encode, - { - pub fn verify_merkle_proof_against_commitment( - self, - commitment: &OutputOf, - max_leaves_revealed: usize, - ) -> Result< - RevealedLeavesAndDidSignature, - DidMerkleProofVerificationError, - > - where - Hasher: Hash, - { - let revealed_leaves = self - .leaves - .verify_against_commitment::(commitment, max_leaves_revealed)?; - Ok(RevealedLeavesAndDidSignature { - signature: self.signature, - leaves: revealed_leaves.into_iter().collect(), - }) - } - } - - pub struct RevealedLeavesAndDidSignature { - pub(crate) leaves: Vec>, - pub(crate) signature: TimeBoundDidSignature, - } - - impl - RevealedLeavesAndDidSignature - where - LocalBlockNumber: PartialOrd + Clone, - { - pub fn extract_signing_key_for_payload( - &self, - payload: &[u8], - current_block_number: LocalBlockNumber, - ) -> Result<&RevealedDidKey, DidSignatureVerificationError> { - let signature = self - .signature - .clone() - .extract_signature_if_not_expired(current_block_number)?; - - let mut revealed_did_verification_keys = self.leaves.iter().filter_map(|leaf| { - // Skip if the leaf is not a DID key leaf. - let RevealedDidMerkleProofLeaf::DidKey(did_key) = leaf else { - return None; - }; - // Skip if the DID key is not a verification key. - let DidPublicKey::PublicVerificationKey(_) = did_key.details.key else { - return None; - }; - // Skip if the verification relationship is not for signatures (should never - // fail, but we check just to be sure). - let DidKeyRelationship::Verification(_) = did_key.relationship else { - return None; - }; - Some(did_key) - }); - - let signing_key_details = revealed_did_verification_keys - .find(|did_key| { - let DidPublicKey::PublicVerificationKey(ref mapped_key) = did_key.details.key else { - return false; - }; - mapped_key.verify_signature(payload, &signature).is_ok() - }) - .ok_or(DidSignatureVerificationError::SignerNotFound)?; - Ok(signing_key_details) - } - } -} - -pub(crate) fn calculate_parachain_head_storage_key(para_id: u32) -> StorageKey { - StorageKey( - [ - frame_support::storage::storage_prefix(b"Paras", b"Heads").as_slice(), - sp_io::hashing::twox_64(para_id.encode().as_ref()).as_slice(), - para_id.encode().as_slice(), - ] - .concat(), - ) -} - -pub(crate) fn calculate_dip_identity_commitment_storage_key_for_runtime( - subject: &Runtime::Identifier, - version: IdentityCommitmentVersion, -) -> StorageKey -where - Runtime: pallet_dip_provider::Config, -{ - StorageKey(pallet_dip_provider::IdentityCommitments::::hashed_key_for( - subject, version, - )) -} diff --git a/crates/kilt-dip-primitives/src/verifier/mod.rs b/crates/kilt-dip-primitives/src/verifier/mod.rs index 663d7c889e..5154391cf1 100644 --- a/crates/kilt-dip-primitives/src/verifier/mod.rs +++ b/crates/kilt-dip-primitives/src/verifier/mod.rs @@ -16,9 +16,6 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -/// Verification logic to integrate a child chain as a DIP provider. -// pub mod relaychain; -pub(crate) mod common; /// Verification logic to integrate a sibling chain as a DIP provider. pub mod parachain; /// Verification logic to integrate a child chain as a DIP provider. @@ -32,5 +29,5 @@ pub use relaychain::{ }; pub mod latest { - pub use super::{common::latest::*, parachain::latest::*, relaychain::latest::*}; + pub use super::{parachain::latest::*, relaychain::latest::*}; } From f62c0fca7230098886ff680a360fdb5d200898c7 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Mon, 15 Jan 2024 14:25:19 +0100 Subject: [PATCH 16/45] The whole thing compiling --- crates/kilt-dip-primitives/src/lib.rs | 10 +- crates/kilt-dip-primitives/src/merkle/mod.rs | 25 +++ .../src/{merkle.rs => merkle/v0.rs} | 80 +++---- .../kilt-dip-primitives/src/verifier/mod.rs | 5 - .../src/verifier/parachain.rs | 167 ++++----------- .../src/verifier/relaychain.rs | 201 +++++------------- 6 files changed, 162 insertions(+), 326 deletions(-) create mode 100644 crates/kilt-dip-primitives/src/merkle/mod.rs rename crates/kilt-dip-primitives/src/{merkle.rs => merkle/v0.rs} (93%) diff --git a/crates/kilt-dip-primitives/src/lib.rs b/crates/kilt-dip-primitives/src/lib.rs index a574e9acea..8b9028aa00 100644 --- a/crates/kilt-dip-primitives/src/lib.rs +++ b/crates/kilt-dip-primitives/src/lib.rs @@ -30,12 +30,8 @@ pub mod merkle; pub mod state_proofs; pub mod traits; pub mod utils; -// pub mod verifier; +pub mod verifier; -pub use merkle::{ - DidKeyRelationship, DidMerkleProof, DipCommitmentProof, Error, ParachainDipDidProof, ProviderHeadProof, - RelayDipDidProof, RevealedAccountId, RevealedDidKey, RevealedDidMerkleProofLeaf, RevealedWeb3Name, - TimeBoundDidSignature, -}; +pub use merkle::latest::*; pub use traits::RelayStateRootsViaRelayStorePallet; -// pub use verifier::*; +pub use verifier::*; diff --git a/crates/kilt-dip-primitives/src/merkle/mod.rs b/crates/kilt-dip-primitives/src/merkle/mod.rs new file mode 100644 index 0000000000..2a30d0bee4 --- /dev/null +++ b/crates/kilt-dip-primitives/src/merkle/mod.rs @@ -0,0 +1,25 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 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 + +//! Module to deal with cross-chain Merkle proof as generated by the KILT chain. + +pub mod v0; + +pub mod latest { + pub use super::v0::*; +} diff --git a/crates/kilt-dip-primitives/src/merkle.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs similarity index 93% rename from crates/kilt-dip-primitives/src/merkle.rs rename to crates/kilt-dip-primitives/src/merkle/v0.rs index 299173f87e..b0051ed767 100644 --- a/crates/kilt-dip-primitives/src/merkle.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -41,15 +41,18 @@ use crate::{ }, }; +#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct ProviderHeadProof { pub(crate) relay_block_number: RelayBlockNumber, pub(crate) proof: BoundedVec>, ConstU32>, } +#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct DipCommitmentProof( pub(crate) BoundedVec>, ConstU32>, ); +#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct DidMerkleProof< ProviderDidKeyId, ProviderAccountId, @@ -74,7 +77,7 @@ pub struct DidMerkleProof< } /// A DID signature anchored to a specific block height. -#[derive(Encode, Decode, RuntimeDebug, Clone, Eq, PartialEq, TypeInfo)] +#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct TimeBoundDidSignature { /// The signature. pub(crate) signature: DidSignature, @@ -83,10 +86,24 @@ pub struct TimeBoundDidSignature { } pub enum Error { - ProviderHeadProof(MerkleProofError), RelayStateRootNotFound, + ProviderHeadProof(MerkleProofError), +} + +impl From for u8 { + fn from(value: Error) -> Self { + match value { + Error::RelayStateRootNotFound => 1, + Error::ProviderHeadProof(error) => match error { + MerkleProofError::InvalidProof => 11, + MerkleProofError::RequiredLeafNotRevealed => 12, + MerkleProofError::ResultDecoding => 13, + }, + } + } } +#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct RelayDipDidProof< RelayBlockNumber: Copy + Into + TryFrom, RelayBlockHasher: Hash, @@ -95,7 +112,6 @@ pub struct RelayDipDidProof< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - ConsumerBlockNumber, const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32 = 10, const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32 = 128, const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 10, @@ -119,7 +135,7 @@ pub struct RelayDipDidProof< MAX_DID_MERKLE_PROOF_LEAVE_SIZE, MAX_DID_MERKLE_LEAVES_REVEALED, >, - pub(crate) signature: TimeBoundDidSignature, + pub(crate) signature: TimeBoundDidSignature, } impl< @@ -130,7 +146,6 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - ConsumerBlockNumber, const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, @@ -147,7 +162,6 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - ConsumerBlockNumber, MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, @@ -170,7 +184,6 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - ConsumerBlockNumber, MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, @@ -207,7 +220,6 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - ConsumerBlockNumber, MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, @@ -236,7 +248,6 @@ pub struct RelayHeaderVerifiedParachainDipDidProof< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - ConsumerBlockNumber, const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32 = 10, const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32 = 128, const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 10, @@ -260,7 +271,7 @@ pub struct RelayHeaderVerifiedParachainDipDidProof< MAX_DID_MERKLE_PROOF_LEAVE_SIZE, MAX_DID_MERKLE_LEAVES_REVEALED, >, - pub(crate) signature: TimeBoundDidSignature, + pub(crate) signature: TimeBoundDidSignature, } impl< @@ -271,7 +282,6 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - ConsumerBlockNumber, const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, @@ -288,7 +298,6 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - ConsumerBlockNumber, MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, @@ -310,7 +319,7 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - ConsumerBlockNumber, + RelayBlockNumber, MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, MAX_DID_MERKLE_PROOF_LEAVE_COUNT, @@ -336,6 +345,7 @@ impl< } } +#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct ParachainDipDidProof< RelayBlockNumber, KiltDidKeyId, @@ -787,7 +797,7 @@ impl< self, payload: &[u8], ) -> Result< - DipSignatureVerifiedProof< + DipSignatureVerifiedInfo< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -825,14 +835,15 @@ impl< }) .ok_or(Error::RelayStateRootNotFound)?; - Ok(DipSignatureVerifiedProof { + Ok(DipSignatureVerifiedInfo { revealed_leaves: self.revealed_leaves, - signing_leaf_index: index, + signing_leaf_index: index.saturated_into(), }) } } -pub struct DipSignatureVerifiedProof< +#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +pub struct DipSignatureVerifiedInfo< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -844,7 +855,7 @@ pub struct DipSignatureVerifiedProof< RevealedDidMerkleProofLeaf, ConstU32, >, - signing_leaf_index: usize, + signing_leaf_index: u32, } impl< @@ -855,7 +866,7 @@ impl< KiltLinkableAccountId, const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > - DipSignatureVerifiedProof< + DipSignatureVerifiedInfo< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -864,25 +875,18 @@ impl< MAX_DID_MERKLE_LEAVES_REVEALED, > { - pub fn get_signing_leaf( - &self, - ) -> &RevealedDidMerkleProofLeaf - { - &self.revealed_leaves[self.signing_leaf_index] - } - - pub fn to_inner( - self, - ) -> BoundedVec< - RevealedDidMerkleProofLeaf, - ConstU32, - > { - self.revealed_leaves + pub fn get_signing_leaf(&self) -> &RevealedDidKey { + let RevealedDidMerkleProofLeaf::DidKey(did_key) = + &self.revealed_leaves[usize::saturated_from(self.signing_leaf_index)] + else { + panic!("Leaf should never fail to be converted to a DID key.") + }; + did_key } } /// Relationship of a key to a DID Document. -#[derive(Clone, Copy, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, PartialOrd, Ord, MaxEncodedLen)] +#[derive(Clone, Copy, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub enum DidKeyRelationship { Encryption, Verification(DidVerificationKeyRelationship), @@ -908,7 +912,7 @@ impl TryFrom for DidVerificationKeyRelationship { /// All possible Merkle leaf types that can be revealed as part of a DIP /// identity Merkle proof. -#[derive(Clone, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub enum RevealedDidMerkleProofLeaf { DidKey(RevealedDidKey), Web3Name(RevealedWeb3Name), @@ -993,7 +997,7 @@ where /// The details of a DID key after it has been successfully verified in a Merkle /// proof. -#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] +#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, RuntimeDebug, TypeInfo)] pub struct RevealedDidKey { /// The key ID, according to the provider's definition. pub id: KeyId, @@ -1006,7 +1010,7 @@ pub struct RevealedDidKey { /// The details of a web3name after it has been successfully verified in a /// Merkle proof. -#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] +#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, RuntimeDebug, TypeInfo)] pub struct RevealedWeb3Name { /// The web3name. pub web3_name: Web3Name, @@ -1017,5 +1021,5 @@ pub struct RevealedWeb3Name { /// The details of an account after it has been successfully verified in a /// Merkle proof. -#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] +#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, RuntimeDebug, TypeInfo)] pub struct RevealedAccountId(pub AccountId); diff --git a/crates/kilt-dip-primitives/src/verifier/mod.rs b/crates/kilt-dip-primitives/src/verifier/mod.rs index 5154391cf1..f3cbe7dfe3 100644 --- a/crates/kilt-dip-primitives/src/verifier/mod.rs +++ b/crates/kilt-dip-primitives/src/verifier/mod.rs @@ -20,14 +20,9 @@ pub mod parachain; /// Verification logic to integrate a child chain as a DIP provider. pub mod relaychain; - pub use parachain::{ DipParachainStateProofVerifierError, KiltVersionedParachainVerifier, VersionedDipParachainStateProof, }; pub use relaychain::{ DipRelaychainStateProofVerifierError, KiltVersionedRelaychainVerifier, VersionedRelaychainStateProof, }; - -pub mod latest { - pub use super::{parachain::latest::*, relaychain::latest::*}; -} diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 7b595aa769..8685899a3f 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -24,17 +24,14 @@ use pallet_dip_provider::IdentityCommitmentOf; use pallet_web3_names::Web3NameOf; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_core::{ConstU32, RuntimeDebug}; -use sp_runtime::BoundedVec; +use sp_core::RuntimeDebug; use sp_std::marker::PhantomData; use crate::{ - did::DidSignatureVerificationError, - merkle::{DidMerkleProofVerificationError, RevealedDidKey, RevealedDidMerkleProofLeaf}, - state_proofs::MerkleProofError, + merkle::v0::RevealedDidKey, traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, - BoundedBlindedValue, + DipSignatureVerifiedInfo, Error, }; /// A KILT-specific DIP identity proof for a sibling consumer that supports @@ -52,7 +49,7 @@ pub enum VersionedDipParachainStateProof< ConsumerBlockNumber, > { V0( - v0::ParachainDipStateProof< + crate::merkle::v0::ParachainDipDidProof< RelayBlockNumber, KiltDidKeyId, KiltAccountId, @@ -66,11 +63,7 @@ pub enum VersionedDipParachainStateProof< pub enum DipParachainStateProofVerifierError { UnsupportedVersion, - RelaychainStateRootNotFound, - ParachainHeadMerkleProof(MerkleProofError), - IdentityCommitmentMerkleProof(MerkleProofError), - DipProof(DidMerkleProofVerificationError), - DidSignature(DidSignatureVerificationError), + ProofVerification(Error), DidOriginError(DidOriginError), Internal, } @@ -82,16 +75,8 @@ where fn from(value: DipParachainStateProofVerifierError) -> Self { match value { DipParachainStateProofVerifierError::UnsupportedVersion => 1, - DipParachainStateProofVerifierError::RelaychainStateRootNotFound => 2, - DipParachainStateProofVerifierError::ParachainHeadMerkleProof(error) => { - u8::MAX as u16 + u8::from(error) as u16 - } - DipParachainStateProofVerifierError::IdentityCommitmentMerkleProof(error) => { - u8::MAX as u16 * 2 + u8::from(error) as u16 - } - DipParachainStateProofVerifierError::DipProof(error) => u8::MAX as u16 * 3 + u8::from(error) as u16, - DipParachainStateProofVerifierError::DidSignature(error) => u8::MAX as u16 * 4 + u8::from(error) as u16, - DipParachainStateProofVerifierError::DidOriginError(error) => u8::MAX as u16 * 5 + error.into() as u16, + DipParachainStateProofVerifierError::ProofVerification(error) => u8::MAX as u16 + u8::from(error) as u16, + DipParachainStateProofVerifierError::DidOriginError(error) => u8::MAX as u16 * 2 + error.into() as u16, DipParachainStateProofVerifierError::Internal => u16::MAX, } } @@ -203,15 +188,12 @@ impl< LinkableAccountId, BlockNumberFor, >; - type VerificationResult = BoundedVec< - RevealedDidMerkleProofLeaf< - KeyIdOf, - KiltRuntime::AccountId, - BlockNumberFor, - Web3NameOf, - LinkableAccountId, - >, - ConstU32, + type VerificationResult = DipSignatureVerifiedInfo< + KeyIdOf, + KiltRuntime::AccountId, + BlockNumberFor, + Web3NameOf, + LinkableAccountId, >; fn verify_proof_for_call_against_details( @@ -241,52 +223,13 @@ impl< } } -pub mod latest { - pub use super::v0::ParachainDipStateProof; -} - pub mod v0 { use super::*; use frame_system::pallet_prelude::HeaderFor; - use sp_runtime::{ - traits::{Header, Zero}, - SaturatedConversion, - }; + use sp_runtime::traits::Zero; - use crate::{ - state_proofs::verify_storage_value_proof, - verifier::common::{ - calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key, - v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof}, - }, - }; - - /// The expected format of a cross-chain DIP identity proof when the - /// identity information is bridged from a provider that is a sibling - /// of the chain where the information is consumed (i.e., consumer - /// chain). - #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)] - pub struct ParachainDipStateProof< - RelayBlockNumber, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - > { - pub(crate) para_state_root: ParachainRootStateProof, - pub(crate) dip_identity_commitment: BoundedBlindedValue, - pub(crate) did: DipMerkleProofAndDidSignature< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - >, - } + use crate::merkle::v0::{DipSignatureVerifiedInfo, ParachainDipDidProof}; pub struct ParachainVerifier< RelaychainRuntime, @@ -341,7 +284,7 @@ pub mod v0 { DidCallVerifier::Error: Into, { type Error = DipParachainStateProofVerifierError; - type Proof = ParachainDipStateProof< + type Proof = ParachainDipDidProof< BlockNumberFor, KeyIdOf, KiltRuntime::AccountId, @@ -351,15 +294,12 @@ pub mod v0 { BlockNumberFor, >; - type VerificationResult = BoundedVec< - RevealedDidMerkleProofLeaf< - KeyIdOf, - KiltRuntime::AccountId, - BlockNumberFor, - Web3NameOf, - LinkableAccountId, - >, - ConstU32, + type VerificationResult = DipSignatureVerifiedInfo< + KeyIdOf, + KiltRuntime::AccountId, + BlockNumberFor, + Web3NameOf, + LinkableAccountId, >; fn verify_proof_for_call_against_details( @@ -370,65 +310,46 @@ pub mod v0 { proof: Self::Proof, ) -> Result { // 1. Verify parachain state is finalized by relay chain and fresh. - let provider_head_storage_key = calculate_parachain_head_storage_key(KILT_PARA_ID); - let relaychain_root_at_proof_block = - RelaychainStateRootStore::get(&proof.para_state_root.relay_block_height) - .ok_or(DipParachainStateProofVerifierError::RelaychainStateRootNotFound)?; - let provider_parachain_header = - verify_storage_value_proof::<_, RelaychainRuntime::Hashing, HeaderFor>( - &provider_head_storage_key, - relaychain_root_at_proof_block, - proof.para_state_root.proof, + let proof_without_relaychain = proof + .verify_provider_head_proof::>( + KILT_PARA_ID, ) - .map_err(DipParachainStateProofVerifierError::ParachainHeadMerkleProof)?; + .map_err(DipParachainStateProofVerifierError::ProofVerification)?; // 2. Verify commitment is included in provider parachain state. - let dip_commitment_storage_key = - calculate_dip_identity_commitment_storage_key_for_runtime::(subject, 0); - let dip_commitment = - verify_storage_value_proof::<_, KiltRuntime::Hashing, IdentityCommitmentOf>( - &dip_commitment_storage_key, - *provider_parachain_header.state_root(), - proof.dip_identity_commitment, - ) - .map_err(DipParachainStateProofVerifierError::IdentityCommitmentMerkleProof)?; - - let did_proof = proof.did; + let proof_without_parachain = proof_without_relaychain + .verify_dip_commitment_proof_for_subject::(subject) + .map_err(DipParachainStateProofVerifierError::ProofVerification)?; // 3. Verify DIP Merkle proof. - let verified_proof = did_proof - .verify_merkle_proof_against_commitment::( - &dip_commitment.into(), - MAX_LEAVES_REVEALED.saturated_into(), - ) - .map_err(DipParachainStateProofVerifierError::DipProof)?; + let proof_without_dip_merkle = proof_without_parachain + .verify_dip_proof::() + .map_err(DipParachainStateProofVerifierError::ProofVerification)?; - // 4. Verify call is signed by one of the DID keys revealed at step 3. + // 4. Verify call is signed by one of the DID keys revealed in the proof let current_block_number = frame_system::Pallet::::block_number(); let consumer_genesis_hash = frame_system::Pallet::::block_hash(BlockNumberFor::::zero()); let signed_extra = SignedExtra::get(); let encoded_payload = (call, &identity_details, submitter, consumer_genesis_hash, signed_extra).encode(); - let signing_key = verified_proof - .extract_signing_key_for_payload(&encoded_payload[..], current_block_number) - .map_err(DipParachainStateProofVerifierError::DidSignature)?; + let revealed_did_info = proof_without_dip_merkle + .verify_signature_time(¤t_block_number) + .and_then(|p| p.retrieve_signing_leaf_for_payload(&encoded_payload[..])) + .map_err(DipParachainStateProofVerifierError::ProofVerification)?; + + // 5. Verify the signing key fulfills the requirements + let signing_key = revealed_did_info.get_signing_leaf(); + DidCallVerifier::check_call_origin_info(call, signing_key) + .map_err(DipParachainStateProofVerifierError::DidOriginError)?; - // Increment the local details + // 6. Increment the local details if let Some(details) = identity_details { details.increment(); } else { *identity_details = Some(Default::default()); }; - DidCallVerifier::check_call_origin_info(call, signing_key) - .map_err(DipParachainStateProofVerifierError::DidOriginError)?; - - let result = verified_proof.leaves.try_into().map_err(|_| { - log::error!("Failed to convert vector of revealed leaves into BoundedVec. This should never happen since the bound checks were checked earlier on."); - DipParachainStateProofVerifierError::Internal - })?; - - Ok(result) + Ok(revealed_did_info) } } } diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index 9b5ac13302..d136f48f59 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -24,17 +24,15 @@ use pallet_dip_provider::IdentityCommitmentOf; use pallet_web3_names::Web3NameOf; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_core::{ConstU32, RuntimeDebug, U256}; -use sp_runtime::{traits::Hash, BoundedVec}; +use sp_core::{RuntimeDebug, U256}; +use sp_runtime::traits::Hash; use sp_std::marker::PhantomData; use crate::{ - did::DidSignatureVerificationError, - merkle::{DidMerkleProofVerificationError, RevealedDidKey, RevealedDidMerkleProofLeaf}, - state_proofs::MerkleProofError, + merkle::v0::RevealedDidKey, traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, - BoundedBlindedValue, + DipSignatureVerifiedInfo, Error, }; /// A KILT-specific DIP identity proof for a parent consumer that supports @@ -52,7 +50,7 @@ pub enum VersionedRelaychainStateProof< KiltLinkableAccountId, > { V0( - v0::RelaychainDipStateProof< + crate::merkle::v0::RelayDipDidProof< ConsumerBlockNumber, ConsumerBlockHasher, KiltDidKeyId, @@ -66,12 +64,7 @@ pub enum VersionedRelaychainStateProof< pub enum DipRelaychainStateProofVerifierError { UnsupportedVersion, - BlockHashNotFound, - InvalidBlockHeader, - ParachainHeadMerkleProof(MerkleProofError), - IdentityCommitmentMerkleProof(MerkleProofError), - DipProof(DidMerkleProofVerificationError), - DidSignature(DidSignatureVerificationError), + ProofVerification(Error), DidOriginError(DidOriginError), Internal, } @@ -83,17 +76,8 @@ where fn from(value: DipRelaychainStateProofVerifierError) -> Self { match value { DipRelaychainStateProofVerifierError::UnsupportedVersion => 1, - DipRelaychainStateProofVerifierError::BlockHashNotFound => 2, - DipRelaychainStateProofVerifierError::InvalidBlockHeader => 3, - DipRelaychainStateProofVerifierError::ParachainHeadMerkleProof(error) => { - u8::MAX as u16 + u8::from(error) as u16 - } - DipRelaychainStateProofVerifierError::IdentityCommitmentMerkleProof(error) => { - u8::MAX as u16 * 2 + u8::from(error) as u16 - } - DipRelaychainStateProofVerifierError::DipProof(error) => u8::MAX as u16 * 3 + u8::from(error) as u16, - DipRelaychainStateProofVerifierError::DidSignature(error) => u8::MAX as u16 * 4 + u8::from(error) as u16, - DipRelaychainStateProofVerifierError::DidOriginError(error) => u8::MAX as u16 * 5 + error.into() as u16, + DipRelaychainStateProofVerifierError::ProofVerification(error) => u8::MAX as u16 + u8::from(error) as u16, + DipRelaychainStateProofVerifierError::DidOriginError(error) => u8::MAX as u16 * 2 + error.into() as u16, DipRelaychainStateProofVerifierError::Internal => u16::MAX, } } @@ -194,15 +178,12 @@ impl< Web3NameOf, LinkableAccountId, >; - type VerificationResult = BoundedVec< - RevealedDidMerkleProofLeaf< - KeyIdOf, - KiltRuntime::AccountId, - BlockNumberFor, - Web3NameOf, - LinkableAccountId, - >, - ConstU32, + type VerificationResult = DipSignatureVerifiedInfo< + KeyIdOf, + KiltRuntime::AccountId, + BlockNumberFor, + Web3NameOf, + LinkableAccountId, >; fn verify_proof_for_call_against_details( @@ -231,60 +212,13 @@ impl< } } -pub mod latest { - pub use super::v0::RelaychainDipStateProof; -} - pub mod v0 { use super::*; use frame_system::pallet_prelude::HeaderFor; - use sp_runtime::{ - generic::Header, - traits::{Hash, Header as HeaderT, Zero}, - SaturatedConversion, - }; + use sp_runtime::traits::Zero; - use crate::{ - latest::ParachainDipStateProof, - state_proofs::verify_storage_value_proof, - verifier::common::{ - calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key, - v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof}, - }, - }; - - /// The expected format of a cross-chain DIP identity proof when the - /// identity information is bridged from a provider that is a child of - /// the chain where the information is consumed (i.e., consumer - /// chain). - #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] - pub struct RelaychainDipStateProof< - ConsumerBlockNumber: Copy + Into + TryFrom, - ConsumerBlockHasher: Hash, - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - > { - /// The state proof for the given parachain head. - para_state_root: ParachainRootStateProof, - /// The relaychain header for the relaychain block specified in the - /// `para_state_root`. - relay_header: Header, - /// The raw state proof for the DIP commitment of the given subject. - dip_identity_commitment: BoundedBlindedValue, - /// The cross-chain DID signature. - did: DipMerkleProofAndDidSignature< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - >, - } + use crate::RelayDipDidProof; /// Generic proof verifier for KILT-specific DIP identity proofs coming from /// a child provider running one of the available KILT runtimes. @@ -399,7 +333,7 @@ pub mod v0 { DidCallVerifier::Error: Into, { type Error = DipRelaychainStateProofVerifierError; - type Proof = RelaychainDipStateProof< + type Proof = RelayDipDidProof< BlockNumberFor, ConsumerRuntime::Hashing, KeyIdOf, @@ -408,15 +342,12 @@ pub mod v0 { Web3NameOf, LinkableAccountId, >; - type VerificationResult = BoundedVec< - RevealedDidMerkleProofLeaf< - KeyIdOf, - KiltRuntime::AccountId, - BlockNumberFor, - Web3NameOf, - LinkableAccountId, - >, - ConstU32, + type VerificationResult = DipSignatureVerifiedInfo< + KeyIdOf, + KiltRuntime::AccountId, + BlockNumberFor, + Web3NameOf, + LinkableAccountId, >; fn verify_proof_for_call_against_details( @@ -426,86 +357,50 @@ pub mod v0 { identity_details: &mut Option, proof: Self::Proof, ) -> Result { - // 1. Retrieve block hash from provider at the proof height - let block_hash_at_height = ConsumerBlockHashStore::get(&proof.para_state_root.relay_block_height) - .ok_or(DipRelaychainStateProofVerifierError::BlockHashNotFound)?; - - // 1.1 Verify that the provided header hashes to the same block hash retrieved - if block_hash_at_height != proof.relay_header.hash() { - return Err(DipRelaychainStateProofVerifierError::InvalidBlockHeader); - } - // 1.2 If so, extract the state root from the header - let state_root_at_height = proof.relay_header.state_root; - - // Remove the header from the proof and verify the rest using the parachain - // verifier logic. - let parachain_proof = ParachainDipStateProof { - para_state_root: proof.para_state_root, - dip_identity_commitment: proof.dip_identity_commitment, - did: proof.did, - }; - - // TODO: Can we re-use the verification logic for the parachain verification? - // Current issue is implementing the expected `RelaychainStateRootStore` trait - // to return the state root we calculated above. + // 1. Verify provided relaychain header. + let proof_without_header = proof + .verify_relay_header::() + .map_err(DipRelaychainStateProofVerifierError::ProofVerification)?; // 2. Verify parachain state is finalized by relay chain and fresh. - let provider_head_storage_key = calculate_parachain_head_storage_key(KILT_PARA_ID); - let provider_parachain_header = - verify_storage_value_proof::<_, ConsumerRuntime::Hashing, HeaderFor>( - &provider_head_storage_key, - state_root_at_height, - parachain_proof.para_state_root.proof, - ) - .map_err(DipRelaychainStateProofVerifierError::ParachainHeadMerkleProof)?; + let proof_without_relaychain = proof_without_header + .verify_provider_head_proof::>(KILT_PARA_ID) + .map_err(DipRelaychainStateProofVerifierError::ProofVerification)?; // 3. Verify commitment is included in provider parachain state. - let dip_commitment_storage_key = - calculate_dip_identity_commitment_storage_key_for_runtime::(subject, 0); - let dip_commitment = - verify_storage_value_proof::<_, KiltRuntime::Hashing, IdentityCommitmentOf>( - &dip_commitment_storage_key, - *provider_parachain_header.state_root(), - parachain_proof.dip_identity_commitment, - ) - .map_err(DipRelaychainStateProofVerifierError::IdentityCommitmentMerkleProof)?; - - let did_proof = parachain_proof.did; + let proof_without_parachain = proof_without_relaychain + .verify_dip_commitment_proof_for_subject::(subject) + .map_err(DipRelaychainStateProofVerifierError::ProofVerification)?; // 4. Verify DIP Merkle proof. - let verified_proof = did_proof - .verify_merkle_proof_against_commitment::( - &dip_commitment.into(), - MAX_LEAVES_REVEALED.saturated_into(), - ) - .map_err(DipRelaychainStateProofVerifierError::DipProof)?; + let proof_without_dip_merkle = proof_without_parachain + .verify_dip_proof::() + .map_err(DipRelaychainStateProofVerifierError::ProofVerification)?; - // 5. Verify call is signed by one of the DID keys revealed at step 3. + // 5. Verify call is signed by one of the DID keys revealed in the proof let current_block_number = frame_system::Pallet::::block_number(); let consumer_genesis_hash = frame_system::Pallet::::block_hash(BlockNumberFor::::zero()); let signed_extra = SignedExtra::get(); let encoded_payload = (call, &identity_details, submitter, consumer_genesis_hash, signed_extra).encode(); - let signing_key = verified_proof - .extract_signing_key_for_payload(&encoded_payload[..], current_block_number) - .map_err(DipRelaychainStateProofVerifierError::DidSignature)?; + let revealed_did_info = proof_without_dip_merkle + .verify_signature_time(¤t_block_number) + .and_then(|p| p.retrieve_signing_leaf_for_payload(&encoded_payload[..])) + .map_err(DipRelaychainStateProofVerifierError::ProofVerification)?; + + // 6. Verify the signing key fulfills the requirements + let signing_key = revealed_did_info.get_signing_leaf(); + DidCallVerifier::check_call_origin_info(call, signing_key) + .map_err(DipRelaychainStateProofVerifierError::DidOriginError)?; - // Increment the local details + // 7. Increment the local details if let Some(details) = identity_details { details.increment(); } else { *identity_details = Some(Default::default()); }; - DidCallVerifier::check_call_origin_info(call, signing_key) - .map_err(DipRelaychainStateProofVerifierError::DidOriginError)?; - - let result = verified_proof.leaves.try_into().map_err(|_| { - log::error!("Failed to convert vector of revealed leaves into BoundedVec. This should never happen since the bound checks were checked earlier on."); - DipRelaychainStateProofVerifierError::Internal - })?; - - Ok(result) + Ok(revealed_did_info) } } } From 582e2c15ad40d2cacb174abf6cc76b8592dc7c9f Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Mon, 15 Jan 2024 14:52:22 +0100 Subject: [PATCH 17/45] Compiling again --- crates/kilt-dip-primitives/src/merkle/v0.rs | 94 +++++++++++-------- .../src/verifier/parachain.rs | 4 +- .../src/verifier/relaychain.rs | 4 +- 3 files changed, 62 insertions(+), 40 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index b0051ed767..c4026a4b4b 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -42,13 +42,13 @@ use crate::{ }; #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] -pub struct ProviderHeadProof { +pub struct ProviderHeadStateProof { pub(crate) relay_block_number: RelayBlockNumber, pub(crate) proof: BoundedVec>, ConstU32>, } #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] -pub struct DipCommitmentProof( +pub struct DipCommitmentStateProof( pub(crate) BoundedVec>, ConstU32>, ); @@ -86,19 +86,39 @@ pub struct TimeBoundDidSignature { } pub enum Error { + InvalidRelayHeader, + RelayBlockNotFound, RelayStateRootNotFound, - ProviderHeadProof(MerkleProofError), + TooManyDidLeaves, + InvalidDidMerkleProof, + InvalidSignatureTime, + InvalidDidKeyRevealed, + ParaHeadMerkleProof(MerkleProofError), + DipCommitmentMerkleProof(MerkleProofError), + Internal, } impl From for u8 { fn from(value: Error) -> Self { match value { - Error::RelayStateRootNotFound => 1, - Error::ProviderHeadProof(error) => match error { + Error::InvalidRelayHeader => 1, + Error::RelayBlockNotFound => 2, + Error::RelayStateRootNotFound => 3, + Error::TooManyDidLeaves => 4, + Error::InvalidDidMerkleProof => 5, + Error::InvalidSignatureTime => 6, + Error::InvalidDidKeyRevealed => 7, + Error::ParaHeadMerkleProof(error) => match error { MerkleProofError::InvalidProof => 11, MerkleProofError::RequiredLeafNotRevealed => 12, MerkleProofError::ResultDecoding => 13, }, + Error::DipCommitmentMerkleProof(error) => match error { + MerkleProofError::InvalidProof => 21, + MerkleProofError::RequiredLeafNotRevealed => 22, + MerkleProofError::ResultDecoding => 23, + }, + Error::Internal => u8::MAX, } } } @@ -121,10 +141,13 @@ pub struct RelayDipDidProof< const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, > { pub(crate) relay_header: Header, - pub(crate) provider_head_proof: - ProviderHeadProof, + pub(crate) provider_head_proof: ProviderHeadStateProof< + RelayBlockNumber, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + >, pub(crate) dip_commitment_proof: - DipCommitmentProof, + DipCommitmentStateProof, pub(crate) dip_proof: DidMerkleProof< KiltDidKeyId, KiltAccountId, @@ -195,8 +218,7 @@ impl< Error, > { if block_hash != &self.relay_header.hash() { - // TODO: Change - return Err(Error::RelayStateRootNotFound); + return Err(Error::InvalidRelayHeader); } Ok(RelayHeaderVerifiedParachainDipDidProof { @@ -233,9 +255,7 @@ impl< where RelayHashStore: GetWithArg>>, { - // TODO: Change error - let relay_block_hash = RelayHashStore::get(&self.relay_header.number).ok_or(Error::RelayStateRootNotFound)?; - + let relay_block_hash = RelayHashStore::get(&self.relay_header.number).ok_or(Error::RelayBlockNotFound)?; self.verify_relay_header_with_block_hash(&relay_block_hash) } } @@ -257,10 +277,13 @@ pub struct RelayHeaderVerifiedParachainDipDidProof< const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, > { pub(crate) relay_state_root: OutputOf, - pub(crate) provider_head_proof: - ProviderHeadProof, + pub(crate) provider_head_proof: ProviderHeadStateProof< + RelayBlockNumber, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + >, pub(crate) dip_commitment_proof: - DipCommitmentProof, + DipCommitmentStateProof, pub(crate) dip_proof: DidMerkleProof< KiltDidKeyId, KiltAccountId, @@ -362,10 +385,13 @@ pub struct ParachainDipDidProof< const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, > { - pub(crate) provider_head_proof: - ProviderHeadProof, + pub(crate) provider_head_proof: ProviderHeadStateProof< + RelayBlockNumber, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + >, pub(crate) dip_commitment_proof: - DipCommitmentProof, + DipCommitmentStateProof, pub(crate) dip_proof: DidMerkleProof< KiltDidKeyId, KiltAccountId, @@ -444,7 +470,7 @@ impl< *relay_state_root, self.provider_head_proof.proof.into_iter().map(|i| i.into()), ) - .map_err(Error::ProviderHeadProof)?; + .map_err(Error::ParaHeadMerkleProof)?; Ok(RelayVerifiedDipProof { state_root: *provider_header.state_root(), dip_commitment_proof: self.dip_commitment_proof, @@ -504,7 +530,7 @@ pub struct RelayVerifiedDipProof< > { pub(crate) state_root: StateRoot, pub(crate) dip_commitment_proof: - DipCommitmentProof, + DipCommitmentStateProof, pub(crate) dip_proof: DidMerkleProof< KiltDidKeyId, KiltAccountId, @@ -580,7 +606,7 @@ impl< self.state_root.into(), self.dip_commitment_proof.0.into_iter().map(|i| i.into()), ) - .map_err(Error::ProviderHeadProof)?; + .map_err(Error::DipCommitmentMerkleProof)?; Ok(CommitmentVerifiedProof { dip_commitment, dip_proof: self.dip_proof, @@ -669,11 +695,7 @@ impl< .take(MAX_DID_MERKLE_LEAVES_REVEALED.saturated_into()); // If there are more keys than MAX_LEAVES_REVEALED, bail out. - ensure!( - revealed_keys.next().is_none(), - // TODO: Change - Error::RelayStateRootNotFound, - ); + ensure!(revealed_keys.next().is_none(), Error::TooManyDidLeaves,); let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = revealed_keys .by_ref() @@ -690,8 +712,7 @@ impl< .as_slice(), &proof_leaves_key_value_pairs, ) - // TODO: Change - .map_err(|_| Error::RelayStateRootNotFound)?; + .map_err(|_| Error::InvalidDidMerkleProof)?; Ok(DipVerifiedProof { revealed_leaves: self.dip_proof.revealed, @@ -750,10 +771,7 @@ impl< >, Error, > { - ensure!( - self.signature.valid_until >= *block_number, - Error::RelayStateRootNotFound - ); + ensure!(self.signature.valid_until >= *block_number, Error::InvalidSignatureTime); Ok(DipSignatureTimeVerifiedProof { revealed_leaves: self.revealed_leaves, signature: self.signature.signature, @@ -831,9 +849,8 @@ impl< return false; }; verification_key.verify_signature(payload, &self.signature).is_ok() - // TODO: Change }) - .ok_or(Error::RelayStateRootNotFound)?; + .ok_or(Error::InvalidDidKeyRevealed)?; Ok(DipSignatureVerifiedInfo { revealed_leaves: self.revealed_leaves, @@ -875,13 +892,14 @@ impl< MAX_DID_MERKLE_LEAVES_REVEALED, > { - pub fn get_signing_leaf(&self) -> &RevealedDidKey { + pub fn get_signing_leaf(&self) -> Result<&RevealedDidKey, Error> { let RevealedDidMerkleProofLeaf::DidKey(did_key) = &self.revealed_leaves[usize::saturated_from(self.signing_leaf_index)] else { - panic!("Leaf should never fail to be converted to a DID key.") + log::error!("Should never fail to convert the signing leaf to a DID Key leaf."); + return Err(Error::Internal); }; - did_key + Ok(did_key) } } diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 8685899a3f..5a7c409a52 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -338,7 +338,9 @@ pub mod v0 { .map_err(DipParachainStateProofVerifierError::ProofVerification)?; // 5. Verify the signing key fulfills the requirements - let signing_key = revealed_did_info.get_signing_leaf(); + let signing_key = revealed_did_info + .get_signing_leaf() + .map_err(DipParachainStateProofVerifierError::ProofVerification)?; DidCallVerifier::check_call_origin_info(call, signing_key) .map_err(DipParachainStateProofVerifierError::DidOriginError)?; diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index d136f48f59..480ac9a6a9 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -389,7 +389,9 @@ pub mod v0 { .map_err(DipRelaychainStateProofVerifierError::ProofVerification)?; // 6. Verify the signing key fulfills the requirements - let signing_key = revealed_did_info.get_signing_leaf(); + let signing_key = revealed_did_info + .get_signing_leaf() + .map_err(DipRelaychainStateProofVerifierError::ProofVerification)?; DidCallVerifier::check_call_origin_info(call, signing_key) .map_err(DipRelaychainStateProofVerifierError::DidOriginError)?; From 9b79d46b505f5cee87511779f56170d0d8d776c6 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Mon, 15 Jan 2024 15:55:00 +0100 Subject: [PATCH 18/45] Removing bounds from proofs --- crates/kilt-dip-primitives/src/merkle/v0.rs | 161 ++++++++---------- .../src/verifier/parachain.rs | 54 +++++- .../src/verifier/relaychain.rs | 6 +- dip-template/runtimes/dip-consumer/src/dip.rs | 3 +- .../dip-consumer/src/origin_adapter.rs | 2 +- runtimes/common/src/dip/did.rs | 2 +- runtimes/common/src/dip/merkle.rs | 38 ++++- 7 files changed, 157 insertions(+), 109 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index c4026a4b4b..e97794da40 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -42,15 +42,13 @@ use crate::{ }; #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] -pub struct ProviderHeadStateProof { +pub struct ProviderHeadStateProof { pub(crate) relay_block_number: RelayBlockNumber, - pub(crate) proof: BoundedVec>, ConstU32>, + pub(crate) proof: Vec>, } #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] -pub struct DipCommitmentStateProof( - pub(crate) BoundedVec>, ConstU32>, -); +pub struct DipCommitmentStateProof(pub(crate) Vec>); #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct DidMerkleProof< @@ -59,12 +57,9 @@ pub struct DidMerkleProof< ProviderBlockNumber, ProviderWeb3Name, ProviderLinkableAccountId, - const MAX_BLINDED_LEAVE_COUNT: u32, - const MAX_BLINDED_LEAVE_SIZE: u32, - const MAX_LEAVES_REVEALED: u32, > { - pub(crate) blinded: BoundedVec>, ConstU32>, - pub(crate) revealed: BoundedVec< + pub(crate) blinded: Vec>, + pub(crate) revealed: Vec< RevealedDidMerkleProofLeaf< ProviderDidKeyId, ProviderAccountId, @@ -72,7 +67,6 @@ pub struct DidMerkleProof< ProviderWeb3Name, ProviderLinkableAccountId, >, - ConstU32, >, } @@ -132,32 +126,12 @@ pub struct RelayDipDidProof< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32 = 10, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32 = 128, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 10, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32 = 128, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 10, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, > { pub(crate) relay_header: Header, - pub(crate) provider_head_proof: ProviderHeadStateProof< - RelayBlockNumber, - MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, - MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, - >, - pub(crate) dip_commitment_proof: - DipCommitmentStateProof, - pub(crate) dip_proof: DidMerkleProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, - >, + pub(crate) provider_head_proof: ProviderHeadStateProof, + pub(crate) dip_commitment_proof: DipCommitmentStateProof, + pub(crate) dip_proof: + DidMerkleProof, pub(crate) signature: TimeBoundDidSignature, } @@ -199,7 +173,7 @@ impl< self, block_hash: &OutputOf, ) -> Result< - RelayHeaderVerifiedParachainDipDidProof< + DipDidProofWithVerifiedRelayStateRoot< RelayBlockHasher, RelayBlockNumber, KiltDidKeyId, @@ -221,7 +195,7 @@ impl< return Err(Error::InvalidRelayHeader); } - Ok(RelayHeaderVerifiedParachainDipDidProof { + Ok(DipDidProofWithVerifiedRelayStateRoot { relay_state_root: self.relay_header.state_root, provider_head_proof: self.provider_head_proof, dip_commitment_proof: self.dip_commitment_proof, @@ -234,7 +208,7 @@ impl< pub fn verify_relay_header( self, ) -> Result< - RelayHeaderVerifiedParachainDipDidProof< + DipDidProofWithVerifiedRelayStateRoot< RelayBlockHasher, RelayBlockNumber, KiltDidKeyId, @@ -260,7 +234,7 @@ impl< } } -pub struct RelayHeaderVerifiedParachainDipDidProof< +pub struct DipDidProofWithVerifiedRelayStateRoot< RelayHasher: Hash, RelayBlockNumber, KiltDidKeyId, @@ -268,13 +242,13 @@ pub struct RelayHeaderVerifiedParachainDipDidProof< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32 = 10, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32 = 128, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 10, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32 = 128, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 10, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { pub(crate) relay_state_root: OutputOf, pub(crate) provider_head_proof: ProviderHeadStateProof< @@ -313,7 +287,7 @@ impl< const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > - RelayHeaderVerifiedParachainDipDidProof< + DipDidProofWithVerifiedRelayStateRoot< RelayHasher, RelayBlockNumber, KiltDidKeyId, @@ -335,7 +309,7 @@ impl< self, provider_para_id: u32, ) -> Result< - RelayVerifiedDipProof< + DipDidProofWithoutRelayProof< OutputOf, KiltDidKeyId, KiltAccountId, @@ -377,13 +351,13 @@ pub struct ParachainDipDidProof< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32 = 10, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32 = 128, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 10, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32 = 128, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 10, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { pub(crate) provider_head_proof: ProviderHeadStateProof< RelayBlockNumber, @@ -444,7 +418,7 @@ impl< provider_para_id: u32, relay_state_root: &OutputOf, ) -> Result< - RelayVerifiedDipProof< + DipDidProofWithoutRelayProof< OutputOf, KiltDidKeyId, KiltAccountId, @@ -471,7 +445,7 @@ impl< self.provider_head_proof.proof.into_iter().map(|i| i.into()), ) .map_err(Error::ParaHeadMerkleProof)?; - Ok(RelayVerifiedDipProof { + Ok(DipDidProofWithoutRelayProof { state_root: *provider_header.state_root(), dip_commitment_proof: self.dip_commitment_proof, dip_proof: self.dip_proof, @@ -484,7 +458,7 @@ impl< self, provider_para_id: u32, ) -> Result< - RelayVerifiedDipProof< + DipDidProofWithoutRelayProof< OutputOf, KiltDidKeyId, KiltAccountId, @@ -514,7 +488,7 @@ impl< } } -pub struct RelayVerifiedDipProof< +pub struct DipDidProofWithoutRelayProof< StateRoot, KiltDidKeyId, KiltAccountId, @@ -522,11 +496,11 @@ pub struct RelayVerifiedDipProof< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 10, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32 = 128, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 10, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { pub(crate) state_root: StateRoot, pub(crate) dip_commitment_proof: @@ -558,7 +532,7 @@ impl< const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > - RelayVerifiedDipProof< + DipDidProofWithoutRelayProof< StateRoot, KiltDidKeyId, KiltAccountId, @@ -578,7 +552,7 @@ impl< self, subject: &ProviderRuntime::Identifier, ) -> Result< - CommitmentVerifiedProof< + DipDidProofWithVerifiedCommitment< Commitment, KiltDidKeyId, KiltAccountId, @@ -607,7 +581,7 @@ impl< self.dip_commitment_proof.0.into_iter().map(|i| i.into()), ) .map_err(Error::DipCommitmentMerkleProof)?; - Ok(CommitmentVerifiedProof { + Ok(DipDidProofWithVerifiedCommitment { dip_commitment, dip_proof: self.dip_proof, signature: self.signature, @@ -615,7 +589,7 @@ impl< } } -pub struct CommitmentVerifiedProof< +pub struct DipDidProofWithVerifiedCommitment< Commitment, KiltDidKeyId, KiltAccountId, @@ -623,9 +597,9 @@ pub struct CommitmentVerifiedProof< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 10, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { pub(crate) dip_commitment: Commitment, pub(crate) dip_proof: DidMerkleProof< @@ -653,7 +627,7 @@ impl< const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > - CommitmentVerifiedProof< + DipDidProofWithVerifiedCommitment< Commitment, KiltDidKeyId, KiltAccountId, @@ -674,7 +648,7 @@ impl< pub fn verify_dip_proof( self, ) -> Result< - DipVerifiedProof< + DipDetailsAndUnverifiedDidSignatureTime< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -714,21 +688,21 @@ impl< ) .map_err(|_| Error::InvalidDidMerkleProof)?; - Ok(DipVerifiedProof { + Ok(DipDetailsAndUnverifiedDidSignatureTime { revealed_leaves: self.dip_proof.revealed, signature: self.signature, }) } } -pub struct DipVerifiedProof< +pub struct DipDetailsAndUnverifiedDidSignatureTime< KiltDidKeyId, KiltAccountId, KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { pub(crate) revealed_leaves: BoundedVec< RevealedDidMerkleProofLeaf, @@ -746,7 +720,7 @@ impl< ConsumerBlockNumber, const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > - DipVerifiedProof< + DipDetailsAndUnverifiedDidSignatureTime< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -761,7 +735,7 @@ impl< self, block_number: &ConsumerBlockNumber, ) -> Result< - DipSignatureTimeVerifiedProof< + DipDetailsAndUnverifiedDidSignaturePayload< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -772,20 +746,20 @@ impl< Error, > { ensure!(self.signature.valid_until >= *block_number, Error::InvalidSignatureTime); - Ok(DipSignatureTimeVerifiedProof { + Ok(DipDetailsAndUnverifiedDidSignaturePayload { revealed_leaves: self.revealed_leaves, signature: self.signature.signature, }) } } -pub struct DipSignatureTimeVerifiedProof< +pub struct DipDetailsAndUnverifiedDidSignaturePayload< KiltDidKeyId, KiltAccountId, KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { pub(crate) revealed_leaves: BoundedVec< RevealedDidMerkleProofLeaf, @@ -802,7 +776,7 @@ impl< KiltLinkableAccountId, const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > - DipSignatureTimeVerifiedProof< + DipDetailsAndUnverifiedDidSignaturePayload< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -815,7 +789,7 @@ impl< self, payload: &[u8], ) -> Result< - DipSignatureVerifiedInfo< + DipVerifiedInfo< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -852,7 +826,7 @@ impl< }) .ok_or(Error::InvalidDidKeyRevealed)?; - Ok(DipSignatureVerifiedInfo { + Ok(DipVerifiedInfo { revealed_leaves: self.revealed_leaves, signing_leaf_index: index.saturated_into(), }) @@ -860,13 +834,13 @@ impl< } #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] -pub struct DipSignatureVerifiedInfo< +pub struct DipVerifiedInfo< KiltDidKeyId, KiltAccountId, KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { revealed_leaves: BoundedVec< RevealedDidMerkleProofLeaf, @@ -883,7 +857,7 @@ impl< KiltLinkableAccountId, const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > - DipSignatureVerifiedInfo< + DipVerifiedInfo< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -892,6 +866,19 @@ impl< MAX_DID_MERKLE_LEAVES_REVEALED, > { + pub fn iter_leaves( + &self, + ) -> impl Iterator< + Item = &RevealedDidMerkleProofLeaf< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + >, + > { + self.revealed_leaves.iter() + } pub fn get_signing_leaf(&self) -> Result<&RevealedDidKey, Error> { let RevealedDidMerkleProofLeaf::DidKey(did_key) = &self.revealed_leaves[usize::saturated_from(self.signing_leaf_index)] diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 5a7c409a52..241db8bd47 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -31,7 +31,7 @@ use crate::{ merkle::v0::RevealedDidKey, traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, - DipSignatureVerifiedInfo, Error, + DipVerifiedInfo, Error, }; /// A KILT-specific DIP identity proof for a sibling consumer that supports @@ -47,6 +47,13 @@ pub enum VersionedDipParachainStateProof< KiltBlockNumber, KiltLinkableAccountId, ConsumerBlockNumber, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { V0( crate::merkle::v0::ParachainDipDidProof< @@ -57,6 +64,13 @@ pub enum VersionedDipParachainStateProof< KiltBlockNumber, KiltLinkableAccountId, ConsumerBlockNumber, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, >, ), } @@ -133,7 +147,13 @@ pub struct KiltVersionedParachainVerifier< KiltRuntime, DidCallVerifier, SignedExtra = (), - const MAX_LEAVES_REVEALED: u32 = 50, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, >( PhantomData<( RelaychainRuntime, @@ -152,7 +172,13 @@ impl< KiltRuntime, DidCallVerifier, SignedExtra, - const MAX_LEAVES_REVEALED: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > IdentityProofVerifier for KiltVersionedParachainVerifier< RelaychainRuntime, @@ -161,7 +187,13 @@ impl< KiltRuntime, DidCallVerifier, SignedExtra, - MAX_LEAVES_REVEALED, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, > where ConsumerRuntime: pallet_dip_consumer::Config, ConsumerRuntime::LocalIdentityInfo: Incrementable + Default, @@ -187,13 +219,21 @@ impl< Web3NameOf, LinkableAccountId, BlockNumberFor, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, >; - type VerificationResult = DipSignatureVerifiedInfo< + type VerificationResult = DipVerifiedInfo< KeyIdOf, KiltRuntime::AccountId, BlockNumberFor, Web3NameOf, LinkableAccountId, + MAX_DID_MERKLE_LEAVES_REVEALED, >; fn verify_proof_for_call_against_details( @@ -229,7 +269,7 @@ pub mod v0 { use frame_system::pallet_prelude::HeaderFor; use sp_runtime::traits::Zero; - use crate::merkle::v0::{DipSignatureVerifiedInfo, ParachainDipDidProof}; + use crate::merkle::v0::{DipVerifiedInfo, ParachainDipDidProof}; pub struct ParachainVerifier< RelaychainRuntime, @@ -294,7 +334,7 @@ pub mod v0 { BlockNumberFor, >; - type VerificationResult = DipSignatureVerifiedInfo< + type VerificationResult = DipVerifiedInfo< KeyIdOf, KiltRuntime::AccountId, BlockNumberFor, diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index 480ac9a6a9..3a6e7d734a 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -32,7 +32,7 @@ use crate::{ merkle::v0::RevealedDidKey, traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, - DipSignatureVerifiedInfo, Error, + DipVerifiedInfo, Error, }; /// A KILT-specific DIP identity proof for a parent consumer that supports @@ -178,7 +178,7 @@ impl< Web3NameOf, LinkableAccountId, >; - type VerificationResult = DipSignatureVerifiedInfo< + type VerificationResult = DipVerifiedInfo< KeyIdOf, KiltRuntime::AccountId, BlockNumberFor, @@ -342,7 +342,7 @@ pub mod v0 { Web3NameOf, LinkableAccountId, >; - type VerificationResult = DipSignatureVerifiedInfo< + type VerificationResult = DipVerifiedInfo< KeyIdOf, KiltRuntime::AccountId, BlockNumberFor, diff --git a/dip-template/runtimes/dip-consumer/src/dip.rs b/dip-template/runtimes/dip-consumer/src/dip.rs index ea1835f2b4..7390c2af43 100644 --- a/dip-template/runtimes/dip-consumer/src/dip.rs +++ b/dip-template/runtimes/dip-consumer/src/dip.rs @@ -21,8 +21,7 @@ use dip_provider_runtime_template::{AccountId as ProviderAccountId, Runtime as P use frame_support::traits::Contains; use frame_system::{pallet_prelude::BlockNumberFor, EnsureSigned}; use kilt_dip_primitives::{ - merkle::RevealedDidKey, traits::DipCallOriginFilter, KiltVersionedParachainVerifier, - RelayStateRootsViaRelayStorePallet, + traits::DipCallOriginFilter, KiltVersionedParachainVerifier, RelayStateRootsViaRelayStorePallet, RevealedDidKey, }; use pallet_dip_consumer::traits::IdentityProofVerifier; use rococo_runtime::Runtime as RelaychainRuntime; diff --git a/dip-template/runtimes/dip-consumer/src/origin_adapter.rs b/dip-template/runtimes/dip-consumer/src/origin_adapter.rs index ad3e9153ac..88cef193ba 100644 --- a/dip-template/runtimes/dip-consumer/src/origin_adapter.rs +++ b/dip-template/runtimes/dip-consumer/src/origin_adapter.rs @@ -57,7 +57,7 @@ impl GetUsername for DipOriginAdapter { fn username(&self) -> Result { self.0 .details - .iter() + .iter_leaves() .find_map(|revealed_leaf| { if let RevealedDidMerkleProofLeaf::Web3Name(revealed_web3name_leaf) = revealed_leaf { Some(revealed_web3name_leaf.web3_name.clone()) diff --git a/runtimes/common/src/dip/did.rs b/runtimes/common/src/dip/did.rs index 688aeba2a4..c5a3df806f 100644 --- a/runtimes/common/src/dip/did.rs +++ b/runtimes/common/src/dip/did.rs @@ -19,7 +19,7 @@ use did::did_details::DidDetails; use frame_support::ensure; use frame_system::pallet_prelude::BlockNumberFor; -use kilt_dip_primitives::merkle::RevealedWeb3Name; +use kilt_dip_primitives::RevealedWeb3Name; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_provider::traits::IdentityProvider; use parity_scale_codec::{Decode, Encode}; diff --git a/runtimes/common/src/dip/merkle.rs b/runtimes/common/src/dip/merkle.rs index 5c1f2c5bcd..56edcb4527 100644 --- a/runtimes/common/src/dip/merkle.rs +++ b/runtimes/common/src/dip/merkle.rs @@ -18,7 +18,7 @@ use did::{DidVerificationKeyRelationship, KeyIdOf}; use frame_support::RuntimeDebug; use frame_system::pallet_prelude::BlockNumberFor; -use kilt_dip_primitives::merkle::DidMerkleProof; +use kilt_dip_primitives::RevealedDidMerkleProofLeaf; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_provider::{ traits::{IdentityCommitmentGenerator, IdentityProvider}, @@ -29,14 +29,31 @@ use scale_info::TypeInfo; use sp_std::{borrow::ToOwned, marker::PhantomData, vec::Vec}; use sp_trie::{generate_trie_proof, LayoutV1, MemoryDB, TrieDBMutBuilder, TrieHash, TrieMut}; -use kilt_dip_primitives::merkle::{DidKeyRelationship, RevealedDidMerkleProofLeaf}; - use crate::dip::did::LinkedDidInfoOf; -pub type BlindedValue = Vec; +#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] +pub struct UnboundDidMerkleProof< + ProviderDidKeyId, + ProviderAccountId, + ProviderBlockNumber, + ProviderWeb3Name, + ProviderLinkableAccountId, +> { + pub(crate) blinded: Vec>, + pub(crate) revealed: Vec< + RevealedDidMerkleProofLeaf< + ProviderDidKeyId, + ProviderAccountId, + ProviderBlockNumber, + ProviderWeb3Name, + ProviderLinkableAccountId, + >, + >, +} + /// Type of the Merkle proof revealing parts of the DIP identity of a given DID /// subject. -pub type DidMerkleProofOf = DidMerkleProof< +pub type DidMerkleProofOf = UnboundDidMerkleProof< KeyIdOf, ::AccountId, BlockNumberFor, @@ -60,6 +77,7 @@ pub enum DidMerkleProofError { KeyNotFound, LinkedAccountNotFound, Web3NameNotFound, + TooManyLeaves, Internal, } @@ -70,13 +88,16 @@ impl From for u16 { DidMerkleProofError::KeyNotFound => 2, DidMerkleProofError::LinkedAccountNotFound => 3, DidMerkleProofError::Web3NameNotFound => 4, + DidMerkleProofError::TooManyLeaves => 5, DidMerkleProofError::Internal => u16::MAX, } } } pub mod v0 { - use kilt_dip_primitives::merkle::{RevealedAccountId, RevealedDidKey, RevealedWeb3Name}; + use kilt_dip_primitives::{ + DidKeyRelationship, RevealedAccountId, RevealedDidKey, RevealedDidMerkleProofLeaf, RevealedWeb3Name, + }; use super::*; @@ -323,11 +344,12 @@ pub mod v0 { ); DidMerkleProofError::Internal })?; + Ok(CompleteMerkleProof { root, proof: DidMerkleProofOf:: { - blinded: proof.into_iter().into(), - revealed: leaves.into_iter().collect(), + blinded: proof, + revealed: leaves, }, }) } From d6647a09f671b8a29dcd5085a8b76a335930bffe Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Mon, 15 Jan 2024 16:04:55 +0100 Subject: [PATCH 19/45] wip --- crates/kilt-dip-primitives/src/merkle/v0.rs | 279 ++---------------- .../src/verifier/parachain.rs | 49 ++- 2 files changed, 52 insertions(+), 276 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index e97794da40..b76d256459 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -24,11 +24,11 @@ use did::{ use frame_support::{ensure, RuntimeDebug}; use parity_scale_codec::{Codec, Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; -use sp_core::{ConstU32, U256}; +use sp_core::U256; use sp_runtime::{ generic::Header, traits::{AtLeast32BitUnsigned, Hash, Header as HeaderT, MaybeDisplay, Member}, - BoundedVec, SaturatedConversion, + SaturatedConversion, }; use sp_std::vec::Vec; use sp_trie::{verify_trie_proof, LayoutV1}; @@ -83,7 +83,6 @@ pub enum Error { InvalidRelayHeader, RelayBlockNotFound, RelayStateRootNotFound, - TooManyDidLeaves, InvalidDidMerkleProof, InvalidSignatureTime, InvalidDidKeyRevealed, @@ -98,10 +97,9 @@ impl From for u8 { Error::InvalidRelayHeader => 1, Error::RelayBlockNotFound => 2, Error::RelayStateRootNotFound => 3, - Error::TooManyDidLeaves => 4, - Error::InvalidDidMerkleProof => 5, - Error::InvalidSignatureTime => 6, - Error::InvalidDidKeyRevealed => 7, + Error::InvalidDidMerkleProof => 4, + Error::InvalidSignatureTime => 5, + Error::InvalidDidKeyRevealed => 6, Error::ParaHeadMerkleProof(error) => match error { MerkleProofError::InvalidProof => 11, MerkleProofError::RequiredLeafNotRevealed => 12, @@ -143,13 +141,6 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > RelayDipDidProof< RelayBlockNumber, @@ -159,16 +150,8 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, - MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, - MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, - MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, > { - #[allow(clippy::type_complexity)] pub fn verify_relay_header_with_block_hash( self, block_hash: &OutputOf, @@ -181,13 +164,6 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, - MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, - MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, - MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, >, Error, > { @@ -204,7 +180,6 @@ impl< }) } - #[allow(clippy::type_complexity)] pub fn verify_relay_header( self, ) -> Result< @@ -216,13 +191,6 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, - MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, - MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, - MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, >, Error, > @@ -242,32 +210,12 @@ pub struct DipDidProofWithVerifiedRelayStateRoot< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { pub(crate) relay_state_root: OutputOf, - pub(crate) provider_head_proof: ProviderHeadStateProof< - RelayBlockNumber, - MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, - MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, - >, - pub(crate) dip_commitment_proof: - DipCommitmentStateProof, - pub(crate) dip_proof: DidMerkleProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, - >, + pub(crate) provider_head_proof: ProviderHeadStateProof, + pub(crate) dip_commitment_proof: DipCommitmentStateProof, + pub(crate) dip_proof: + DidMerkleProof, pub(crate) signature: TimeBoundDidSignature, } @@ -279,13 +227,6 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > DipDidProofWithVerifiedRelayStateRoot< RelayHasher, @@ -295,16 +236,8 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, - MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, - MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, - MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, > { - #[allow(clippy::type_complexity)] pub fn verify_provider_head_proof( self, provider_para_id: u32, @@ -317,11 +250,6 @@ impl< KiltWeb3Name, KiltLinkableAccountId, RelayBlockNumber, - MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, - MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, >, Error, > @@ -351,31 +279,11 @@ pub struct ParachainDipDidProof< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { - pub(crate) provider_head_proof: ProviderHeadStateProof< - RelayBlockNumber, - MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, - MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, - >, - pub(crate) dip_commitment_proof: - DipCommitmentStateProof, - pub(crate) dip_proof: DidMerkleProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, - >, + pub(crate) provider_head_proof: ProviderHeadStateProof, + pub(crate) dip_commitment_proof: DipCommitmentStateProof, + pub(crate) dip_proof: + DidMerkleProof, pub(crate) signature: TimeBoundDidSignature, } @@ -387,13 +295,6 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > ParachainDipDidProof< RelayBlockNumber, @@ -403,16 +304,8 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, - MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, - MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, - MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, > { - #[allow(clippy::type_complexity)] pub fn verify_provider_head_proof_with_state_root( self, provider_para_id: u32, @@ -426,11 +319,6 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, - MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, >, Error, > @@ -453,7 +341,6 @@ impl< }) } - #[allow(clippy::type_complexity)] pub fn verify_provider_head_proof( self, provider_para_id: u32, @@ -466,11 +353,6 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, - MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, >, Error, > @@ -496,25 +378,11 @@ pub struct DipDidProofWithoutRelayProof< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { pub(crate) state_root: StateRoot, - pub(crate) dip_commitment_proof: - DipCommitmentStateProof, - pub(crate) dip_proof: DidMerkleProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, - >, + pub(crate) dip_commitment_proof: DipCommitmentStateProof, + pub(crate) dip_proof: + DidMerkleProof, pub(crate) signature: TimeBoundDidSignature, } @@ -526,11 +394,6 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > DipDidProofWithoutRelayProof< StateRoot, @@ -540,14 +403,8 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, - MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, > { - #[allow(clippy::type_complexity)] pub fn verify_dip_commitment_proof_for_subject( self, subject: &ProviderRuntime::Identifier, @@ -560,9 +417,6 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, >, Error, > @@ -597,21 +451,10 @@ pub struct DipDidProofWithVerifiedCommitment< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { pub(crate) dip_commitment: Commitment, - pub(crate) dip_proof: DidMerkleProof< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, - >, + pub(crate) dip_proof: + DidMerkleProof, pub(crate) signature: TimeBoundDidSignature, } @@ -623,9 +466,6 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > DipDidProofWithVerifiedCommitment< Commitment, @@ -635,9 +475,6 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, > where KiltDidKeyId: Encode, KiltAccountId: Encode, @@ -655,18 +492,13 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - MAX_DID_MERKLE_LEAVES_REVEALED, >, Error, > where MerkleHasher: Hash, { - let mut revealed_keys = self - .dip_proof - .revealed - .iter() - .take(MAX_DID_MERKLE_LEAVES_REVEALED.saturated_into()); + let mut revealed_keys = self.dip_proof.revealed.iter(); // If there are more keys than MAX_LEAVES_REVEALED, bail out. ensure!(revealed_keys.next().is_none(), Error::TooManyDidLeaves,); @@ -702,24 +534,14 @@ pub struct DipDetailsAndUnverifiedDidSignatureTime< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { - pub(crate) revealed_leaves: BoundedVec< + pub(crate) revealed_leaves: Vec< RevealedDidMerkleProofLeaf, - ConstU32, >, pub(crate) signature: TimeBoundDidSignature, } -impl< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - ConsumerBlockNumber, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, - > +impl DipDetailsAndUnverifiedDidSignatureTime< KiltDidKeyId, KiltAccountId, @@ -727,7 +549,6 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - MAX_DID_MERKLE_LEAVES_REVEALED, > where ConsumerBlockNumber: PartialOrd, { @@ -741,7 +562,6 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - MAX_DID_MERKLE_LEAVES_REVEALED, >, Error, > { @@ -759,46 +579,27 @@ pub struct DipDetailsAndUnverifiedDidSignaturePayload< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { - pub(crate) revealed_leaves: BoundedVec< + pub(crate) revealed_leaves: Vec< RevealedDidMerkleProofLeaf, - ConstU32, >, pub(crate) signature: DidSignature, } -impl< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, - > +impl DipDetailsAndUnverifiedDidSignaturePayload< KiltDidKeyId, KiltAccountId, KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - MAX_DID_MERKLE_LEAVES_REVEALED, > { pub fn retrieve_signing_leaf_for_payload( self, payload: &[u8], - ) -> Result< - DipVerifiedInfo< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_DID_MERKLE_LEAVES_REVEALED, - >, - Error, - > { + ) -> Result, Error> + { let revealed_verification_keys = self.revealed_leaves.iter().filter(|leaf| { matches!( leaf, @@ -834,37 +635,15 @@ impl< } #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] -pub struct DipVerifiedInfo< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, -> { - revealed_leaves: BoundedVec< +pub struct DipVerifiedInfo { + revealed_leaves: Vec< RevealedDidMerkleProofLeaf, - ConstU32, >, signing_leaf_index: u32, } -impl< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, - > - DipVerifiedInfo< - KiltDidKeyId, - KiltAccountId, - KiltBlockNumber, - KiltWeb3Name, - KiltLinkableAccountId, - MAX_DID_MERKLE_LEAVES_REVEALED, - > +impl + DipVerifiedInfo { pub fn iter_leaves( &self, diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 241db8bd47..f08c0125ed 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -47,13 +47,6 @@ pub enum VersionedDipParachainStateProof< KiltBlockNumber, KiltLinkableAccountId, ConsumerBlockNumber, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, - const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > { V0( crate::merkle::v0::ParachainDipDidProof< @@ -64,13 +57,6 @@ pub enum VersionedDipParachainStateProof< KiltBlockNumber, KiltLinkableAccountId, ConsumerBlockNumber, - MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, - MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, - MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, - MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, >, ), } @@ -219,13 +205,6 @@ impl< Web3NameOf, LinkableAccountId, BlockNumberFor, - MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, - MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, - MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, - MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_PROOF_LEAVE_COUNT, - MAX_DID_MERKLE_PROOF_LEAVE_SIZE, - MAX_DID_MERKLE_LEAVES_REVEALED, >; type VerificationResult = DipVerifiedInfo< KeyIdOf, @@ -233,7 +212,6 @@ impl< BlockNumberFor, Web3NameOf, LinkableAccountId, - MAX_DID_MERKLE_LEAVES_REVEALED, >; fn verify_proof_for_call_against_details( @@ -251,7 +229,6 @@ impl< KiltRuntime, DidCallVerifier, SignedExtra, - MAX_LEAVES_REVEALED, > as IdentityProofVerifier>::verify_proof_for_call_against_details( call, subject, @@ -278,7 +255,13 @@ pub mod v0 { KiltRuntime, DidCallVerifier, SignedExtra, - const MAX_LEAVES_REVEALED: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, >( PhantomData<( RelaychainRuntime, @@ -297,7 +280,13 @@ pub mod v0 { KiltRuntime, DidCallVerifier, SignedExtra, - const MAX_LEAVES_REVEALED: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > IdentityProofVerifier for ParachainVerifier< RelaychainRuntime, @@ -306,7 +295,13 @@ pub mod v0 { KiltRuntime, DidCallVerifier, SignedExtra, - MAX_LEAVES_REVEALED, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, > where ConsumerRuntime: pallet_dip_consumer::Config, ConsumerRuntime::LocalIdentityInfo: Incrementable + Default, @@ -350,6 +345,8 @@ pub mod v0 { proof: Self::Proof, ) -> Result { // 1. Verify parachain state is finalized by relay chain and fresh. + // TODO: Enforce limits passed by the const generics for each step. + proof.provider_head_proof.proof let proof_without_relaychain = proof .verify_provider_head_proof::>( KILT_PARA_ID, From a03f576006622a9f93bbdf6364114307a02e0826 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 16 Jan 2024 10:08:30 +0100 Subject: [PATCH 20/45] Project compiling --- crates/kilt-dip-primitives/src/merkle/v0.rs | 46 ++- .../src/verifier/parachain.rs | 8 +- runtimes/common/src/dip/merkle.rs | 300 +++++++++--------- 3 files changed, 188 insertions(+), 166 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index b76d256459..25b3ac0ee4 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -70,6 +70,25 @@ pub struct DidMerkleProof< >, } +impl + DidMerkleProof +{ + pub fn new( + blinded: Vec>, + revealed: Vec< + RevealedDidMerkleProofLeaf< + ProviderDidKeyId, + ProviderAccountId, + ProviderBlockNumber, + ProviderWeb3Name, + ProviderLinkableAccountId, + >, + >, + ) -> Self { + Self { blinded, revealed } + } +} + /// A DID signature anchored to a specific block height. #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct TimeBoundDidSignature { @@ -152,6 +171,7 @@ impl< KiltLinkableAccountId, > { + #[allow(clippy::type_complexity)] pub fn verify_relay_header_with_block_hash( self, block_hash: &OutputOf, @@ -180,6 +200,7 @@ impl< }) } + #[allow(clippy::type_complexity)] pub fn verify_relay_header( self, ) -> Result< @@ -238,6 +259,7 @@ impl< KiltLinkableAccountId, > { + #[allow(clippy::type_complexity)] pub fn verify_provider_head_proof( self, provider_para_id: u32, @@ -306,6 +328,7 @@ impl< ConsumerBlockNumber, > { + #[allow(clippy::type_complexity)] pub fn verify_provider_head_proof_with_state_root( self, provider_para_id: u32, @@ -330,7 +353,7 @@ impl< let provider_header = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( &provider_head_storage_key, *relay_state_root, - self.provider_head_proof.proof.into_iter().map(|i| i.into()), + self.provider_head_proof.proof, ) .map_err(Error::ParaHeadMerkleProof)?; Ok(DipDidProofWithoutRelayProof { @@ -341,6 +364,7 @@ impl< }) } + #[allow(clippy::type_complexity)] pub fn verify_provider_head_proof( self, provider_para_id: u32, @@ -405,6 +429,7 @@ impl< ConsumerBlockNumber, > { + #[allow(clippy::type_complexity)] pub fn verify_dip_commitment_proof_for_subject( self, subject: &ProviderRuntime::Identifier, @@ -432,7 +457,7 @@ impl< let dip_commitment = verify_storage_value_proof::<_, MerkleHasher, Commitment>( &dip_commitment_storage_key, self.state_root.into(), - self.dip_commitment_proof.0.into_iter().map(|i| i.into()), + self.dip_commitment_proof.0, ) .map_err(Error::DipCommitmentMerkleProof)?; Ok(DipDidProofWithVerifiedCommitment { @@ -498,24 +523,17 @@ impl< where MerkleHasher: Hash, { - let mut revealed_keys = self.dip_proof.revealed.iter(); - - // If there are more keys than MAX_LEAVES_REVEALED, bail out. - ensure!(revealed_keys.next().is_none(), Error::TooManyDidLeaves,); - - let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = revealed_keys + let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = self + .dip_proof + .revealed + .iter() .by_ref() .map(|revealed_leaf| (revealed_leaf.encoded_key(), Some(revealed_leaf.encoded_value()))) .collect(); verify_trie_proof::, _, _, _>( &self.dip_commitment, - self.dip_proof - .blinded - .into_iter() - .map(|l| l.into_inner()) - .collect::>() - .as_slice(), + self.dip_proof.blinded.as_slice(), &proof_leaves_key_value_pairs, ) .map_err(|_| Error::InvalidDidMerkleProof)?; diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index f08c0125ed..94bed07467 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -229,6 +229,13 @@ impl< KiltRuntime, DidCallVerifier, SignedExtra, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, > as IdentityProofVerifier>::verify_proof_for_call_against_details( call, subject, @@ -346,7 +353,6 @@ pub mod v0 { ) -> Result { // 1. Verify parachain state is finalized by relay chain and fresh. // TODO: Enforce limits passed by the const generics for each step. - proof.provider_head_proof.proof let proof_without_relaychain = proof .verify_provider_head_proof::>( KILT_PARA_ID, diff --git a/runtimes/common/src/dip/merkle.rs b/runtimes/common/src/dip/merkle.rs index 56edcb4527..16ec5fca81 100644 --- a/runtimes/common/src/dip/merkle.rs +++ b/runtimes/common/src/dip/merkle.rs @@ -18,7 +18,7 @@ use did::{DidVerificationKeyRelationship, KeyIdOf}; use frame_support::RuntimeDebug; use frame_system::pallet_prelude::BlockNumberFor; -use kilt_dip_primitives::RevealedDidMerkleProofLeaf; +use kilt_dip_primitives::DidMerkleProof; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_provider::{ traits::{IdentityCommitmentGenerator, IdentityProvider}, @@ -31,29 +31,9 @@ use sp_trie::{generate_trie_proof, LayoutV1, MemoryDB, TrieDBMutBuilder, TrieHas use crate::dip::did::LinkedDidInfoOf; -#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] -pub struct UnboundDidMerkleProof< - ProviderDidKeyId, - ProviderAccountId, - ProviderBlockNumber, - ProviderWeb3Name, - ProviderLinkableAccountId, -> { - pub(crate) blinded: Vec>, - pub(crate) revealed: Vec< - RevealedDidMerkleProofLeaf< - ProviderDidKeyId, - ProviderAccountId, - ProviderBlockNumber, - ProviderWeb3Name, - ProviderLinkableAccountId, - >, - >, -} - /// Type of the Merkle proof revealing parts of the DIP identity of a given DID /// subject. -pub type DidMerkleProofOf = UnboundDidMerkleProof< +pub type DidMerkleProofOf = DidMerkleProof< KeyIdOf, ::AccountId, BlockNumberFor, @@ -95,39 +75,25 @@ impl From for u16 { } pub mod v0 { + use did::did_details::DidDetails; use kilt_dip_primitives::{ DidKeyRelationship, RevealedAccountId, RevealedDidKey, RevealedDidMerkleProofLeaf, RevealedWeb3Name, }; + use pallet_web3_names::Web3NameOf; - use super::*; + use crate::dip::did::Web3OwnershipOf; - /// Type of a Merkle leaf revealed as part of a DIP Merkle proof. - type ProofLeafOf = RevealedDidMerkleProofLeaf< - KeyIdOf, - ::AccountId, - BlockNumberFor, - ::Web3Name, - LinkableAccountId, - >; + use super::*; - /// Given the provided DID info, it calculates the Merkle commitment (root) - /// using the provided in-memory DB. - pub(super) fn calculate_root_with_db( - identity: &LinkedDidInfoOf, - db: &mut MemoryDB, - ) -> Result + fn get_auth_leaves( + did_details: &DidDetails, + ) -> Result< + impl Iterator, BlockNumberFor, Runtime::AccountId>>, + DidMerkleProofError, + > where - Runtime: did::Config + pallet_did_lookup::Config + pallet_web3_names::Config, + Runtime: did::Config, { - let LinkedDidInfoOf { - did_details, - web3_name_details, - linked_accounts, - } = identity; - let mut trie = TrieHash::>::default(); - let mut trie_builder = TrieDBMutBuilder::>::new(db, &mut trie).build(); - - // Authentication key let auth_key_details = did_details .public_keys .get(&did_details.authentication_key) @@ -135,127 +101,162 @@ pub mod v0 { log::error!("Authentication key should be part of the public keys."); DidMerkleProofError::Internal })?; - let auth_leaf = ProofLeafOf::::from(RevealedDidKey { + Ok([RevealedDidKey { id: did_details.authentication_key, relationship: DidVerificationKeyRelationship::Authentication.into(), details: auth_key_details.clone(), - }); - trie_builder - .insert(auth_leaf.encoded_key().as_slice(), auth_leaf.encoded_value().as_slice()) - .map_err(|_| { - log::error!( - "Failed to insert authentication key in the trie builder. Authentication leaf: {:#?}", - auth_leaf - ); - DidMerkleProofError::Internal - })?; - // Attestation key, if present - if let Some(att_key_id) = did_details.attestation_key { - let att_key_details = did_details.public_keys.get(&att_key_id).ok_or_else(|| { - log::error!("Attestation key should be part of the public keys."); - DidMerkleProofError::Internal - })?; - let att_leaf = ProofLeafOf::::from(RevealedDidKey { - id: att_key_id, - relationship: DidVerificationKeyRelationship::AssertionMethod.into(), - details: att_key_details.clone(), - }); - trie_builder - .insert(att_leaf.encoded_key().as_slice(), att_leaf.encoded_value().as_slice()) - .map_err(|_| { - log::error!( - "Failed to insert attestation key in the trie builder. Attestation leaf: {:#?}", - att_leaf - ); - DidMerkleProofError::Internal - })?; + }] + .into_iter()) + } + + fn get_att_leaves( + did_details: &DidDetails, + ) -> Result< + impl Iterator, BlockNumberFor, Runtime::AccountId>>, + DidMerkleProofError, + > + where + Runtime: did::Config, + { + let Some(att_key_id) = did_details.attestation_key else { + return Ok(vec![].into_iter()); }; - // Delegation key, if present - if let Some(del_key_id) = did_details.delegation_key { - let del_key_details = did_details.public_keys.get(&del_key_id).ok_or_else(|| { - log::error!("Delegation key should be part of the public keys."); - DidMerkleProofError::Internal - })?; - let del_leaf = ProofLeafOf::::from(RevealedDidKey { - id: del_key_id, - relationship: DidVerificationKeyRelationship::CapabilityDelegation.into(), - details: del_key_details.clone(), - }); - trie_builder - .insert(del_leaf.encoded_key().as_slice(), del_leaf.encoded_value().as_slice()) - .map_err(|_| { - log::error!( - "Failed to insert delegation key in the trie builder. Delegation leaf: {:#?}", - del_leaf - ); - DidMerkleProofError::Internal - })?; + let att_key_details = did_details.public_keys.get(&att_key_id).ok_or_else(|| { + log::error!("Attestation key should be part of the public keys."); + DidMerkleProofError::Internal + })?; + Ok(vec![RevealedDidKey { + id: att_key_id, + relationship: DidVerificationKeyRelationship::AssertionMethod.into(), + details: att_key_details.clone(), + }] + .into_iter()) + } + + fn get_del_leaves( + did_details: &DidDetails, + ) -> Result< + impl Iterator, BlockNumberFor, Runtime::AccountId>>, + DidMerkleProofError, + > + where + Runtime: did::Config, + { + let Some(del_key_id) = did_details.delegation_key else { + return Ok(vec![].into_iter()); }; - // Key agreement keys - did_details + let del_key_details = did_details.public_keys.get(&del_key_id).ok_or_else(|| { + log::error!("Delegation key should be part of the public keys."); + DidMerkleProofError::Internal + })?; + Ok(vec![RevealedDidKey { + id: del_key_id, + relationship: DidVerificationKeyRelationship::CapabilityDelegation.into(), + details: del_key_details.clone(), + }] + .into_iter()) + } + + fn get_enc_leaves( + did_details: &DidDetails, + ) -> Result< + impl Iterator, BlockNumberFor, Runtime::AccountId>>, + DidMerkleProofError, + > + where + Runtime: did::Config, + { + let keys = did_details .key_agreement_keys .iter() - .try_for_each(|id| -> Result<(), DidMerkleProofError> { + .map(|id| { let key_agreement_details = did_details.public_keys.get(id).ok_or_else(|| { log::error!("Key agreement key should be part of the public keys."); DidMerkleProofError::Internal })?; - let enc_leaf = ProofLeafOf::::from(RevealedDidKey { + Ok(RevealedDidKey { id: *id, relationship: DidKeyRelationship::Encryption, details: key_agreement_details.clone(), - }); - trie_builder - .insert(enc_leaf.encoded_key().as_slice(), enc_leaf.encoded_value().as_slice()) - .map_err(|_| { - log::error!( - "Failed to insert key agreement key in the trie builder. Key agreement leaf: {:#?}", - enc_leaf - ); - DidMerkleProofError::Internal - })?; - Ok(()) - })?; + }) + }) + .collect::, _>>()?; + Ok(keys.into_iter()) + } - // Linked accounts - linked_accounts + fn get_linked_account_leaves( + linked_accounts: &[LinkableAccountId], + ) -> impl Iterator> { + let leaves = linked_accounts .iter() - .try_for_each(|linked_account| -> Result<(), DidMerkleProofError> { - let linked_account_leaf = ProofLeafOf::::from(RevealedAccountId(linked_account.clone())); - trie_builder - .insert( - linked_account_leaf.encoded_key().as_slice(), - linked_account_leaf.encoded_value().as_slice(), - ) - .map_err(|_| { - log::error!( - "Failed to insert linked account in the trie builder. Linked account leaf: {:#?}", - linked_account_leaf - ); - DidMerkleProofError::Internal - })?; - Ok(()) - })?; + .map(|linked_account| RevealedAccountId(linked_account.clone())); + leaves.collect::>().into_iter() + } + + fn get_web3name_leaf( + web3name_details: &Web3OwnershipOf, + ) -> RevealedWeb3Name, BlockNumberFor> + where + Runtime: pallet_web3_names::Config, + { + RevealedWeb3Name { + web3_name: web3name_details.web3_name.clone(), + claimed_at: web3name_details.claimed_at, + } + } - // Web3name, if present - if let Some(web3name_details) = web3_name_details { - let web3_name_leaf = ProofLeafOf::::from(RevealedWeb3Name { - web3_name: web3name_details.web3_name.clone(), - claimed_at: web3name_details.claimed_at, - }); + /// Given the provided DID info, it calculates the Merkle commitment (root) + /// using the provided in-memory DB. + pub(super) fn calculate_root_with_db( + identity: &LinkedDidInfoOf, + db: &mut MemoryDB, + ) -> Result + where + Runtime: did::Config + pallet_did_lookup::Config + pallet_web3_names::Config, + { + let LinkedDidInfoOf { + did_details, + web3_name_details, + linked_accounts, + } = identity; + let mut trie = TrieHash::>::default(); + let mut trie_builder = TrieDBMutBuilder::>::new(db, &mut trie).build(); + + // Authentication key. + let auth_leaves = get_auth_leaves(did_details)?; + // Attestation key, if present. + let att_leaves = get_att_leaves(did_details)?; + // Delegation key, if present. + let del_leaves = get_del_leaves(did_details)?; + // Key agreement keys. + let enc_leaves = get_enc_leaves(did_details)?; + // Linked accounts. + let linked_accounts = get_linked_account_leaves(linked_accounts); + // Web3name. + let web3_name = web3_name_details.as_ref().map(get_web3name_leaf::); + + // Add all leaves to the proof builder. + let keys = auth_leaves + .chain(att_leaves) + .chain(del_leaves) + .chain(enc_leaves) + .map(RevealedDidMerkleProofLeaf::from); + let linked_accounts = linked_accounts.map(RevealedDidMerkleProofLeaf::from); + let web3_names = web3_name + .map(|n| vec![n]) + .unwrap_or(vec![]) + .into_iter() + .map(RevealedDidMerkleProofLeaf::from); + + keys.chain(linked_accounts).chain(web3_names).try_for_each(|leaf| { trie_builder - .insert( - web3_name_leaf.encoded_key().as_slice(), - web3_name_leaf.encoded_value().as_slice(), - ) + .insert(leaf.encoded_key().as_slice(), leaf.encoded_value().as_slice()) .map_err(|_| { - log::error!( - "Failed to insert web3name in the trie builder. Web3name leaf: {:#?}", - web3_name_leaf - ); + log::error!("Failed to insert leaf in the trie builder. Leaf: {:#?}", leaf); DidMerkleProofError::Internal })?; - } + Ok(()) + })?; trie_builder.commit(); Ok(trie_builder.root().to_owned()) @@ -347,10 +348,7 @@ pub mod v0 { Ok(CompleteMerkleProof { root, - proof: DidMerkleProofOf:: { - blinded: proof, - revealed: leaves, - }, + proof: DidMerkleProofOf::::new(proof, leaves), }) } From 3c88ad5b1f15b97fa349b20011581ba3ecfca4e3 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 16 Jan 2024 11:17:16 +0100 Subject: [PATCH 21/45] Debug assertions --- crates/kilt-dip-primitives/src/state_proofs/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/kilt-dip-primitives/src/state_proofs/mod.rs b/crates/kilt-dip-primitives/src/state_proofs/mod.rs index 129a9694ce..d240bfc573 100644 --- a/crates/kilt-dip-primitives/src/state_proofs/mod.rs +++ b/crates/kilt-dip-primitives/src/state_proofs/mod.rs @@ -69,8 +69,6 @@ where let revealed_leaves = read_proof_check::(state_root, storage_proof, [storage_key].iter()) .map_err(|_| MerkleProofError::InvalidProof)?; - #[cfg(feature)] - debug_assert!( revealed_leaves.len() == 1usize, "Only a single leaf is expected to be revealed in the storage proof." From cb6b385dcca888aae8d7ce165b918763f5c455ef Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 16 Jan 2024 11:38:14 +0100 Subject: [PATCH 22/45] Minor chores --- .../src/verifier/parachain.rs | 2 +- .../src/verifier/relaychain.rs | 56 ++++++++++++++++--- .../nodes/dip-consumer/src/command.rs | 11 ++-- .../nodes/dip-provider/src/command.rs | 11 ++-- runtimes/common/src/dip/did.rs | 2 +- 5 files changed, 65 insertions(+), 17 deletions(-) diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index b09b4a0f7c..f3b4b27897 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -253,7 +253,7 @@ pub mod v0 { use frame_system::pallet_prelude::HeaderFor; use sp_runtime::traits::Zero; - use crate::merkle::v0::{DipVerifiedInfo, ParachainDipDidProof}; + use crate::merkle::v0::ParachainDipDidProof; pub struct ParachainVerifier< RelaychainRuntime, diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index a8ca3678d6..aec391b60e 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -133,7 +133,13 @@ pub struct KiltVersionedRelaychainVerifier< KiltRuntime, DidCallVerifier, SignedExtra = (), - const MAX_LEAVES_REVEALED: u32 = 50, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 10, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 10, >(#[allow(clippy::type_complexity)] PhantomData<(ConsumerBlockHashStore, KiltRuntime, DidCallVerifier, SignedExtra)>); impl< @@ -143,7 +149,13 @@ impl< KiltRuntime, DidCallVerifier, SignedExtra, - const MAX_LEAVES_REVEALED: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > IdentityProofVerifier for KiltVersionedRelaychainVerifier< ConsumerBlockHashStore, @@ -151,7 +163,13 @@ impl< KiltRuntime, DidCallVerifier, SignedExtra, - MAX_LEAVES_REVEALED, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, > where ConsumerRuntime: pallet_dip_consumer::Config, ConsumerRuntime::LocalIdentityInfo: Incrementable + Default, @@ -200,7 +218,13 @@ impl< KiltRuntime, DidCallVerifier, SignedExtra, - MAX_LEAVES_REVEALED, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, > as IdentityProofVerifier>::verify_proof_for_call_against_details( call, subject, @@ -294,7 +318,13 @@ pub mod v0 { KiltRuntime, DidCallVerifier, SignedExtra, - const MAX_LEAVES_REVEALED: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, >( #[allow(clippy::type_complexity)] PhantomData<(ConsumerBlockHashStore, KiltRuntime, DidCallVerifier, SignedExtra)>, @@ -307,7 +337,13 @@ pub mod v0 { KiltRuntime, DidCallVerifier, SignedExtra, - const MAX_LEAVES_REVEALED: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32, + const MAX_DID_MERKLE_LEAVES_REVEALED: u32, > IdentityProofVerifier for RelaychainVerifier< ConsumerBlockHashStore, @@ -315,7 +351,13 @@ pub mod v0 { KiltRuntime, DidCallVerifier, SignedExtra, - MAX_LEAVES_REVEALED, + MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT, + MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE, + MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT, + MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_PROOF_LEAVE_COUNT, + MAX_DID_MERKLE_PROOF_LEAVE_SIZE, + MAX_DID_MERKLE_LEAVES_REVEALED, > where ConsumerRuntime: pallet_dip_consumer::Config, ConsumerRuntime::LocalIdentityInfo: Incrementable + Default, diff --git a/dip-template/nodes/dip-consumer/src/command.rs b/dip-template/nodes/dip-consumer/src/command.rs index 7d6cb78290..048933f6a5 100644 --- a/dip-template/nodes/dip-consumer/src/command.rs +++ b/dip-template/nodes/dip-consumer/src/command.rs @@ -210,11 +210,14 @@ pub fn run() -> Result<()> { cmd.run(partials.client) }), #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => Err(sc_cli::Error::Input( - "Compile with --features=runtime-benchmarks \ + BenchmarkCmd::Storage(_) => { + return Err(sc_cli::Error::Input( + "Compile with --features=runtime-benchmarks \ to enable storage benchmarks." - .into(), - )), + .into(), + ) + .into()) + } #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { let partials = new_partial(&config)?; diff --git a/dip-template/nodes/dip-provider/src/command.rs b/dip-template/nodes/dip-provider/src/command.rs index 5934c78874..7913cafd0a 100644 --- a/dip-template/nodes/dip-provider/src/command.rs +++ b/dip-template/nodes/dip-provider/src/command.rs @@ -210,11 +210,14 @@ pub fn run() -> Result<()> { cmd.run(partials.client) }), #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => Err(sc_cli::Error::Input( - "Compile with --features=runtime-benchmarks \ + BenchmarkCmd::Storage(_) => { + return Err(sc_cli::Error::Input( + "Compile with --features=runtime-benchmarks \ to enable storage benchmarks." - .into(), - )), + .into(), + ) + .into()) + } #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { let partials = new_partial(&config)?; diff --git a/runtimes/common/src/dip/did.rs b/runtimes/common/src/dip/did.rs index fe3297c7c3..55c31bd7e9 100644 --- a/runtimes/common/src/dip/did.rs +++ b/runtimes/common/src/dip/did.rs @@ -19,7 +19,7 @@ use did::did_details::DidDetails; use frame_support::ensure; use frame_system::pallet_prelude::BlockNumberFor; -use kilt_dip_primitives::RevealedWeb3Name; +use kilt_dip_primitives::merkle::RevealedWeb3Name; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_provider::traits::IdentityProvider; use parity_scale_codec::{Decode, Encode}; From 290f7cd9dafe292458a01c2e848564be1ae7b345 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 16 Jan 2024 12:39:28 +0100 Subject: [PATCH 23/45] Before refactoring with runtime --- crates/kilt-dip-primitives/src/merkle/v0.rs | 185 ++++++++++++++++++ crates/kilt-dip-primitives/src/traits.rs | 10 + .../src/verifier/parachain.rs | 60 +++--- 3 files changed, 217 insertions(+), 38 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index 25b3ac0ee4..54638e6964 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -22,6 +22,7 @@ use did::{ DidSignature, DidVerificationKeyRelationship, }; use frame_support::{ensure, RuntimeDebug}; +use pallet_dip_provider::IdentityCommitmentOf; use parity_scale_codec::{Codec, Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_core::U256; @@ -41,15 +42,29 @@ use crate::{ }, }; +/// The state proof for a parachain head. +/// +/// The generic types indicate the following: +/// * `RelayBlockNumber`: The `BlockNumber` definition of the relaychain. #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct ProviderHeadStateProof { pub(crate) relay_block_number: RelayBlockNumber, pub(crate) proof: Vec>, } +/// The state proof for a DIP commitment. #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct DipCommitmentStateProof(pub(crate) Vec>); +/// The Merkle proof for a KILT DID. +/// +/// The generic types indicate the following: +/// * `ProviderDidKeyId`: The DID key ID type configured by the provider. +/// * `ProviderAccountId`: The `AccountId` type configured by the provider. +/// * `ProviderBlockNumber`: The `BlockNumber` type configured by the provider. +/// * `ProviderWeb3Name`: The web3name type configured by the provider. +/// * `ProviderLinkableAccountId`: The linkable account ID type configured by +/// the provider. #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct DidMerkleProof< ProviderDidKeyId, @@ -90,6 +105,10 @@ impl { /// The signature. @@ -134,6 +153,17 @@ impl From for u8 { } } +/// A DIP proof submitted to a relaychain consumer. +/// +/// The generic types indicate the following: +/// * `RelayBlockNumber`: The `BlockNumber` definition of the relaychain. +/// * `RelayBlockHasher`: The hashing algorithm used by the relaychain. +/// * `KiltDidKeyId`: The DID key ID type configured by the KILT chain. +/// * `KiltAccountId`: The `AccountId` type configured by the KILT chain. +/// * `KiltBlockNumber`: The `BlockNumber` type configured by the KILT chain. +/// * `KiltWeb3Name`: The web3name type configured by the KILT chain. +/// * `KiltLinkableAccountId`: The linkable account ID type configured by the +/// KILT chain. #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct RelayDipDidProof< RelayBlockNumber: Copy + Into + TryFrom, @@ -144,11 +174,17 @@ pub struct RelayDipDidProof< KiltWeb3Name, KiltLinkableAccountId, > { + /// The relaychain header for the relaychain block specified in the + /// `provider_head_proof`. pub(crate) relay_header: Header, + /// The state proof for the given parachain head. pub(crate) provider_head_proof: ProviderHeadStateProof, + /// The raw state proof for the DIP commitment of the given subject. pub(crate) dip_commitment_proof: DipCommitmentStateProof, + /// The Merkle proof of the subject's DID details. pub(crate) dip_proof: DidMerkleProof, + /// The cross-chain DID signature. pub(crate) signature: TimeBoundDidSignature, } @@ -171,6 +207,8 @@ impl< KiltLinkableAccountId, > { + /// Verifies the relaychain part of the state proof using the provided block + /// hash. #[allow(clippy::type_complexity)] pub fn verify_relay_header_with_block_hash( self, @@ -200,6 +238,12 @@ impl< }) } + /// Verifies the relaychain part of the state proof using the block hash + /// returned by the provided implementation. + /// + /// The generic types indicate the following: + /// * `RelayHashStore`: The type that returns a relaychain block hash given + /// a relaychain block number. #[allow(clippy::type_complexity)] pub fn verify_relay_header( self, @@ -223,6 +267,18 @@ impl< } } +/// A DIP proof submitted to a relaychain consumer that has had the proof header +/// verified against a given block hash. +/// +/// The generic types indicate the following: +/// * `RelayBlockHasher`: The hashing algorithm used by the relaychain. +/// * `RelayBlockNumber`: The `BlockNumber` definition of the relaychain. +/// * `KiltDidKeyId`: The DID key ID type configured by the KILT chain. +/// * `KiltAccountId`: The `AccountId` type configured by the KILT chain. +/// * `KiltBlockNumber`: The `BlockNumber` type configured by the KILT chain. +/// * `KiltWeb3Name`: The web3name type configured by the KILT chain. +/// * `KiltLinkableAccountId`: The linkable account ID type configured by the +/// KILT chain. pub struct DipDidProofWithVerifiedRelayStateRoot< RelayHasher: Hash, RelayBlockNumber, @@ -232,11 +288,17 @@ pub struct DipDidProofWithVerifiedRelayStateRoot< KiltWeb3Name, KiltLinkableAccountId, > { + /// The verified state root for the relaychain at the block specified in the + /// proof. pub(crate) relay_state_root: OutputOf, + /// The state proof for the given parachain head. pub(crate) provider_head_proof: ProviderHeadStateProof, + /// The raw state proof for the DIP commitment of the given subject. pub(crate) dip_commitment_proof: DipCommitmentStateProof, + /// The Merkle proof of the subject's DID details. pub(crate) dip_proof: DidMerkleProof, + /// The cross-chain DID signature. pub(crate) signature: TimeBoundDidSignature, } @@ -259,6 +321,12 @@ impl< KiltLinkableAccountId, > { + /// Verifies the head data of the state proof for the provider with the + /// given para ID. + /// + /// The generic types indicate the following: + /// * `ProviderHeader`: The type of the parachain header to be revealed in + /// the state proof. #[allow(clippy::type_complexity)] pub fn verify_provider_head_proof( self, @@ -292,6 +360,18 @@ impl< } } +/// A DIP proof submitted to a parachain consumer. +/// +/// The generic types indicate the following: +/// * `RelayBlockNumber`: The `BlockNumber` definition of the relaychain. +/// * `KiltDidKeyId`: The DID key ID type configured by the KILT chain. +/// * `KiltAccountId`: The `AccountId` type configured by the KILT chain. +/// * `KiltBlockNumber`: The `BlockNumber` type configured by the KILT chain. +/// * `KiltWeb3Name`: The web3name type configured by the KILT chain. +/// * `KiltLinkableAccountId`: The linkable account ID type configured by the +/// KILT chain. +/// * `ConsumerBlockNumber`: The `BlockNumber` definition of the consumer +/// parachain. #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct ParachainDipDidProof< RelayBlockNumber, @@ -302,10 +382,14 @@ pub struct ParachainDipDidProof< KiltLinkableAccountId, ConsumerBlockNumber, > { + /// The state proof for the given parachain head. pub(crate) provider_head_proof: ProviderHeadStateProof, + /// The raw state proof for the DIP commitment of the given subject. pub(crate) dip_commitment_proof: DipCommitmentStateProof, + /// The Merkle proof of the subject's DID details. pub(crate) dip_proof: DidMerkleProof, + /// The cross-chain DID signature. pub(crate) signature: TimeBoundDidSignature, } @@ -328,6 +412,8 @@ impl< ConsumerBlockNumber, > { + /// Verifies the head data of the state proof for the provider with the + /// given para ID and relaychain state root. #[allow(clippy::type_complexity)] pub fn verify_provider_head_proof_with_state_root( self, @@ -364,6 +450,17 @@ impl< }) } + /// Verifies the head data of the state proof for the provider with the + /// given para ID using the state root returned by the provided + /// implementation. + /// + /// The generic types indicate the following: + /// * `RelayHasher`: The hashing algorithm used on the relaychain to + /// generate the parachains head data. + /// * `StateRootStore`: The type that returns a relaychain state root given + /// a relaychain block number. + /// * `ProviderHeader`: The type of the parachain header to be revealed in + /// the state proof. #[allow(clippy::type_complexity)] pub fn verify_provider_head_proof( self, @@ -394,6 +491,19 @@ impl< } } +/// A DIP proof that has had the proof header and the relaychain state verified +/// for the provided relaychain block number. +/// +/// The generic types indicate the following: +/// * `StateRoot`: The type of the relaychain state root. +/// * `KiltDidKeyId`: The DID key ID type configured by the KILT chain. +/// * `KiltAccountId`: The `AccountId` type configured by the KILT chain. +/// * `KiltBlockNumber`: The `BlockNumber` type configured by the KILT chain. +/// * `KiltWeb3Name`: The web3name type configured by the KILT chain. +/// * `KiltLinkableAccountId`: The linkable account ID type configured by the +/// KILT chain. +/// * `ConsumerBlockNumber`: The `BlockNumber` definition of the consumer +/// parachain. pub struct DipDidProofWithoutRelayProof< StateRoot, KiltDidKeyId, @@ -403,10 +513,14 @@ pub struct DipDidProofWithoutRelayProof< KiltLinkableAccountId, ConsumerBlockNumber, > { + /// The relaychain state root for the block specified in the DIP proof. pub(crate) state_root: StateRoot, + /// The raw state proof for the DIP commitment of the given subject. pub(crate) dip_commitment_proof: DipCommitmentStateProof, + /// The Merkle proof of the subject's DID details. pub(crate) dip_proof: DidMerkleProof, + /// The cross-chain DID signature. pub(crate) signature: TimeBoundDidSignature, } @@ -429,7 +543,16 @@ impl< ConsumerBlockNumber, > { + /// Verifies the DIP commitment part of the state proof for the subject with + /// the given identifier. + /// + /// The generic types indicate the following: + /// * `MerkleHasher`: The hashing algorithm used to generate the identity + /// commitment. + /// * `ProviderRuntime`: The provider runtime definition. + /// * `Commitment`: The provider definition of an identity commitment. #[allow(clippy::type_complexity)] + // TODO: Refactor this. pub fn verify_dip_commitment_proof_for_subject( self, subject: &ProviderRuntime::Identifier, @@ -468,6 +591,20 @@ impl< } } +/// A DIP proof that has had the relaychain state and the DIP commitment +/// verified for the provided relaychain block number. +/// +/// The generic types indicate the following: +/// * `Commitment`: The DIP identity commitment type configured by the KILT +/// chain. +/// * `KiltDidKeyId`: The DID key ID type configured by the KILT chain. +/// * `KiltAccountId`: The `AccountId` type configured by the KILT chain. +/// * `KiltBlockNumber`: The `BlockNumber` type configured by the KILT chain. +/// * `KiltWeb3Name`: The web3name type configured by the KILT chain. +/// * `KiltLinkableAccountId`: The linkable account ID type configured by the +/// KILT chain. +/// * `ConsumerBlockNumber`: The `BlockNumber` definition of the consumer +/// parachain. pub struct DipDidProofWithVerifiedCommitment< Commitment, KiltDidKeyId, @@ -477,9 +614,12 @@ pub struct DipDidProofWithVerifiedCommitment< KiltLinkableAccountId, ConsumerBlockNumber, > { + /// The verified DIP identity commitment. pub(crate) dip_commitment: Commitment, + /// The Merkle proof of the subject's DID details. pub(crate) dip_proof: DidMerkleProof, + /// The cross-chain DID signature. pub(crate) signature: TimeBoundDidSignature, } @@ -507,6 +647,11 @@ impl< KiltWeb3Name: Encode, KiltLinkableAccountId: Encode, { + /// Verifies the Merkle proof of the subject's DID details. + /// + /// The generic types indicate the following: + /// * `MerkleHasher`: The hashing algorithm used to merkleize the DID + /// details. pub fn verify_dip_proof( self, ) -> Result< @@ -545,6 +690,18 @@ impl< } } +/// A DIP proof whose information has been verified but that contains a +/// cross-chain [`TimeBoundDidSignature`] that still needs verification. +/// +/// The generic types indicate the following: +/// * `KiltDidKeyId`: The DID key ID type configured by the KILT chain. +/// * `KiltAccountId`: The `AccountId` type configured by the KILT chain. +/// * `KiltBlockNumber`: The `BlockNumber` type configured by the KILT chain. +/// * `KiltWeb3Name`: The web3name type configured by the KILT chain. +/// * `KiltLinkableAccountId`: The linkable account ID type configured by the +/// KILT chain. +/// * `ConsumerBlockNumber`: The `BlockNumber` definition of the consumer +/// parachain. pub struct DipDetailsAndUnverifiedDidSignatureTime< KiltDidKeyId, KiltAccountId, @@ -553,9 +710,11 @@ pub struct DipDetailsAndUnverifiedDidSignatureTime< KiltLinkableAccountId, ConsumerBlockNumber, > { + /// The parts of the subject's DID details revealed in the DIP proof. pub(crate) revealed_leaves: Vec< RevealedDidMerkleProofLeaf, >, + /// The cross-chain DID signature. pub(crate) signature: TimeBoundDidSignature, } @@ -570,6 +729,8 @@ impl where ConsumerBlockNumber: PartialOrd, { + /// Verifies that the DIP proof signature is anchored to a block that has + /// not passed on the consumer chain. pub fn verify_signature_time( self, block_number: &ConsumerBlockNumber, @@ -591,6 +752,17 @@ impl { + /// The parts of the subject's DID details revealed in the DIP proof. pub(crate) revealed_leaves: Vec< RevealedDidMerkleProofLeaf, >, + /// The cross-chain DID signature without time information. pub(crate) signature: DidSignature, } @@ -613,6 +787,8 @@ impl { + /// Iterates over the revealed DID leafs to find the one that generated a + /// valid signature for the provided payload. pub fn retrieve_signing_leaf_for_payload( self, payload: &[u8], @@ -652,17 +828,22 @@ impl { + /// The parts of the subject's DID details revealed in the DIP proof. revealed_leaves: Vec< RevealedDidMerkleProofLeaf, >, + /// The index of the signing leaf from the vector above, signing_leaf_index: u32, } impl DipVerifiedInfo { + /// Returns an iterator over the revealed DID leaves. pub fn iter_leaves( &self, ) -> impl Iterator< @@ -676,6 +857,10 @@ impl { self.revealed_leaves.iter() } + + /// Returns a reference to the leaf that signed the cross-chain operation. + /// This operation should never fail, so the only error it returns is an + /// `Error::Internal` which, anyway, should never happen. pub fn get_signing_leaf(&self) -> Result<&RevealedDidKey, Error> { let RevealedDidMerkleProofLeaf::DidKey(did_key) = &self.revealed_leaves[usize::saturated_from(self.signing_leaf_index)] diff --git a/crates/kilt-dip-primitives/src/traits.rs b/crates/kilt-dip-primitives/src/traits.rs index 01f8055f32..8a20d43233 100644 --- a/crates/kilt-dip-primitives/src/traits.rs +++ b/crates/kilt-dip-primitives/src/traits.rs @@ -57,12 +57,20 @@ pub trait DipCallOriginFilter { fn check_call_origin_info(call: &Call, info: &Self::OriginInfo) -> Result; } +/// A trait similar in functionality to the [`frame_support::traits::Get`], but +/// with an input argument and an associated return type. pub trait GetWithArg { type Result; fn get(arg: &Arg) -> Self::Result; } +/// Implementor of the [`GetWithArg`] trait that return the state +/// root of a relaychain block with a given number by retrieving it from the +/// [`pallet_relay_store::Pallet`] pallet storage. It hardcodes the +/// relaychain `BlockNumber`, `Hasher`, `StorageKey`, and `ParaId` to the +/// ones used by Polkadot-based relaychains. This type cannot be used with +/// relaychains that adopt a different definition for any on those types. pub struct RelayStateRootsViaRelayStorePallet(PhantomData); impl GetWithArg for RelayStateRootsViaRelayStorePallet @@ -77,6 +85,8 @@ where } } +/// A trait similar in functionality to the [`frame_support::traits::Get`], but +/// with an associated return type. pub trait GetWithoutArg { type Result; diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index f3b4b27897..13aa7799f9 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -84,48 +84,32 @@ where /// Proof verifier configured given a specific KILT runtime implementation. /// -/// It is a specialization of the -/// [`GenericVersionedParachainVerifier`] type, with -/// configurations derived from the provided KILT runtime. -/// /// The generic types /// indicate the following: +/// * `RelaychainRuntime`: The relaychain runtime definition. +/// * `RelaychainStateRootStore`: A type providing state roots for relaychain +/// blocks. +/// * `KILT_PARA_ID`: The ID of the specific KILT parachain instance. /// * `KiltRuntime`: A KILT runtime definition. -/// * `KiltParachainId`: The ID of the specific KILT parachain instance. -/// * `RelayChainInfo`: The type providing information about the relaychain. -/// * `KiltDipMerkleHasher`: The hashing algorithm used by the KILT parachain -/// for the generation of the DIP identity commitment. -/// * `LocalDidCallVerifier`: Logic to map `RuntimeCall`s to a specific DID key +/// * `DidCallVerifier`: Logic to map `RuntimeCall`s to a specific DID key /// relationship. This information is used once the Merkle proof is verified, /// to filter only the revealed keys that match the provided relationship. -/// * `MAX_REVEALED_KEYS_COUNT`: **OPTIONAL** Max number of DID keys that the -/// verifier will accept revealed as part of the DIP identity proof. It -/// defaults to **10**. -/// * `MAX_REVEALED_ACCOUNTS_COUNT`: **OPTIONAL** Max number of linked accounts -/// that the verifier will accept revealed as part of the DIP identity proof. -/// It defaults to **10**. -/// * `MAX_DID_SIGNATURE_DURATION`: **OPTIONAL** Max number of blocks a -/// cross-chain DID signature is considered fresh. It defaults to **50**. -/// -/// It specializes the [`GenericVersionedParachainVerifier`] -/// type by using the following types for its generics: -/// * `RelayChainInfo`: The provided `RelayChainInfo`. -/// * `ChildProviderParachainId`: The provided `KiltParachainId`. -/// * `ChildProviderStateInfo`: The -/// [`ProviderParachainStateInfoViaProviderPallet`] type configured with the -/// provided `KiltRuntime`. -/// * `ProviderDipMerkleHasher`: The provided `KiltDipMerkleHasher`. -/// * `ProviderDidKeyId`: The [`KeyIdOf`] type configured with the provided -/// `KiltRuntime`. -/// * `KiltAccountId`: The `KiltRuntime::AccountId` type. -/// * `KiltWeb3Name`: The `KiltRuntime::Web3Name` type. -/// * `KiltLinkableAccountId`: The [`LinkableAccountId`] type. -/// * `MAX_REVEALED_KEYS_COUNT`: The provided `MAX_REVEALED_KEYS_COUNT`. -/// * `MAX_REVEALED_ACCOUNTS_COUNT`: The provided `MAX_REVEALED_ACCOUNTS_COUNT`. -/// * `LocalContextProvider`: The [`FrameSystemDidSignatureContext`] type -/// configured with the provided `KiltRuntime` and -/// `MAX_DID_SIGNATURE_DURATION`. -/// * `LocalDidCallVerifier`: The provided `LocalDidCallVerifier`. +/// * `SignedExtra`: Any additional information that must be signed by the DID +/// subject in the cross-chain operation. +/// * `MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT`: The maximum number of leaves that +/// can be revealed as part of the parachain head storage proof. +/// * `MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE`: The maximum size of each leaf +/// revealed as part of the parachain head storage proof. +/// * `MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT`: The maximum number of leaves that +/// can be revealed as part of the DIP commitment storage proof. +/// * `MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE`: The maximum size of each leaf +/// revealed as part of the DIP commitment storage proof. +/// * `MAX_DID_MERKLE_PROOF_LEAVE_COUNT`: The maximum number of *blinded* leaves +/// that can be revealed as part of the DID Merkle proof. +/// * `MAX_DID_MERKLE_PROOF_LEAVE_SIZE`: The maximum size of each *blinded* leaf +/// revealed as part of the DID Merkle proof. +/// * `MAX_DID_MERKLE_PROOF_LEAVE_SIZE`: The maximum number of leaves that can +/// be revealed as part of the DID Merkle proof. pub struct KiltVersionedParachainVerifier< RelaychainRuntime, RelaychainStateRootStore, @@ -361,7 +345,7 @@ pub mod v0 { // 2. Verify commitment is included in provider parachain state. let proof_without_parachain = proof_without_relaychain - .verify_dip_commitment_proof_for_subject::(subject) + .verify_dip_commitment_proof_for_subject::(subject) .map_err(DipParachainStateProofVerifierError::ProofVerification)?; // 3. Verify DIP Merkle proof. From 1c70fc448e5847cad0a8d120e31fd972cb652934 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 16 Jan 2024 15:07:58 +0100 Subject: [PATCH 24/45] COMPILING --- crates/kilt-dip-primitives/src/merkle/v0.rs | 71 +++++++++---------- .../src/verifier/parachain.rs | 20 ++++-- .../src/verifier/relaychain.rs | 22 ++++-- 3 files changed, 65 insertions(+), 48 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index 54638e6964..7af85b9b55 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -157,7 +157,7 @@ impl From for u8 { /// /// The generic types indicate the following: /// * `RelayBlockNumber`: The `BlockNumber` definition of the relaychain. -/// * `RelayBlockHasher`: The hashing algorithm used by the relaychain. +/// * `RelayHasher`: The hashing algorithm used by the relaychain. /// * `KiltDidKeyId`: The DID key ID type configured by the KILT chain. /// * `KiltAccountId`: The `AccountId` type configured by the KILT chain. /// * `KiltBlockNumber`: The `BlockNumber` type configured by the KILT chain. @@ -167,7 +167,7 @@ impl From for u8 { #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct RelayDipDidProof< RelayBlockNumber: Copy + Into + TryFrom, - RelayBlockHasher: Hash, + RelayHasher: Hash, KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -176,7 +176,7 @@ pub struct RelayDipDidProof< > { /// The relaychain header for the relaychain block specified in the /// `provider_head_proof`. - pub(crate) relay_header: Header, + pub(crate) relay_header: Header, /// The state proof for the given parachain head. pub(crate) provider_head_proof: ProviderHeadStateProof, /// The raw state proof for the DIP commitment of the given subject. @@ -190,7 +190,7 @@ pub struct RelayDipDidProof< impl< RelayBlockNumber: Member + sp_std::hash::Hash + Copy + MaybeDisplay + AtLeast32BitUnsigned + Codec + Into + TryFrom, - RelayBlockHasher: Hash, + RelayHasher: Hash, KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -199,7 +199,7 @@ impl< > RelayDipDidProof< RelayBlockNumber, - RelayBlockHasher, + RelayHasher, KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -212,10 +212,10 @@ impl< #[allow(clippy::type_complexity)] pub fn verify_relay_header_with_block_hash( self, - block_hash: &OutputOf, + block_hash: &OutputOf, ) -> Result< DipDidProofWithVerifiedRelayStateRoot< - RelayBlockHasher, + OutputOf, RelayBlockNumber, KiltDidKeyId, KiltAccountId, @@ -249,7 +249,7 @@ impl< self, ) -> Result< DipDidProofWithVerifiedRelayStateRoot< - RelayBlockHasher, + OutputOf, RelayBlockNumber, KiltDidKeyId, KiltAccountId, @@ -260,7 +260,7 @@ impl< Error, > where - RelayHashStore: GetWithArg>>, + RelayHashStore: GetWithArg>>, { let relay_block_hash = RelayHashStore::get(&self.relay_header.number).ok_or(Error::RelayBlockNotFound)?; self.verify_relay_header_with_block_hash(&relay_block_hash) @@ -271,7 +271,7 @@ impl< /// verified against a given block hash. /// /// The generic types indicate the following: -/// * `RelayBlockHasher`: The hashing algorithm used by the relaychain. +/// * `StateRoot`: The type of the state root used by the relaychain. /// * `RelayBlockNumber`: The `BlockNumber` definition of the relaychain. /// * `KiltDidKeyId`: The DID key ID type configured by the KILT chain. /// * `KiltAccountId`: The `AccountId` type configured by the KILT chain. @@ -280,7 +280,7 @@ impl< /// * `KiltLinkableAccountId`: The linkable account ID type configured by the /// KILT chain. pub struct DipDidProofWithVerifiedRelayStateRoot< - RelayHasher: Hash, + StateRoot, RelayBlockNumber, KiltDidKeyId, KiltAccountId, @@ -290,7 +290,7 @@ pub struct DipDidProofWithVerifiedRelayStateRoot< > { /// The verified state root for the relaychain at the block specified in the /// proof. - pub(crate) relay_state_root: OutputOf, + pub(crate) relay_state_root: StateRoot, /// The state proof for the given parachain head. pub(crate) provider_head_proof: ProviderHeadStateProof, /// The raw state proof for the DIP commitment of the given subject. @@ -303,7 +303,7 @@ pub struct DipDidProofWithVerifiedRelayStateRoot< } impl< - RelayHasher: Hash, + StateRoot, RelayBlockNumber, KiltDidKeyId, KiltAccountId, @@ -312,7 +312,7 @@ impl< KiltLinkableAccountId, > DipDidProofWithVerifiedRelayStateRoot< - RelayHasher, + StateRoot, RelayBlockNumber, KiltDidKeyId, KiltAccountId, @@ -328,12 +328,12 @@ impl< /// * `ProviderHeader`: The type of the parachain header to be revealed in /// the state proof. #[allow(clippy::type_complexity)] - pub fn verify_provider_head_proof( + pub fn verify_provider_head_proof( self, provider_para_id: u32, ) -> Result< DipDidProofWithoutRelayProof< - OutputOf, + OutputOf, KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -344,7 +344,8 @@ impl< Error, > where - ProviderHeader: Decode + HeaderT, + RelayHasher: Hash, + ProviderHeader: Decode + HeaderT>, { let parachain_dip_proof = ParachainDipDidProof { provider_head_proof: self.provider_head_proof, @@ -421,7 +422,7 @@ impl< relay_state_root: &OutputOf, ) -> Result< DipDidProofWithoutRelayProof< - OutputOf, + OutputOf, KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -433,7 +434,7 @@ impl< > where RelayHasher: Hash, - ProviderHeader: Decode + HeaderT, + ProviderHeader: Decode + HeaderT>, { let provider_head_storage_key = calculate_parachain_head_storage_key(provider_para_id); let provider_header = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( @@ -467,7 +468,7 @@ impl< provider_para_id: u32, ) -> Result< DipDidProofWithoutRelayProof< - OutputOf, + OutputOf, KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -480,7 +481,7 @@ impl< where RelayHasher: Hash, StateRootStore: GetWithArg>>, - ProviderHeader: Decode + HeaderT, + ProviderHeader: Decode + HeaderT>, { let relay_state_root = StateRootStore::get(&self.provider_head_proof.relay_block_number).ok_or(Error::RelayStateRootNotFound)?; @@ -547,18 +548,16 @@ impl< /// the given identifier. /// /// The generic types indicate the following: - /// * `MerkleHasher`: The hashing algorithm used to generate the identity - /// commitment. + /// * `ParachainHasher`: The hashing algorithm used to hash storage on the + /// parachain. /// * `ProviderRuntime`: The provider runtime definition. - /// * `Commitment`: The provider definition of an identity commitment. #[allow(clippy::type_complexity)] - // TODO: Refactor this. - pub fn verify_dip_commitment_proof_for_subject( + pub fn verify_dip_commitment_proof_for_subject( self, subject: &ProviderRuntime::Identifier, ) -> Result< DipDidProofWithVerifiedCommitment< - Commitment, + IdentityCommitmentOf, KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -569,17 +568,15 @@ impl< Error, > where - MerkleHasher: Hash, - StateRoot: Into>, + StateRoot: Ord, + ParachainHasher: Hash, ProviderRuntime: pallet_dip_provider::Config, - Commitment: Decode, - OutputOf: Into, { let dip_commitment_storage_key = calculate_dip_identity_commitment_storage_key_for_runtime::(subject, 0); - let dip_commitment = verify_storage_value_proof::<_, MerkleHasher, Commitment>( + let dip_commitment = verify_storage_value_proof::<_, ParachainHasher, IdentityCommitmentOf>( &dip_commitment_storage_key, - self.state_root.into(), + self.state_root, self.dip_commitment_proof.0, ) .map_err(Error::DipCommitmentMerkleProof)?; @@ -650,9 +647,9 @@ impl< /// Verifies the Merkle proof of the subject's DID details. /// /// The generic types indicate the following: - /// * `MerkleHasher`: The hashing algorithm used to merkleize the DID + /// * `DidMerkleHasher`: The hashing algorithm used to merkleize the DID /// details. - pub fn verify_dip_proof( + pub fn verify_dip_proof( self, ) -> Result< DipDetailsAndUnverifiedDidSignatureTime< @@ -666,7 +663,7 @@ impl< Error, > where - MerkleHasher: Hash, + DidMerkleHasher: Hash, { let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = self .dip_proof @@ -676,7 +673,7 @@ impl< .map(|revealed_leaf| (revealed_leaf.encoded_key(), Some(revealed_leaf.encoded_value()))) .collect(); - verify_trie_proof::, _, _, _>( + verify_trie_proof::, _, _, _>( &self.dip_commitment, self.dip_proof.blinded.as_slice(), &proof_leaves_key_value_pairs, diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 13aa7799f9..7968fddebc 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -20,7 +20,7 @@ use did::KeyIdOf; use frame_system::pallet_prelude::BlockNumberFor; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_consumer::{traits::IdentityProofVerifier, RuntimeCallOf}; -use pallet_dip_provider::IdentityCommitmentOf; +use pallet_dip_provider::traits::IdentityCommitmentGenerator; use pallet_web3_names::Web3NameOf; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; @@ -170,8 +170,13 @@ impl< RelaychainRuntime: frame_system::Config, RelaychainStateRootStore: GetWithArg, Result = Option>>, - KiltRuntime: pallet_dip_provider::Config + did::Config + pallet_web3_names::Config + pallet_did_lookup::Config, - IdentityCommitmentOf: Into, + KiltRuntime: frame_system::Config + + pallet_dip_provider::Config + + did::Config + + pallet_web3_names::Config + + pallet_did_lookup::Config, + KiltRuntime::IdentityCommitmentGenerator: + IdentityCommitmentGenerator, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, DidCallVerifier: DipCallOriginFilter< @@ -299,8 +304,13 @@ pub mod v0 { RelaychainRuntime: frame_system::Config, RelaychainStateRootStore: GetWithArg, Result = Option>>, - KiltRuntime: pallet_dip_provider::Config + did::Config + pallet_web3_names::Config + pallet_did_lookup::Config, - IdentityCommitmentOf: Into, + KiltRuntime: frame_system::Config + + pallet_dip_provider::Config + + did::Config + + pallet_web3_names::Config + + pallet_did_lookup::Config, + KiltRuntime::IdentityCommitmentGenerator: + IdentityCommitmentGenerator, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, DidCallVerifier: DipCallOriginFilter< diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index aec391b60e..cdb341892f 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -20,7 +20,7 @@ use did::KeyIdOf; use frame_system::pallet_prelude::BlockNumberFor; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_consumer::{traits::IdentityProofVerifier, RuntimeCallOf}; -use pallet_dip_provider::IdentityCommitmentOf; +use pallet_dip_provider::{traits::IdentityCommitmentGenerator, IdentityCommitmentOf}; use pallet_web3_names::Web3NameOf; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; @@ -176,8 +176,12 @@ impl< BlockNumberFor: Into + TryFrom, ConsumerBlockHashStore: GetWithArg, Result = Option>>, - KiltRuntime: pallet_dip_provider::Config + did::Config + pallet_web3_names::Config + pallet_did_lookup::Config, - IdentityCommitmentOf: Into, + KiltRuntime: frame_system::Config + + pallet_dip_provider::Config + + did::Config + + pallet_web3_names::Config + + pallet_did_lookup::Config, + KiltRuntime::IdentityCommitmentGenerator: IdentityCommitmentGenerator, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, DidCallVerifier: DipCallOriginFilter< @@ -364,7 +368,13 @@ pub mod v0 { BlockNumberFor: Into + TryFrom, ConsumerBlockHashStore: GetWithArg, Result = Option>>, - KiltRuntime: pallet_dip_provider::Config + did::Config + pallet_web3_names::Config + pallet_did_lookup::Config, + KiltRuntime: frame_system::Config + + pallet_dip_provider::Config + + did::Config + + pallet_web3_names::Config + + pallet_did_lookup::Config, + KiltRuntime::IdentityCommitmentGenerator: + IdentityCommitmentGenerator, IdentityCommitmentOf: Into, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, @@ -406,12 +416,12 @@ pub mod v0 { // 2. Verify parachain state is finalized by relay chain and fresh. let proof_without_relaychain = proof_without_header - .verify_provider_head_proof::>(KILT_PARA_ID) + .verify_provider_head_proof::>(KILT_PARA_ID) .map_err(DipRelaychainStateProofVerifierError::ProofVerification)?; // 3. Verify commitment is included in provider parachain state. let proof_without_parachain = proof_without_relaychain - .verify_dip_commitment_proof_for_subject::(subject) + .verify_dip_commitment_proof_for_subject::(subject) .map_err(DipRelaychainStateProofVerifierError::ProofVerification)?; // 4. Verify DIP Merkle proof. From d266720efc0d322d471af6b8c86aeaf4fb5ed1de Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 16 Jan 2024 15:21:30 +0100 Subject: [PATCH 25/45] Comments addressed --- crates/kilt-dip-primitives/src/merkle/v0.rs | 6 + .../src/verifier/parachain.rs | 59 ++++---- .../src/verifier/relaychain.rs | 134 ++++-------------- 3 files changed, 63 insertions(+), 136 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index 7af85b9b55..b5e884d892 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -325,6 +325,7 @@ impl< /// given para ID. /// /// The generic types indicate the following: + /// * `RelayHasher`: The head data hashing algorithm used by the relaychain. /// * `ProviderHeader`: The type of the parachain header to be revealed in /// the state proof. #[allow(clippy::type_complexity)] @@ -415,6 +416,11 @@ impl< { /// Verifies the head data of the state proof for the provider with the /// given para ID and relaychain state root. + /// + /// The generic types indicate the following: + /// * `RelayHasher`: The head data hashing algorithm used by the relaychain. + /// * `ProviderHeader`: The type of the parachain header to be revealed in + /// the state proof. #[allow(clippy::type_complexity)] pub fn verify_provider_head_proof_with_state_root( self, diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 7968fddebc..6c7b6c2e8a 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -82,34 +82,8 @@ where } } -/// Proof verifier configured given a specific KILT runtime implementation. -/// -/// The generic types -/// indicate the following: -/// * `RelaychainRuntime`: The relaychain runtime definition. -/// * `RelaychainStateRootStore`: A type providing state roots for relaychain -/// blocks. -/// * `KILT_PARA_ID`: The ID of the specific KILT parachain instance. -/// * `KiltRuntime`: A KILT runtime definition. -/// * `DidCallVerifier`: Logic to map `RuntimeCall`s to a specific DID key -/// relationship. This information is used once the Merkle proof is verified, -/// to filter only the revealed keys that match the provided relationship. -/// * `SignedExtra`: Any additional information that must be signed by the DID -/// subject in the cross-chain operation. -/// * `MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT`: The maximum number of leaves that -/// can be revealed as part of the parachain head storage proof. -/// * `MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE`: The maximum size of each leaf -/// revealed as part of the parachain head storage proof. -/// * `MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT`: The maximum number of leaves that -/// can be revealed as part of the DIP commitment storage proof. -/// * `MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE`: The maximum size of each leaf -/// revealed as part of the DIP commitment storage proof. -/// * `MAX_DID_MERKLE_PROOF_LEAVE_COUNT`: The maximum number of *blinded* leaves -/// that can be revealed as part of the DID Merkle proof. -/// * `MAX_DID_MERKLE_PROOF_LEAVE_SIZE`: The maximum size of each *blinded* leaf -/// revealed as part of the DID Merkle proof. -/// * `MAX_DID_MERKLE_PROOF_LEAVE_SIZE`: The maximum number of leaves that can -/// be revealed as part of the DID Merkle proof. +/// Versioned proof verifier. For version-specific description, refer to each +/// verifier's documentation. pub struct KiltVersionedParachainVerifier< RelaychainRuntime, RelaychainStateRootStore, @@ -244,6 +218,35 @@ pub mod v0 { use crate::merkle::v0::ParachainDipDidProof; + /// Proof verifier configured given a specific KILT runtime implementation. + /// + /// The generic types + /// indicate the following: + /// * `RelaychainRuntime`: The relaychain runtime definition. + /// * `RelaychainStateRootStore`: A type providing state roots for + /// relaychain blocks. + /// * `KILT_PARA_ID`: The ID of the specific KILT parachain instance. + /// * `KiltRuntime`: A KILT runtime definition. + /// * `DidCallVerifier`: Logic to map `RuntimeCall`s to a specific DID key + /// relationship. This information is used once the Merkle proof is + /// verified, to filter only the revealed keys that match the provided + /// relationship. + /// * `SignedExtra`: Any additional information that must be signed by the + /// DID subject in the cross-chain operation. + /// * `MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT`: The maximum number of leaves + /// that can be revealed as part of the parachain head storage proof. + /// * `MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE`: The maximum size of each leaf + /// revealed as part of the parachain head storage proof. + /// * `MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT`: The maximum number of leaves + /// that can be revealed as part of the DIP commitment storage proof. + /// * `MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE`: The maximum size of each leaf + /// revealed as part of the DIP commitment storage proof. + /// * `MAX_DID_MERKLE_PROOF_LEAVE_COUNT`: The maximum number of *blinded* + /// leaves that can be revealed as part of the DID Merkle proof. + /// * `MAX_DID_MERKLE_PROOF_LEAVE_SIZE`: The maximum size of each *blinded* + /// leaf revealed as part of the DID Merkle proof. + /// * `MAX_DID_MERKLE_PROOF_LEAVE_SIZE`: The maximum number of leaves that + /// can be revealed as part of the DID Merkle proof. pub struct ParachainVerifier< RelaychainRuntime, RelaychainStateRootStore, diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index cdb341892f..f5d2bc0bdb 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -83,50 +83,8 @@ where } } -/// Proof verifier configured given a specific KILT runtime implementation. -/// -/// A specialization of the -/// [`GenericVersionedRelaychainVerifier`] type, with -/// configurations derived from the provided KILT runtime. -/// -/// The generic types are the following: -/// * `KiltRuntime`: A KILT runtime definition. -/// * `KiltParachainId`: The ID of the specific KILT parachain instance. -/// * `RelayChainInfo`: The type providing information about the consumer -/// (relay)chain. -/// * `KiltDipMerkleHasher`: The hashing algorithm used by the KILT parachain -/// for the generation of the DIP identity commitment. -/// * `LocalDidCallVerifier`: Logic to map `RuntimeCall`s to a specific DID key -/// relationship. This information is used once the Merkle proof is verified, -/// to filter only the revealed keys that match the provided relationship. -/// * `MAX_REVEALED_KEYS_COUNT`: **OPTIONAL** Max number of DID keys that the -/// verifier will accept revealed as part of the DIP identity proof. It -/// defaults to **10**. -/// * `MAX_REVEALED_ACCOUNTS_COUNT`: **OPTIONAL** Max number of linked accounts -/// that the verifier will accept revealed as part of the DIP identity proof. -/// It defaults to **10**. -/// * `MAX_DID_SIGNATURE_DURATION`: **OPTIONAL** Max number of blocks a -/// cross-chain DID signature is considered fresh. It defaults to **50**. -/// -/// It specializes the [`GenericVersionedRelaychainVerifier`] -/// type by using the following types for its generics: -/// * `RelayChainInfo`: The provided `RelayChainInfo`. -/// * `ChildProviderParachainId`: The provided `KiltParachainId`. -/// * `ChildProviderStateInfo`: The -/// [`ProviderParachainStateInfoViaProviderPallet`] type configured with the -/// provided `KiltRuntime`. -/// * `ProviderDipMerkleHasher`: The provided `KiltDipMerkleHasher`. -/// * `ProviderDidKeyId`: The [`KeyIdOf`] type configured with the provided -/// `KiltRuntime`. -/// * `KiltAccountId`: The `KiltRuntime::AccountId` type. -/// * `KiltWeb3Name`: The `KiltRuntime::Web3Name` type. -/// * `KiltLinkableAccountId`: The [`LinkableAccountId`] type. -/// * `MAX_REVEALED_KEYS_COUNT`: The provided `MAX_REVEALED_KEYS_COUNT`. -/// * `MAX_REVEALED_ACCOUNTS_COUNT`: The provided `MAX_REVEALED_ACCOUNTS_COUNT`. -/// * `LocalContextProvider`: The [`FrameSystemDidSignatureContext`] type -/// configured with the provided `KiltRuntime` and -/// `MAX_DID_SIGNATURE_DURATION`. -/// * `LocalDidCallVerifier`: The provided `LocalDidCallVerifier`. +/// Versioned proof verifier. For version-specific description, refer to each +/// verifier's documentation. pub struct KiltVersionedRelaychainVerifier< ConsumerBlockHashStore, const KILT_PARA_ID: u32, @@ -248,74 +206,34 @@ pub mod v0 { use crate::RelayDipDidProof; - /// Generic proof verifier for KILT-specific DIP identity proofs coming from - /// a child provider running one of the available KILT runtimes. - /// The proof verification step is performed on every request, and this - /// specific verifier has no knowledge of caching or storing state about the - /// subject. It only takes the provided - /// `ConsumerRuntime::LocalIdentityInfo` and increases it if the proof is - /// successfully verified, to prevent replay attacks. If additional logic is - /// to be stored under the `ConsumerRuntime::LocalIdentityInfo` entry, a - /// different verifier or a wrapper around this verifier must be built. + /// Proof verifier configured given a specific KILT runtime implementation. /// - /// It expects the DIP proof to be a - /// [`VersionedRelaychainStateProof`], and returns - /// [`RevealedDidMerkleProofLeaves`] if the proof is successfully verified. - /// This information is then made availabe as an origin to the downstream - /// call dispatched. + /// The generic types are the following: /// - /// The verifier performs the following steps: - /// 1. Verifies the state proof about the state root of the relaychain block - /// at the provided height. The state root is retrieved from the provided - /// relaychain header, which is checked to be the header of a - /// previously-finalized relaychain block. - /// 2. Verifies the state proof about the DIP commitment value on the - /// provider parachain at the block finalized at the given relaychain - /// block, using the relay state root validated in the previous step. - /// 3. Verifies the DIP Merkle proof revealing parts of the subject's DID - /// Document against the retrieved DIP commitment validated in the - /// previous step. - /// 4. Verifies the cross-chain DID signature over the payload composed by - /// the SCALE-encoded tuple of `(C, D, S, B, G, E)`, with: - /// * `C`: The `RuntimeCall` to dispatch after performing DIP - /// verification. - /// * `D`: The local details associated to the DID subject as stored in - /// the [`pallet_dip_consumer`] `IdentityEntries` storage map. - /// * `S`: The tx submitter's address. - /// * `B`: The block number of the consumer chain provided in the - /// cross-chain DID signature. - /// * `G`: The genesis hash of the consumer chain. - /// * `E`: Any additional information provided by the - /// `LocalContextProvider` implementation. - /// The generic types - /// indicate the following: - /// * `RelayChainInfo`: The type providing information about the consumer - /// (relay)chain. - /// * `ChildProviderParachainId`: The parachain ID of the provider KILT - /// child parachain. - /// * `ChildProviderStateInfo`: The type providing storage and state - /// information about the provider KILT child parachain. - /// * `ProviderDipMerkleHasher`: The hashing algorithm used by the KILT - /// parachain for the generation of the DIP identity commitment. - /// * `ProviderDidKeyId`: The runtime type of a DID key ID as defined by the - /// KILT child parachain. - /// * `KiltAccountId`: The runtime type of an account ID as defined by the - /// KILT child parachain. - /// * `KiltWeb3Name`: The runtime type of a web3name as defined by the KILT - /// child parachain. - /// * `KiltLinkableAccountId`: The runtime type of a linked account ID as - /// defined by the KILT child parachain. - /// * `MAX_REVEALED_KEYS_COUNT`: Max number of DID keys that the verifier - /// will accept revealed as part of the DIP identity proof. - /// * `MAX_REVEALED_ACCOUNTS_COUNT`: Max number of linked accounts that the - /// verifier will accept revealed as part of the DIP identity proof. - /// * `LocalContextProvider`: The type providing context of the consumer - /// chain (e.g., current block number) for the sake of cross-chain DID - /// signature verification. - /// * `LocalDidCallVerifier`: Logic to map `RuntimeCall`s to a specific DID - /// key relationship. This information is used once the Merkle proof is + /// * `ConsumerBlockHashStore`: A type providing block hashes for the + /// relaychain blocks. + /// * `KILT_PARA_ID`: The ID of the specific KILT parachain instance. + /// * `KiltRuntime`: A KILT runtime definition. + /// * `DidCallVerifier`: Logic to map `RuntimeCall`s to a specific DID key + /// relationship. This information is used once the Merkle proof is /// verified, to filter only the revealed keys that match the provided /// relationship. + /// * `SignedExtra`: Any additional information that must be signed by the + /// DID subject in the cross-chain operation. + /// * `MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT`: The maximum number of leaves + /// that can be revealed as part of the parachain head storage proof. + /// * `MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE`: The maximum size of each leaf + /// revealed as part of the parachain head storage proof. + /// * `MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT`: The maximum number of leaves + /// that can be revealed as part of the DIP commitment storage proof. + /// * `MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE`: The maximum size of each leaf + /// revealed as part of the DIP commitment storage proof. + /// * `MAX_DID_MERKLE_PROOF_LEAVE_COUNT`: The maximum number of *blinded* + /// leaves that can be revealed as part of the DID Merkle proof. + /// * `MAX_DID_MERKLE_PROOF_LEAVE_SIZE`: The maximum size of each *blinded* + /// leaf revealed as part of the DID Merkle proof. + /// * `MAX_DID_MERKLE_PROOF_LEAVE_SIZE`: The maximum number of leaves that + /// can be revealed as part of the DID Merkle proof. pub struct RelaychainVerifier< ConsumerBlockHashStore, const KILT_PARA_ID: u32, From c59b30fd43832314e5ab5f614a6cfbff23c0786a Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Wed, 17 Jan 2024 09:10:27 +0100 Subject: [PATCH 26/45] Staging changes --- crates/kilt-dip-primitives/src/merkle/v0.rs | 223 +++++++++++++++++--- crates/kilt-dip-primitives/src/traits.rs | 12 ++ crates/kilt-dip-primitives/src/utils.rs | 63 +++++- 3 files changed, 262 insertions(+), 36 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index b5e884d892..f49e9b21c3 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -18,7 +18,7 @@ //! Module to deal with cross-chain Merkle proof as generated by the KILT chain. use did::{ - did_details::{DidPublicKey, DidPublicKeyDetails}, + did_details::{DidPublicKey, DidPublicKeyDetails, DidVerificationKey}, DidSignature, DidVerificationKeyRelationship, }; use frame_support::{ensure, RuntimeDebug}; @@ -36,9 +36,10 @@ use sp_trie::{verify_trie_proof, LayoutV1}; use crate::{ state_proofs::{verify_storage_value_proof, MerkleProofError}, - traits::GetWithArg, + traits::{BenchmarkDefault, GetWithArg}, utils::{ - calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key, OutputOf, + calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key, + BoundedBlindedValue, OutputOf, }, }; @@ -49,12 +50,32 @@ use crate::{ #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct ProviderHeadStateProof { pub(crate) relay_block_number: RelayBlockNumber, - pub(crate) proof: Vec>, + pub(crate) proof: BoundedBlindedValue, +} + +#[cfg(feature = "runtime-benchmarks")] +impl kilt_support::traits::GetWorstCase for ProviderHeadStateProof +where + RelayBlockNumber: Default, +{ + fn worst_case(context: Context) -> Self { + Self { + relay_block_number: RelayBlockNumber::default(), + proof: BoundedBlindedValue::worst_case(context), + } + } } /// The state proof for a DIP commitment. #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] -pub struct DipCommitmentStateProof(pub(crate) Vec>); +pub struct DipCommitmentStateProof(pub(crate) BoundedBlindedValue); + +#[cfg(feature = "runtime-benchmarks")] +impl kilt_support::traits::GetWorstCase for DipCommitmentStateProof { + fn worst_case(context: Context) -> Self { + Self(BoundedBlindedValue::worst_case(context)) + } +} /// The Merkle proof for a KILT DID. /// @@ -73,7 +94,7 @@ pub struct DidMerkleProof< ProviderWeb3Name, ProviderLinkableAccountId, > { - pub(crate) blinded: Vec>, + pub(crate) blinded: BoundedBlindedValue, pub(crate) revealed: Vec< RevealedDidMerkleProofLeaf< ProviderDidKeyId, @@ -89,7 +110,7 @@ impl { pub fn new( - blinded: Vec>, + blinded: BoundedBlindedValue, revealed: Vec< RevealedDidMerkleProofLeaf< ProviderDidKeyId, @@ -104,6 +125,36 @@ impl kilt_support::traits::GetWorstCase + for DidMerkleProof< + ProviderDidKeyId, + ProviderAccountId, + ProviderBlockNumber, + ProviderWeb3Name, + ProviderLinkableAccountId, + > where + ProviderDidKeyId: Default + Clone, + ProviderAccountId: Clone, + ProviderBlockNumber: Default + Clone, + ProviderWeb3Name: Clone, + ProviderLinkableAccountId: Clone, +{ + fn worst_case(context: Context) -> Self { + Self { + blinded: BoundedBlindedValue::worst_case(context), + revealed: sp_std::vec![RevealedDidMerkleProofLeaf::default(); 64], + } + } +} + /// A DID signature anchored to a specific block height. /// /// The generic types indicate the following: @@ -117,6 +168,20 @@ pub struct TimeBoundDidSignature { pub(crate) valid_until: BlockNumber, } +#[cfg(feature = "runtime-benchmarks")] +impl kilt_support::traits::GetWorstCase for TimeBoundDidSignature +where + DidSignature: kilt_support::traits::GetWorstCase, + BlockNumber: Default, +{ + fn worst_case(context: Context) -> Self { + Self { + signature: DidSignature::worst_case(context), + valid_until: BlockNumber::default(), + } + } +} + pub enum Error { InvalidRelayHeader, RelayBlockNotFound, @@ -395,6 +460,45 @@ pub struct ParachainDipDidProof< pub(crate) signature: TimeBoundDidSignature, } +#[cfg(feature = "runtime-benchmarks")] +impl< + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + Context, + > kilt_support::traits::GetWorstCase + for ParachainDipDidProof< + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + > where + RelayBlockNumber: Default, + KiltDidKeyId: Default + Clone, + KiltAccountId: Clone, + KiltBlockNumber: Default + Clone, + KiltWeb3Name: Clone, + KiltLinkableAccountId: Clone, + ConsumerBlockNumber: Default, + Context: Clone, +{ + fn worst_case(context: Context) -> Self { + Self { + provider_head_proof: ProviderHeadStateProof::worst_case(context.clone()), + dip_commitment_proof: DipCommitmentStateProof::worst_case(context.clone()), + dip_proof: DidMerkleProof::worst_case(context.clone()), + signature: TimeBoundDidSignature::worst_case(context), + } + } +} + impl< RelayBlockNumber, KiltDidKeyId, @@ -440,15 +544,26 @@ impl< > where RelayHasher: Hash, - ProviderHeader: Decode + HeaderT>, + ProviderHeader: Decode + HeaderT> + BenchmarkDefault, { let provider_head_storage_key = calculate_parachain_head_storage_key(provider_para_id); - let provider_header = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( - &provider_head_storage_key, - *relay_state_root, - self.provider_head_proof.proof, - ) - .map_err(Error::ParaHeadMerkleProof)?; + cfg_if::cfg_if! { + if #[cfg(feature = "runtime-benchmarks")] { + let provider_header = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( + &provider_head_storage_key, + *relay_state_root, + self.provider_head_proof.proof, + ) + .unwrap_or_default(); + } else { + let provider_header = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( + &provider_head_storage_key, + *relay_state_root, + self.provider_head_proof.proof, + ) + .map_err(Error::ParaHeadMerkleProof)?; + } + } Ok(DipDidProofWithoutRelayProof { state_root: *provider_header.state_root(), dip_commitment_proof: self.dip_commitment_proof, @@ -487,7 +602,7 @@ impl< where RelayHasher: Hash, StateRootStore: GetWithArg>>, - ProviderHeader: Decode + HeaderT>, + ProviderHeader: Decode + HeaderT> + BenchmarkDefault, { let relay_state_root = StateRootStore::get(&self.provider_head_proof.relay_block_number).ok_or(Error::RelayStateRootNotFound)?; @@ -577,15 +692,27 @@ impl< StateRoot: Ord, ParachainHasher: Hash, ProviderRuntime: pallet_dip_provider::Config, + IdentityCommitmentOf: BenchmarkDefault, { let dip_commitment_storage_key = calculate_dip_identity_commitment_storage_key_for_runtime::(subject, 0); - let dip_commitment = verify_storage_value_proof::<_, ParachainHasher, IdentityCommitmentOf>( - &dip_commitment_storage_key, - self.state_root, - self.dip_commitment_proof.0, - ) - .map_err(Error::DipCommitmentMerkleProof)?; + cfg_if::cfg_if! { + if #[cfg(feature = "runtime-benchmarks")] { + let dip_commitment = verify_storage_value_proof::<_, ParachainHasher, IdentityCommitmentOf>( + &dip_commitment_storage_key, + self.state_root, + self.dip_commitment_proof.0, + ) + .unwrap_or_default(); + } else { + let dip_commitment = verify_storage_value_proof::<_, ParachainHasher, IdentityCommitmentOf>( + &dip_commitment_storage_key, + self.state_root, + self.dip_commitment_proof.0, + ) + .map_err(Error::DipCommitmentMerkleProof)?; + } + } Ok(DipDidProofWithVerifiedCommitment { dip_commitment, dip_proof: self.dip_proof, @@ -679,12 +806,22 @@ impl< .map(|revealed_leaf| (revealed_leaf.encoded_key(), Some(revealed_leaf.encoded_value()))) .collect(); - verify_trie_proof::, _, _, _>( - &self.dip_commitment, - self.dip_proof.blinded.as_slice(), - &proof_leaves_key_value_pairs, - ) - .map_err(|_| Error::InvalidDidMerkleProof)?; + cfg_if::cfg_if! { + if #[cfg(feature = "runtime-benchmarks")] { + verify_trie_proof::, _, _, _>( + &self.dip_commitment, + self.dip_proof.blinded.as_slice(), + &proof_leaves_key_value_pairs, + ) + .map_err(|_| Error::InvalidDidMerkleProof)?; + } else { + let _ = verify_trie_proof::, _, _, _>( + &self.dip_commitment, + self.dip_proof.blinded.as_slice(), + &proof_leaves_key_value_pairs, + ); + } + } Ok(DipDetailsAndUnverifiedDidSignatureTime { revealed_leaves: self.dip_proof.revealed, @@ -747,7 +884,13 @@ impl, Error, > { - ensure!(self.signature.valid_until >= *block_number, Error::InvalidSignatureTime); + cfg_if::cfg_if! { + if #[cfg(feature = "runtime-benchmarks")] { + let _ = self.signature.valid_until >= *block_number; + } else { + ensure!(self.signature.valid_until >= *block_number, Error::InvalidSignatureTime); + } + } Ok(DipDetailsAndUnverifiedDidSignaturePayload { revealed_leaves: self.revealed_leaves, signature: self.signature.signature, @@ -788,7 +931,9 @@ impl + > where + KiltDidKeyId: BenchmarkDefault, + KiltBlockNumber: BenchmarkDefault, { /// Iterates over the revealed DID leafs to find the one that generated a /// valid signature for the provided payload. @@ -806,7 +951,7 @@ impl Self::Result {} } + +// Marker trait that requires a type to implement `Default` only for benchmarks. +// Avoids code duplication. +#[cfg(not(feature = "runtime-benchmarks"))] +pub trait BenchmarkDefault {} +#[cfg(not(feature = "runtime-benchmarks"))] +impl BenchmarkDefault for T {} + +#[cfg(feature = "runtime-benchmarks")] +pub trait BenchmarkDefault: Default {} +#[cfg(feature = "runtime-benchmarks")] +impl BenchmarkDefault for T {} diff --git a/crates/kilt-dip-primitives/src/utils.rs b/crates/kilt-dip-primitives/src/utils.rs index 2fa15d61d6..0296b3c12c 100644 --- a/crates/kilt-dip-primitives/src/utils.rs +++ b/crates/kilt-dip-primitives/src/utils.rs @@ -17,12 +17,71 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org use pallet_dip_provider::IdentityCommitmentVersion; -use parity_scale_codec::Encode; -use sp_core::storage::StorageKey; +use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_core::{storage::StorageKey, RuntimeDebug}; +use sp_std::vec::Vec; /// The output of a type implementing the [`sp_runtime::traits::Hash`] trait. pub type OutputOf = ::Output; +/// The vector of vectors that implements a statically-configured maximum length +/// without requiring const generics, used in benchmarking worst cases. +#[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, Clone)] +pub struct BoundedBlindedValue(Vec>); + +impl BoundedBlindedValue { + pub fn into_inner(self) -> Vec> { + self.0 + } +} + +impl From for BoundedBlindedValue +where + C: Iterator>, +{ + fn from(value: C) -> Self { + Self(value.into_iter().collect()) + } +} + +impl sp_std::ops::Deref for BoundedBlindedValue { + type Target = Vec>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl IntoIterator for BoundedBlindedValue { + type IntoIter = > as IntoIterator>::IntoIter; + type Item = > as IntoIterator>::Item; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +#[cfg(feature = "runtime-benchmarks")] +impl kilt_support::traits::GetWorstCase for BoundedBlindedValue +where + T: Default + Clone, +{ + fn worst_case(_context: Context) -> Self { + Self(sp_std::vec![sp_std::vec![T::default(); 128]; 64]) + } +} + +#[cfg(feature = "runtime-benchmarks")] +impl Default for BoundedBlindedValue +where + T: Default + Clone, +{ + fn default() -> Self { + Self(sp_std::vec![sp_std::vec![T::default(); 128]; 64]) + } +} + pub(crate) fn calculate_parachain_head_storage_key(para_id: u32) -> StorageKey { StorageKey( [ From 82160d2fef2728b188af2e1b8a9d9d7a174fee7d Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 23 Jan 2024 10:57:34 +0100 Subject: [PATCH 27/45] Primitives compiling again --- crates/kilt-dip-primitives/src/lib.rs | 6 + crates/kilt-dip-primitives/src/merkle/mod.rs | 2 - crates/kilt-dip-primitives/src/merkle/v0.rs | 216 ++++++++++++------ .../src/state_proofs/mod.rs | 2 - .../src/verifier/parachain.rs | 64 +++++- .../src/verifier/relaychain.rs | 20 +- 6 files changed, 221 insertions(+), 89 deletions(-) diff --git a/crates/kilt-dip-primitives/src/lib.rs b/crates/kilt-dip-primitives/src/lib.rs index 651f2958a2..30623e96ca 100644 --- a/crates/kilt-dip-primitives/src/lib.rs +++ b/crates/kilt-dip-primitives/src/lib.rs @@ -26,10 +26,16 @@ #![cfg_attr(not(feature = "std"), no_std)] +/// Module to deal with cross-chain Merkle proof as generated by the KILT chain. pub mod merkle; +/// Module to deal with cross-chain state proofs. pub mod state_proofs; +/// Collection of traits used throughout the crate and useful for both providers +/// and consumers. pub mod traits; pub mod utils; +/// Verifier module containing types that implement the verifier component to be +/// deployed both on a sibling parachain and on a parent relaychain. pub mod verifier; pub use merkle::latest::*; diff --git a/crates/kilt-dip-primitives/src/merkle/mod.rs b/crates/kilt-dip-primitives/src/merkle/mod.rs index 2a30d0bee4..552a922f8b 100644 --- a/crates/kilt-dip-primitives/src/merkle/mod.rs +++ b/crates/kilt-dip-primitives/src/merkle/mod.rs @@ -16,8 +16,6 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -//! Module to deal with cross-chain Merkle proof as generated by the KILT chain. - pub mod v0; pub mod latest { diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index f49e9b21c3..058513b6b0 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -18,18 +18,18 @@ //! Module to deal with cross-chain Merkle proof as generated by the KILT chain. use did::{ - did_details::{DidPublicKey, DidPublicKeyDetails, DidVerificationKey}, + did_details::{DidPublicKey, DidPublicKeyDetails}, DidSignature, DidVerificationKeyRelationship, }; use frame_support::{ensure, RuntimeDebug}; use pallet_dip_provider::IdentityCommitmentOf; use parity_scale_codec::{Codec, Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; -use sp_core::U256; +use sp_core::{ConstU32, U256}; use sp_runtime::{ generic::Header, traits::{AtLeast32BitUnsigned, Hash, Header as HeaderT, MaybeDisplay, Member}, - SaturatedConversion, + BoundedVec, SaturatedConversion, }; use sp_std::vec::Vec; use sp_trie::{verify_trie_proof, LayoutV1}; @@ -187,6 +187,7 @@ pub enum Error { RelayBlockNotFound, RelayStateRootNotFound, InvalidDidMerkleProof, + TooManyLeavesRevealed, InvalidSignatureTime, InvalidDidKeyRevealed, ParaHeadMerkleProof(MerkleProofError), @@ -201,8 +202,9 @@ impl From for u8 { Error::RelayBlockNotFound => 2, Error::RelayStateRootNotFound => 3, Error::InvalidDidMerkleProof => 4, - Error::InvalidSignatureTime => 5, - Error::InvalidDidKeyRevealed => 6, + Error::TooManyLeavesRevealed => 5, + Error::InvalidSignatureTime => 6, + Error::InvalidDidKeyRevealed => 7, Error::ParaHeadMerkleProof(error) => match error { MerkleProofError::InvalidProof => 11, MerkleProofError::RequiredLeafNotRevealed => 12, @@ -411,7 +413,7 @@ impl< > where RelayHasher: Hash, - ProviderHeader: Decode + HeaderT>, + ProviderHeader: Decode + HeaderT> + BenchmarkDefault, { let parachain_dip_proof = ParachainDipDidProof { provider_head_proof: self.provider_head_proof, @@ -547,21 +549,16 @@ impl< ProviderHeader: Decode + HeaderT> + BenchmarkDefault, { let provider_head_storage_key = calculate_parachain_head_storage_key(provider_para_id); + let provider_header_result = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( + &provider_head_storage_key, + *relay_state_root, + self.provider_head_proof.proof, + ); cfg_if::cfg_if! { if #[cfg(feature = "runtime-benchmarks")] { - let provider_header = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( - &provider_head_storage_key, - *relay_state_root, - self.provider_head_proof.proof, - ) - .unwrap_or_default(); + let provider_header = provider_header_result.unwrap_or_default(); } else { - let provider_header = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( - &provider_head_storage_key, - *relay_state_root, - self.provider_head_proof.proof, - ) - .map_err(Error::ParaHeadMerkleProof)?; + let provider_header = provider_header_result.map_err(Error::ParaHeadMerkleProof)?; } } Ok(DipDidProofWithoutRelayProof { @@ -696,21 +693,17 @@ impl< { let dip_commitment_storage_key = calculate_dip_identity_commitment_storage_key_for_runtime::(subject, 0); + let dip_commitment_result = + verify_storage_value_proof::<_, ParachainHasher, IdentityCommitmentOf>( + &dip_commitment_storage_key, + self.state_root, + self.dip_commitment_proof.0, + ); cfg_if::cfg_if! { if #[cfg(feature = "runtime-benchmarks")] { - let dip_commitment = verify_storage_value_proof::<_, ParachainHasher, IdentityCommitmentOf>( - &dip_commitment_storage_key, - self.state_root, - self.dip_commitment_proof.0, - ) - .unwrap_or_default(); + let dip_commitment = dip_commitment_result.unwrap_or_default(); } else { - let dip_commitment = verify_storage_value_proof::<_, ParachainHasher, IdentityCommitmentOf>( - &dip_commitment_storage_key, - self.state_root, - self.dip_commitment_proof.0, - ) - .map_err(Error::DipCommitmentMerkleProof)?; + let dip_commitment = dip_commitment_result.map_err(Error::DipCommitmentMerkleProof)?; } } Ok(DipDidProofWithVerifiedCommitment { @@ -782,7 +775,9 @@ impl< /// The generic types indicate the following: /// * `DidMerkleHasher`: The hashing algorithm used to merkleize the DID /// details. - pub fn verify_dip_proof( + /// * `MAX_REVEALED_LEAVES_COUNT`: The maximum number of leaves revealable + /// in the proof. + pub fn verify_dip_proof( self, ) -> Result< DipDetailsAndUnverifiedDidSignatureTime< @@ -792,39 +787,45 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, + MAX_REVEALED_LEAVES_COUNT, >, Error, > where DidMerkleHasher: Hash, { - let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = self + let mut max_revealed_leaves_iter = self .dip_proof .revealed .iter() + .take(MAX_REVEALED_LEAVES_COUNT.saturated_into()); + // If more than `max_revealed_leaves_count` are revealed, return an error. + ensure!(max_revealed_leaves_iter.next().is_none(), Error::TooManyLeavesRevealed); + + let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = max_revealed_leaves_iter .by_ref() .map(|revealed_leaf| (revealed_leaf.encoded_key(), Some(revealed_leaf.encoded_value()))) .collect(); + let proof_verification_result = verify_trie_proof::, _, _, _>( + &self.dip_commitment, + self.dip_proof.blinded.as_slice(), + &proof_leaves_key_value_pairs, + ); cfg_if::cfg_if! { if #[cfg(feature = "runtime-benchmarks")] { - verify_trie_proof::, _, _, _>( - &self.dip_commitment, - self.dip_proof.blinded.as_slice(), - &proof_leaves_key_value_pairs, - ) - .map_err(|_| Error::InvalidDidMerkleProof)?; + proof_verification_result.map_err(|_| Error::InvalidDidMerkleProof)?; } else { - let _ = verify_trie_proof::, _, _, _>( - &self.dip_commitment, - self.dip_proof.blinded.as_slice(), - &proof_leaves_key_value_pairs, - ); + drop(proof_verification_result); } } + let revealed_leaves = BoundedVec::try_from(self.dip_proof.revealed).map_err(|_| { + log::error!("Should not fail to construct BoundedVec since bounds were checked before."); + Error::Internal + })?; Ok(DipDetailsAndUnverifiedDidSignatureTime { - revealed_leaves: self.dip_proof.revealed, + revealed_leaves, signature: self.signature, }) } @@ -842,6 +843,8 @@ impl< /// KILT chain. /// * `ConsumerBlockNumber`: The `BlockNumber` definition of the consumer /// parachain. +/// * `MAX_REVEALED_LEAVES_COUNT`: The maximum number of leaves revealable in +/// the proof. pub struct DipDetailsAndUnverifiedDidSignatureTime< KiltDidKeyId, KiltAccountId, @@ -849,16 +852,26 @@ pub struct DipDetailsAndUnverifiedDidSignatureTime< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, + const MAX_REVEALED_LEAVES_COUNT: u32, > { /// The parts of the subject's DID details revealed in the DIP proof. - pub(crate) revealed_leaves: Vec< + pub(crate) revealed_leaves: BoundedVec< RevealedDidMerkleProofLeaf, + ConstU32, >, /// The cross-chain DID signature. pub(crate) signature: TimeBoundDidSignature, } -impl +impl< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + const MAX_REVEALED_LEAVES_COUNT: u32, + > DipDetailsAndUnverifiedDidSignatureTime< KiltDidKeyId, KiltAccountId, @@ -866,6 +879,7 @@ impl where ConsumerBlockNumber: PartialOrd, { @@ -881,6 +895,7 @@ impl, Error, > { @@ -888,7 +903,7 @@ impl= *block_number; } else { - ensure!(self.signature.valid_until >= *block_number, Error::InvalidSignatureTime); + frame_support::ensure!(self.signature.valid_until >= *block_number, Error::InvalidSignatureTime); } } Ok(DipDetailsAndUnverifiedDidSignaturePayload { @@ -909,28 +924,40 @@ impl { /// The parts of the subject's DID details revealed in the DIP proof. - pub(crate) revealed_leaves: Vec< + pub(crate) revealed_leaves: BoundedVec< RevealedDidMerkleProofLeaf, + ConstU32, >, /// The cross-chain DID signature without time information. pub(crate) signature: DidSignature, } -impl +impl< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + const MAX_REVEALED_LEAVES_COUNT: u32, + > DipDetailsAndUnverifiedDidSignaturePayload< KiltDidKeyId, KiltAccountId, KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, + MAX_REVEALED_LEAVES_COUNT, > where KiltDidKeyId: BenchmarkDefault, KiltBlockNumber: BenchmarkDefault, @@ -940,8 +967,17 @@ impl Result, Error> - { + ) -> Result< + DipVerifiedInfo< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_REVEALED_LEAVES_COUNT, + >, + Error, + > { let revealed_verification_keys = self.revealed_leaves.iter().filter(|leaf| { matches!( leaf, @@ -951,7 +987,7 @@ impl { +pub struct DipVerifiedInfo< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + const MAX_REVEALED_LEAVES_COUNT: u32, +> { /// The parts of the subject's DID details revealed in the DIP proof. - revealed_leaves: Vec< + revealed_leaves: BoundedVec< RevealedDidMerkleProofLeaf, + ConstU32, >, /// The index of the signing leaf from the vector above, signing_leaf_index: u32, } -impl - DipVerifiedInfo +impl< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + const MAX_REVEALED_LEAVES_COUNT: u32, + > + DipVerifiedInfo< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_REVEALED_LEAVES_COUNT, + > { /// Returns an iterator over the revealed DID leaves. pub fn iter_leaves( @@ -1020,9 +1089,14 @@ impl Result<&RevealedDidKey, Error> { - let RevealedDidMerkleProofLeaf::DidKey(did_key) = - &self.revealed_leaves[usize::saturated_from(self.signing_leaf_index)] - else { + let leaf = &self + .revealed_leaves + .get(usize::saturated_from(self.signing_leaf_index)) + .ok_or_else(|| { + log::error!("Should never fail to retrieve the signing leaf."); + Error::Internal + })?; + let RevealedDidMerkleProofLeaf::DidKey(did_key) = leaf else { log::error!("Should never fail to convert the signing leaf to a DID Key leaf."); return Err(Error::Internal); }; diff --git a/crates/kilt-dip-primitives/src/state_proofs/mod.rs b/crates/kilt-dip-primitives/src/state_proofs/mod.rs index 31f452fde7..84c6492547 100644 --- a/crates/kilt-dip-primitives/src/state_proofs/mod.rs +++ b/crates/kilt-dip-primitives/src/state_proofs/mod.rs @@ -16,8 +16,6 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org -//! Module to deal with cross-chain state proofs. - use parity_scale_codec::Decode; use sp_runtime::traits::Hash; use sp_std::vec::Vec; diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 6c7b6c2e8a..1f3533f17e 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -17,7 +17,7 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org use did::KeyIdOf; -use frame_system::pallet_prelude::BlockNumberFor; +use frame_system::pallet_prelude::{BlockNumberFor, HeaderFor}; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_consumer::{traits::IdentityProofVerifier, RuntimeCallOf}; use pallet_dip_provider::traits::IdentityCommitmentGenerator; @@ -29,7 +29,7 @@ use sp_std::marker::PhantomData; use crate::{ merkle::v0::RevealedDidKey, - traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, + traits::{BenchmarkDefault, DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, DipVerifiedInfo, Error, }; @@ -63,6 +63,7 @@ pub enum VersionedDipParachainStateProof< pub enum DipParachainStateProofVerifierError { UnsupportedVersion, + ProofComponentTooLarge(u8), ProofVerification(Error), DidOriginError(DidOriginError), Internal, @@ -75,8 +76,13 @@ where fn from(value: DipParachainStateProofVerifierError) -> Self { match value { DipParachainStateProofVerifierError::UnsupportedVersion => 1, - DipParachainStateProofVerifierError::ProofVerification(error) => u8::MAX as u16 + u8::from(error) as u16, - DipParachainStateProofVerifierError::DidOriginError(error) => u8::MAX as u16 * 2 + error.into() as u16, + DipParachainStateProofVerifierError::ProofComponentTooLarge(component_id) => { + u8::MAX as u16 + component_id as u16 + } + DipParachainStateProofVerifierError::ProofVerification(error) => { + u8::MAX as u16 * 2 + u8::from(error) as u16 + } + DipParachainStateProofVerifierError::DidOriginError(error) => u8::MAX as u16 * 3 + error.into() as u16, DipParachainStateProofVerifierError::Internal => u16::MAX, } } @@ -151,6 +157,7 @@ impl< + pallet_did_lookup::Config, KiltRuntime::IdentityCommitmentGenerator: IdentityCommitmentGenerator, + HeaderFor: BenchmarkDefault, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, DidCallVerifier: DipCallOriginFilter< @@ -175,6 +182,7 @@ impl< BlockNumberFor, Web3NameOf, LinkableAccountId, + MAX_DID_MERKLE_LEAVES_REVEALED, >; fn verify_proof_for_call_against_details( @@ -213,8 +221,8 @@ impl< pub mod v0 { use super::*; - use frame_system::pallet_prelude::HeaderFor; - use sp_runtime::traits::Zero; + use frame_support::ensure; + use sp_runtime::{traits::Zero, SaturatedConversion}; use crate::merkle::v0::ParachainDipDidProof; @@ -245,7 +253,7 @@ pub mod v0 { /// leaves that can be revealed as part of the DID Merkle proof. /// * `MAX_DID_MERKLE_PROOF_LEAVE_SIZE`: The maximum size of each *blinded* /// leaf revealed as part of the DID Merkle proof. - /// * `MAX_DID_MERKLE_PROOF_LEAVE_SIZE`: The maximum number of leaves that + /// * `MAX_DID_MERKLE_LEAVES_REVEALED`: The maximum number of leaves that /// can be revealed as part of the DID Merkle proof. pub struct ParachainVerifier< RelaychainRuntime, @@ -314,6 +322,7 @@ pub mod v0 { + pallet_did_lookup::Config, KiltRuntime::IdentityCommitmentGenerator: IdentityCommitmentGenerator, + HeaderFor: BenchmarkDefault, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, DidCallVerifier: DipCallOriginFilter< @@ -339,6 +348,7 @@ pub mod v0 { BlockNumberFor, Web3NameOf, LinkableAccountId, + MAX_DID_MERKLE_LEAVES_REVEALED, >; fn verify_proof_for_call_against_details( @@ -349,7 +359,18 @@ pub mod v0 { proof: Self::Proof, ) -> Result { // 1. Verify parachain state is finalized by relay chain and fresh. - // TODO: Enforce limits passed by the const generics for each step. + ensure!( + proof.provider_head_proof.proof.len() <= MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT.saturated_into(), + DipParachainStateProofVerifierError::ProofComponentTooLarge(0) + ); + ensure!( + proof + .provider_head_proof + .proof + .iter() + .all(|l| l.len() <= MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE.saturated_into()), + DipParachainStateProofVerifierError::ProofComponentTooLarge(1) + ); let proof_without_relaychain = proof .verify_provider_head_proof::>( KILT_PARA_ID, @@ -357,13 +378,38 @@ pub mod v0 { .map_err(DipParachainStateProofVerifierError::ProofVerification)?; // 2. Verify commitment is included in provider parachain state. + ensure!( + proof_without_relaychain.dip_commitment_proof.0.len() + <= MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT.saturated_into(), + DipParachainStateProofVerifierError::ProofComponentTooLarge(2) + ); + ensure!( + proof_without_relaychain + .dip_commitment_proof + .0 + .iter() + .all(|l| l.len() <= MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE.saturated_into()), + DipParachainStateProofVerifierError::ProofComponentTooLarge(3) + ); let proof_without_parachain = proof_without_relaychain .verify_dip_commitment_proof_for_subject::(subject) .map_err(DipParachainStateProofVerifierError::ProofVerification)?; // 3. Verify DIP Merkle proof. + ensure!( + proof_without_parachain.dip_proof.blinded.len() <= MAX_DID_MERKLE_PROOF_LEAVE_COUNT.saturated_into(), + DipParachainStateProofVerifierError::ProofComponentTooLarge(4) + ); + ensure!( + proof_without_parachain + .dip_proof + .blinded + .iter() + .all(|l| l.len() <= MAX_DID_MERKLE_PROOF_LEAVE_SIZE.saturated_into()), + DipParachainStateProofVerifierError::ProofComponentTooLarge(5) + ); let proof_without_dip_merkle = proof_without_parachain - .verify_dip_proof::() + .verify_dip_proof::() .map_err(DipParachainStateProofVerifierError::ProofVerification)?; // 4. Verify call is signed by one of the DID keys revealed in the proof diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index f5d2bc0bdb..45f914a22f 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -17,7 +17,7 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org use did::KeyIdOf; -use frame_system::pallet_prelude::BlockNumberFor; +use frame_system::pallet_prelude::{BlockNumberFor, HeaderFor}; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_consumer::{traits::IdentityProofVerifier, RuntimeCallOf}; use pallet_dip_provider::{traits::IdentityCommitmentGenerator, IdentityCommitmentOf}; @@ -30,7 +30,7 @@ use sp_std::marker::PhantomData; use crate::{ merkle::v0::RevealedDidKey, - traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, + traits::{BenchmarkDefault, DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, DipVerifiedInfo, Error, }; @@ -64,6 +64,7 @@ pub enum VersionedRelaychainStateProof< pub enum DipRelaychainStateProofVerifierError { UnsupportedVersion, + ProofComponentTooLarge(u8), ProofVerification(Error), DidOriginError(DidOriginError), Internal, @@ -76,8 +77,13 @@ where fn from(value: DipRelaychainStateProofVerifierError) -> Self { match value { DipRelaychainStateProofVerifierError::UnsupportedVersion => 1, - DipRelaychainStateProofVerifierError::ProofVerification(error) => u8::MAX as u16 + u8::from(error) as u16, - DipRelaychainStateProofVerifierError::DidOriginError(error) => u8::MAX as u16 * 2 + error.into() as u16, + DipRelaychainStateProofVerifierError::ProofComponentTooLarge(component_id) => { + u8::MAX as u16 + component_id as u16 + } + DipRelaychainStateProofVerifierError::ProofVerification(error) => { + u8::MAX as u16 * 2 + u8::from(error) as u16 + } + DipRelaychainStateProofVerifierError::DidOriginError(error) => u8::MAX as u16 * 3 + error.into() as u16, DipRelaychainStateProofVerifierError::Internal => u16::MAX, } } @@ -140,6 +146,7 @@ impl< + pallet_web3_names::Config + pallet_did_lookup::Config, KiltRuntime::IdentityCommitmentGenerator: IdentityCommitmentGenerator, + HeaderFor: BenchmarkDefault, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, DidCallVerifier: DipCallOriginFilter< @@ -164,6 +171,7 @@ impl< BlockNumberFor, Web3NameOf, LinkableAccountId, + MAX_DID_MERKLE_LEAVES_REVEALED, >; fn verify_proof_for_call_against_details( @@ -293,6 +301,7 @@ pub mod v0 { + pallet_did_lookup::Config, KiltRuntime::IdentityCommitmentGenerator: IdentityCommitmentGenerator, + HeaderFor: BenchmarkDefault, IdentityCommitmentOf: Into, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, @@ -318,6 +327,7 @@ pub mod v0 { BlockNumberFor, Web3NameOf, LinkableAccountId, + MAX_DID_MERKLE_LEAVES_REVEALED, >; fn verify_proof_for_call_against_details( @@ -344,7 +354,7 @@ pub mod v0 { // 4. Verify DIP Merkle proof. let proof_without_dip_merkle = proof_without_parachain - .verify_dip_proof::() + .verify_dip_proof::() .map_err(DipRelaychainStateProofVerifierError::ProofVerification)?; // 5. Verify call is signed by one of the DID keys revealed in the proof From 14e5a532abdc3e9834ad71b5cb7a8d68cbdf3a3d Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 23 Jan 2024 11:09:05 +0100 Subject: [PATCH 28/45] Runtime common compiling --- runtimes/common/src/dip/did.rs | 2 +- runtimes/common/src/dip/merkle.rs | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/runtimes/common/src/dip/did.rs b/runtimes/common/src/dip/did.rs index 55c31bd7e9..fe3297c7c3 100644 --- a/runtimes/common/src/dip/did.rs +++ b/runtimes/common/src/dip/did.rs @@ -19,7 +19,7 @@ use did::did_details::DidDetails; use frame_support::ensure; use frame_system::pallet_prelude::BlockNumberFor; -use kilt_dip_primitives::merkle::RevealedWeb3Name; +use kilt_dip_primitives::RevealedWeb3Name; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_provider::traits::IdentityProvider; use parity_scale_codec::{Decode, Encode}; diff --git a/runtimes/common/src/dip/merkle.rs b/runtimes/common/src/dip/merkle.rs index 38bdd67a20..6f99ceec58 100644 --- a/runtimes/common/src/dip/merkle.rs +++ b/runtimes/common/src/dip/merkle.rs @@ -186,11 +186,8 @@ pub mod v0 { fn get_linked_account_leaves( linked_accounts: &[LinkableAccountId], - ) -> impl Iterator> { - let leaves = linked_accounts - .iter() - .map(|linked_account| RevealedAccountId(linked_account.clone())); - leaves.collect::>().into_iter() + ) -> impl Iterator> + '_ { + linked_accounts.iter().cloned().map(RevealedAccountId) } fn get_web3name_leaf( @@ -244,7 +241,7 @@ pub mod v0 { let linked_accounts = linked_accounts.map(RevealedDidMerkleProofLeaf::from); let web3_names = web3_name .map(|n| vec![n]) - .unwrap_or(vec![]) + .unwrap_or_default() .into_iter() .map(RevealedDidMerkleProofLeaf::from); @@ -348,7 +345,7 @@ pub mod v0 { Ok(CompleteMerkleProof { root, - proof: DidMerkleProofOf::::new(proof, leaves), + proof: DidMerkleProofOf::::new(proof.into_iter().into(), leaves), }) } From 51d45700c8fcc6e02e2129135544db29b480a176 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 23 Jan 2024 11:30:36 +0100 Subject: [PATCH 29/45] Project compiling without benchmarking feature --- crates/kilt-dip-primitives/src/merkle/v0.rs | 8 ++++++-- runtimes/common/src/dip/merkle.rs | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index 058513b6b0..537f7629c1 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -1010,7 +1010,7 @@ impl< } else { cfg_if::cfg_if! { if #[cfg(feature = "runtime-benchmarks")] { - let default_keys = vec![ + let default_keys = sp_std::vec![ RevealedDidKey { id: KiltDidKeyId::default(), details: DidPublicKeyDetails { @@ -1019,7 +1019,11 @@ impl< }, relationship: DidVerificationKeyRelationship::Authentication.into() }.into()]; - (default_keys, 0u32) + let bounded_keys = default_keys.try_into().map_err(|_| { + log::error!("Should not fail to convert single element to a BoundedVec."); + Error::Internal + })?; + (bounded_keys, 0u32) } else { return Err(Error::InvalidDidKeyRevealed); } diff --git a/runtimes/common/src/dip/merkle.rs b/runtimes/common/src/dip/merkle.rs index 6f99ceec58..5a0845d3a0 100644 --- a/runtimes/common/src/dip/merkle.rs +++ b/runtimes/common/src/dip/merkle.rs @@ -80,6 +80,7 @@ pub mod v0 { DidKeyRelationship, RevealedAccountId, RevealedDidKey, RevealedDidMerkleProofLeaf, RevealedWeb3Name, }; use pallet_web3_names::Web3NameOf; + use sp_std::vec; use crate::dip::did::Web3OwnershipOf; From dc271c71b6ee7a1b9512cced05d657312399c57c Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Tue, 23 Jan 2024 13:18:04 +0100 Subject: [PATCH 30/45] Project compiling with all features enabled --- crates/kilt-dip-primitives/src/merkle/v0.rs | 72 +++++++++++++------ .../src/verifier/parachain.rs | 42 +++++++++-- .../src/verifier/relaychain.rs | 6 +- 3 files changed, 91 insertions(+), 29 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index 537f7629c1..fb8c09bf86 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -386,7 +386,8 @@ impl< KiltBlockNumber, KiltWeb3Name, KiltLinkableAccountId, - > + > where + KiltBlockNumber: BenchmarkDefault, { /// Verifies the head data of the state proof for the provider with the /// given para ID. @@ -413,7 +414,7 @@ impl< > where RelayHasher: Hash, - ProviderHeader: Decode + HeaderT> + BenchmarkDefault, + ProviderHeader: Decode + HeaderT, Number = KiltBlockNumber>, { let parachain_dip_proof = ParachainDipDidProof { provider_head_proof: self.provider_head_proof, @@ -518,7 +519,8 @@ impl< KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, - > + > where + KiltBlockNumber: BenchmarkDefault, { /// Verifies the head data of the state proof for the provider with the /// given para ID and relaychain state root. @@ -546,7 +548,7 @@ impl< > where RelayHasher: Hash, - ProviderHeader: Decode + HeaderT> + BenchmarkDefault, + ProviderHeader: Decode + HeaderT, Number = KiltBlockNumber>, { let provider_head_storage_key = calculate_parachain_head_storage_key(provider_para_id); let provider_header_result = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( @@ -556,7 +558,7 @@ impl< ); cfg_if::cfg_if! { if #[cfg(feature = "runtime-benchmarks")] { - let provider_header = provider_header_result.unwrap_or_default(); + let provider_header = provider_header_result.unwrap_or_else(|_| ProviderHeader::new(::Number::default(), ::Hash::default(), ::Hash::default(), ::Hash::default(), sp_runtime::Digest::default())); } else { let provider_header = provider_header_result.map_err(Error::ParaHeadMerkleProof)?; } @@ -599,7 +601,7 @@ impl< where RelayHasher: Hash, StateRootStore: GetWithArg>>, - ProviderHeader: Decode + HeaderT> + BenchmarkDefault, + ProviderHeader: Decode + HeaderT, Number = KiltBlockNumber>, { let relay_state_root = StateRootStore::get(&self.provider_head_proof.relay_block_number).ok_or(Error::RelayStateRootNotFound)?; @@ -1010,20 +1012,7 @@ impl< } else { cfg_if::cfg_if! { if #[cfg(feature = "runtime-benchmarks")] { - let default_keys = sp_std::vec![ - RevealedDidKey { - id: KiltDidKeyId::default(), - details: DidPublicKeyDetails { - key: did::did_details::DidVerificationKey::Ed25519(sp_core::ed25519::Public::from_raw([0u8; 32])).into(), - block_number: KiltBlockNumber::default() - }, - relationship: DidVerificationKeyRelationship::Authentication.into() - }.into()]; - let bounded_keys = default_keys.try_into().map_err(|_| { - log::error!("Should not fail to convert single element to a BoundedVec."); - Error::Internal - })?; - (bounded_keys, 0u32) + return Ok(DipVerifiedInfo::default()); } else { return Err(Error::InvalidDidKeyRevealed); } @@ -1108,6 +1097,49 @@ impl< } } +#[cfg(feature = "runtime-benchmarks")] +impl< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + const MAX_REVEALED_LEAVES_COUNT: u32, + > Default + for DipVerifiedInfo< + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + MAX_REVEALED_LEAVES_COUNT, + > where + KiltDidKeyId: BenchmarkDefault, + KiltBlockNumber: BenchmarkDefault, +{ + fn default() -> Self { + let default_keys = sp_std::vec![RevealedDidKey { + id: KiltDidKeyId::default(), + details: DidPublicKeyDetails { + key: did::did_details::DidVerificationKey::Ed25519(sp_core::ed25519::Public::from_raw([0u8; 32])) + .into(), + block_number: KiltBlockNumber::default() + }, + relationship: DidVerificationKeyRelationship::Authentication.into() + } + .into()]; + let bounded_keys = default_keys + .try_into() + // To avoid requiring types to implement `Debug`. + .map_err(|_| "Should not fail to convert single element to a BoundedVec.") + .unwrap(); + Self { + revealed_leaves: bounded_keys, + signing_leaf_index: 0u32, + } + } +} + /// Relationship of a key to a DID Document. #[derive(Clone, Copy, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub enum DidKeyRelationship { diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 1f3533f17e..4fe101a269 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -29,7 +29,7 @@ use sp_std::marker::PhantomData; use crate::{ merkle::v0::RevealedDidKey, - traits::{BenchmarkDefault, DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, + traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, DipVerifiedInfo, Error, }; @@ -43,8 +43,8 @@ pub enum VersionedDipParachainStateProof< RelayBlockNumber, KiltDidKeyId, KiltAccountId, - KiltWeb3Name, KiltBlockNumber, + KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, > { @@ -53,14 +53,48 @@ pub enum VersionedDipParachainStateProof< RelayBlockNumber, KiltDidKeyId, KiltAccountId, - KiltWeb3Name, KiltBlockNumber, + KiltWeb3Name, KiltLinkableAccountId, ConsumerBlockNumber, >, ), } +#[cfg(feature = "runtime-benchmarks")] +impl< + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + Context, + > kilt_support::traits::GetWorstCase + for VersionedDipParachainStateProof< + RelayBlockNumber, + KiltDidKeyId, + KiltAccountId, + KiltBlockNumber, + KiltWeb3Name, + KiltLinkableAccountId, + ConsumerBlockNumber, + > where + RelayBlockNumber: Default, + KiltDidKeyId: Default + Clone, + KiltAccountId: Clone, + KiltBlockNumber: Default + Clone, + KiltWeb3Name: Clone, + KiltLinkableAccountId: Clone, + ConsumerBlockNumber: Default, + Context: Clone, +{ + fn worst_case(context: Context) -> Self { + Self::V0(crate::merkle::v0::ParachainDipDidProof::worst_case(context)) + } +} + pub enum DipParachainStateProofVerifierError { UnsupportedVersion, ProofComponentTooLarge(u8), @@ -157,7 +191,6 @@ impl< + pallet_did_lookup::Config, KiltRuntime::IdentityCommitmentGenerator: IdentityCommitmentGenerator, - HeaderFor: BenchmarkDefault, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, DidCallVerifier: DipCallOriginFilter< @@ -322,7 +355,6 @@ pub mod v0 { + pallet_did_lookup::Config, KiltRuntime::IdentityCommitmentGenerator: IdentityCommitmentGenerator, - HeaderFor: BenchmarkDefault, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, DidCallVerifier: DipCallOriginFilter< diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index 45f914a22f..a640229368 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -17,7 +17,7 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org use did::KeyIdOf; -use frame_system::pallet_prelude::{BlockNumberFor, HeaderFor}; +use frame_system::pallet_prelude::BlockNumberFor; use pallet_did_lookup::linkable_account::LinkableAccountId; use pallet_dip_consumer::{traits::IdentityProofVerifier, RuntimeCallOf}; use pallet_dip_provider::{traits::IdentityCommitmentGenerator, IdentityCommitmentOf}; @@ -30,7 +30,7 @@ use sp_std::marker::PhantomData; use crate::{ merkle::v0::RevealedDidKey, - traits::{BenchmarkDefault, DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, + traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, DipVerifiedInfo, Error, }; @@ -146,7 +146,6 @@ impl< + pallet_web3_names::Config + pallet_did_lookup::Config, KiltRuntime::IdentityCommitmentGenerator: IdentityCommitmentGenerator, - HeaderFor: BenchmarkDefault, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, DidCallVerifier: DipCallOriginFilter< @@ -301,7 +300,6 @@ pub mod v0 { + pallet_did_lookup::Config, KiltRuntime::IdentityCommitmentGenerator: IdentityCommitmentGenerator, - HeaderFor: BenchmarkDefault, IdentityCommitmentOf: Into, SignedExtra: GetWithoutArg, SignedExtra::Result: Encode, From a520335822224705998b7dcd130bab29cf3e4a2c Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 26 Jan 2024 11:23:01 +0100 Subject: [PATCH 31/45] Benchmarks passing for consumer template --- crates/kilt-dip-primitives/src/merkle/v0.rs | 34 ++++++++++++------- .../src/verifier/parachain.rs | 28 +++++++++++++-- dip-template/runtimes/dip-consumer/src/dip.rs | 8 +++++ 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index fb8c09bf86..2b16f77782 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -603,8 +603,14 @@ impl< StateRootStore: GetWithArg>>, ProviderHeader: Decode + HeaderT, Number = KiltBlockNumber>, { - let relay_state_root = - StateRootStore::get(&self.provider_head_proof.relay_block_number).ok_or(Error::RelayStateRootNotFound)?; + let relay_state_root = StateRootStore::get(&self.provider_head_proof.relay_block_number); + cfg_if::cfg_if! { + if #[cfg(feature = "runtime-benchmarks")] { + let relay_state_root = relay_state_root.unwrap_or_default(); + } else { + let relay_state_root = relay_state_root.ok_or(Error::RelayStateRootNotFound)?; + } + } self.verify_provider_head_proof_with_state_root::( provider_para_id, &relay_state_root, @@ -796,35 +802,39 @@ impl< where DidMerkleHasher: Hash, { - let mut max_revealed_leaves_iter = self - .dip_proof - .revealed - .iter() - .take(MAX_REVEALED_LEAVES_COUNT.saturated_into()); + log::debug!(target: "dip-provider", "91"); + let mut revealed_leaves_iter = self.dip_proof.revealed.iter(); // If more than `max_revealed_leaves_count` are revealed, return an error. - ensure!(max_revealed_leaves_iter.next().is_none(), Error::TooManyLeavesRevealed); + ensure!( + revealed_leaves_iter.by_ref().count() <= MAX_REVEALED_LEAVES_COUNT.saturated_into(), + Error::TooManyLeavesRevealed + ); + log::debug!(target: "dip-provider", "92"); - let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = max_revealed_leaves_iter - .by_ref() + let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = revealed_leaves_iter .map(|revealed_leaf| (revealed_leaf.encoded_key(), Some(revealed_leaf.encoded_value()))) .collect(); + log::debug!(target: "dip-provider", "94"); let proof_verification_result = verify_trie_proof::, _, _, _>( &self.dip_commitment, self.dip_proof.blinded.as_slice(), &proof_leaves_key_value_pairs, ); + log::debug!(target: "dip-provider", "95"); cfg_if::cfg_if! { if #[cfg(feature = "runtime-benchmarks")] { - proof_verification_result.map_err(|_| Error::InvalidDidMerkleProof)?; - } else { drop(proof_verification_result); + } else { + proof_verification_result.map_err(|_| Error::InvalidDidMerkleProof)?; } } + log::debug!(target: "dip-provider", "96"); let revealed_leaves = BoundedVec::try_from(self.dip_proof.revealed).map_err(|_| { log::error!("Should not fail to construct BoundedVec since bounds were checked before."); Error::Internal })?; + log::debug!(target: "dip-provider", "97"); Ok(DipDetailsAndUnverifiedDidSignatureTime { revealed_leaves, diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 4fe101a269..45a81525dc 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -390,11 +390,13 @@ pub mod v0 { identity_details: &mut Option<::LocalIdentityInfo>, proof: Self::Proof, ) -> Result { + log::debug!(target: "dip-provider", "1"); // 1. Verify parachain state is finalized by relay chain and fresh. ensure!( proof.provider_head_proof.proof.len() <= MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT.saturated_into(), DipParachainStateProofVerifierError::ProofComponentTooLarge(0) ); + log::debug!(target: "dip-provider", "2"); ensure!( proof .provider_head_proof @@ -403,11 +405,13 @@ pub mod v0 { .all(|l| l.len() <= MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE.saturated_into()), DipParachainStateProofVerifierError::ProofComponentTooLarge(1) ); + log::debug!(target: "dip-provider", "3"); let proof_without_relaychain = proof .verify_provider_head_proof::>( KILT_PARA_ID, ) .map_err(DipParachainStateProofVerifierError::ProofVerification)?; + log::debug!(target: "dip-provider", "4"); // 2. Verify commitment is included in provider parachain state. ensure!( @@ -415,6 +419,7 @@ pub mod v0 { <= MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT.saturated_into(), DipParachainStateProofVerifierError::ProofComponentTooLarge(2) ); + log::debug!(target: "dip-provider", "5"); ensure!( proof_without_relaychain .dip_commitment_proof @@ -423,15 +428,18 @@ pub mod v0 { .all(|l| l.len() <= MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE.saturated_into()), DipParachainStateProofVerifierError::ProofComponentTooLarge(3) ); + log::debug!(target: "dip-provider", "6"); let proof_without_parachain = proof_without_relaychain .verify_dip_commitment_proof_for_subject::(subject) .map_err(DipParachainStateProofVerifierError::ProofVerification)?; + log::debug!(target: "dip-provider", "7"); // 3. Verify DIP Merkle proof. ensure!( proof_without_parachain.dip_proof.blinded.len() <= MAX_DID_MERKLE_PROOF_LEAVE_COUNT.saturated_into(), DipParachainStateProofVerifierError::ProofComponentTooLarge(4) ); + log::debug!(target: "dip-provider", "8"); ensure!( proof_without_parachain .dip_proof @@ -440,27 +448,42 @@ pub mod v0 { .all(|l| l.len() <= MAX_DID_MERKLE_PROOF_LEAVE_SIZE.saturated_into()), DipParachainStateProofVerifierError::ProofComponentTooLarge(5) ); + log::debug!(target: "dip-provider", "9"); let proof_without_dip_merkle = proof_without_parachain .verify_dip_proof::() .map_err(DipParachainStateProofVerifierError::ProofVerification)?; + log::debug!(target: "dip-provider", "10"); // 4. Verify call is signed by one of the DID keys revealed in the proof let current_block_number = frame_system::Pallet::::block_number(); + log::debug!(target: "dip-provider", "11"); let consumer_genesis_hash = frame_system::Pallet::::block_hash(BlockNumberFor::::zero()); + log::debug!(target: "dip-provider", "12"); let signed_extra = SignedExtra::get(); + log::debug!(target: "dip-provider", "13"); let encoded_payload = (call, &identity_details, submitter, consumer_genesis_hash, signed_extra).encode(); + log::debug!(target: "dip-provider", "14"); let revealed_did_info = proof_without_dip_merkle .verify_signature_time(¤t_block_number) .and_then(|p| p.retrieve_signing_leaf_for_payload(&encoded_payload[..])) .map_err(DipParachainStateProofVerifierError::ProofVerification)?; + log::debug!(target: "dip-provider", "15"); // 5. Verify the signing key fulfills the requirements let signing_key = revealed_did_info .get_signing_leaf() .map_err(DipParachainStateProofVerifierError::ProofVerification)?; - DidCallVerifier::check_call_origin_info(call, signing_key) - .map_err(DipParachainStateProofVerifierError::DidOriginError)?; + log::debug!(target: "dip-provider", "16"); + let call_origin_check_result = DidCallVerifier::check_call_origin_info(call, signing_key); + cfg_if::cfg_if! { + if #[cfg(feature = "runtime-benchmarks")] { + drop(call_origin_check_result); + } else { + call_origin_check_result.map_err(DipParachainStateProofVerifierError::DidOriginError)?; + } + } + log::debug!(target: "dip-provider", "17"); // 6. Increment the local details if let Some(details) = identity_details { @@ -468,6 +491,7 @@ pub mod v0 { } else { *identity_details = Some(Default::default()); }; + log::debug!(target: "dip-provider", "18"); Ok(revealed_did_info) } diff --git a/dip-template/runtimes/dip-consumer/src/dip.rs b/dip-template/runtimes/dip-consumer/src/dip.rs index 1f246996a1..db079e7b49 100644 --- a/dip-template/runtimes/dip-consumer/src/dip.rs +++ b/dip-template/runtimes/dip-consumer/src/dip.rs @@ -42,6 +42,14 @@ pub type ProofVerifier = KiltVersionedParachainVerifier< 2_000, ProviderRuntime, DipCallFilter, BlockNumberFor, ProviderAccountId>, + (), + 64, + 128, + 64, + 128, + 64, + 128, + 64, >; impl pallet_dip_consumer::Config for Runtime { From e4e853af341ec9e329e57881d2e178fa2040c9e6 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 26 Jan 2024 12:08:26 +0100 Subject: [PATCH 32/45] Remove benchmarks from verifier code --- Cargo.lock | 1 + crates/kilt-dip-primitives/src/merkle/v0.rs | 6 ---- .../src/verifier/parachain.rs | 28 ++----------------- dip-template/runtimes/dip-consumer/Cargo.toml | 1 + dip-template/runtimes/dip-consumer/src/dip.rs | 2 ++ 5 files changed, 6 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 09458d85f5..a1f075a7b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2485,6 +2485,7 @@ dependencies = [ name = "dip-consumer-runtime-template" version = "1.12.0-dev" dependencies = [ + "cfg-if", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index 2b16f77782..01134c2bf0 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -802,25 +802,21 @@ impl< where DidMerkleHasher: Hash, { - log::debug!(target: "dip-provider", "91"); let mut revealed_leaves_iter = self.dip_proof.revealed.iter(); // If more than `max_revealed_leaves_count` are revealed, return an error. ensure!( revealed_leaves_iter.by_ref().count() <= MAX_REVEALED_LEAVES_COUNT.saturated_into(), Error::TooManyLeavesRevealed ); - log::debug!(target: "dip-provider", "92"); let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = revealed_leaves_iter .map(|revealed_leaf| (revealed_leaf.encoded_key(), Some(revealed_leaf.encoded_value()))) .collect(); - log::debug!(target: "dip-provider", "94"); let proof_verification_result = verify_trie_proof::, _, _, _>( &self.dip_commitment, self.dip_proof.blinded.as_slice(), &proof_leaves_key_value_pairs, ); - log::debug!(target: "dip-provider", "95"); cfg_if::cfg_if! { if #[cfg(feature = "runtime-benchmarks")] { @@ -829,12 +825,10 @@ impl< proof_verification_result.map_err(|_| Error::InvalidDidMerkleProof)?; } } - log::debug!(target: "dip-provider", "96"); let revealed_leaves = BoundedVec::try_from(self.dip_proof.revealed).map_err(|_| { log::error!("Should not fail to construct BoundedVec since bounds were checked before."); Error::Internal })?; - log::debug!(target: "dip-provider", "97"); Ok(DipDetailsAndUnverifiedDidSignatureTime { revealed_leaves, diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 45a81525dc..4fe101a269 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -390,13 +390,11 @@ pub mod v0 { identity_details: &mut Option<::LocalIdentityInfo>, proof: Self::Proof, ) -> Result { - log::debug!(target: "dip-provider", "1"); // 1. Verify parachain state is finalized by relay chain and fresh. ensure!( proof.provider_head_proof.proof.len() <= MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT.saturated_into(), DipParachainStateProofVerifierError::ProofComponentTooLarge(0) ); - log::debug!(target: "dip-provider", "2"); ensure!( proof .provider_head_proof @@ -405,13 +403,11 @@ pub mod v0 { .all(|l| l.len() <= MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE.saturated_into()), DipParachainStateProofVerifierError::ProofComponentTooLarge(1) ); - log::debug!(target: "dip-provider", "3"); let proof_without_relaychain = proof .verify_provider_head_proof::>( KILT_PARA_ID, ) .map_err(DipParachainStateProofVerifierError::ProofVerification)?; - log::debug!(target: "dip-provider", "4"); // 2. Verify commitment is included in provider parachain state. ensure!( @@ -419,7 +415,6 @@ pub mod v0 { <= MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT.saturated_into(), DipParachainStateProofVerifierError::ProofComponentTooLarge(2) ); - log::debug!(target: "dip-provider", "5"); ensure!( proof_without_relaychain .dip_commitment_proof @@ -428,18 +423,15 @@ pub mod v0 { .all(|l| l.len() <= MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE.saturated_into()), DipParachainStateProofVerifierError::ProofComponentTooLarge(3) ); - log::debug!(target: "dip-provider", "6"); let proof_without_parachain = proof_without_relaychain .verify_dip_commitment_proof_for_subject::(subject) .map_err(DipParachainStateProofVerifierError::ProofVerification)?; - log::debug!(target: "dip-provider", "7"); // 3. Verify DIP Merkle proof. ensure!( proof_without_parachain.dip_proof.blinded.len() <= MAX_DID_MERKLE_PROOF_LEAVE_COUNT.saturated_into(), DipParachainStateProofVerifierError::ProofComponentTooLarge(4) ); - log::debug!(target: "dip-provider", "8"); ensure!( proof_without_parachain .dip_proof @@ -448,42 +440,27 @@ pub mod v0 { .all(|l| l.len() <= MAX_DID_MERKLE_PROOF_LEAVE_SIZE.saturated_into()), DipParachainStateProofVerifierError::ProofComponentTooLarge(5) ); - log::debug!(target: "dip-provider", "9"); let proof_without_dip_merkle = proof_without_parachain .verify_dip_proof::() .map_err(DipParachainStateProofVerifierError::ProofVerification)?; - log::debug!(target: "dip-provider", "10"); // 4. Verify call is signed by one of the DID keys revealed in the proof let current_block_number = frame_system::Pallet::::block_number(); - log::debug!(target: "dip-provider", "11"); let consumer_genesis_hash = frame_system::Pallet::::block_hash(BlockNumberFor::::zero()); - log::debug!(target: "dip-provider", "12"); let signed_extra = SignedExtra::get(); - log::debug!(target: "dip-provider", "13"); let encoded_payload = (call, &identity_details, submitter, consumer_genesis_hash, signed_extra).encode(); - log::debug!(target: "dip-provider", "14"); let revealed_did_info = proof_without_dip_merkle .verify_signature_time(¤t_block_number) .and_then(|p| p.retrieve_signing_leaf_for_payload(&encoded_payload[..])) .map_err(DipParachainStateProofVerifierError::ProofVerification)?; - log::debug!(target: "dip-provider", "15"); // 5. Verify the signing key fulfills the requirements let signing_key = revealed_did_info .get_signing_leaf() .map_err(DipParachainStateProofVerifierError::ProofVerification)?; - log::debug!(target: "dip-provider", "16"); - let call_origin_check_result = DidCallVerifier::check_call_origin_info(call, signing_key); - cfg_if::cfg_if! { - if #[cfg(feature = "runtime-benchmarks")] { - drop(call_origin_check_result); - } else { - call_origin_check_result.map_err(DipParachainStateProofVerifierError::DidOriginError)?; - } - } - log::debug!(target: "dip-provider", "17"); + DidCallVerifier::check_call_origin_info(call, signing_key) + .map_err(DipParachainStateProofVerifierError::DidOriginError)?; // 6. Increment the local details if let Some(details) = identity_details { @@ -491,7 +468,6 @@ pub mod v0 { } else { *identity_details = Some(Default::default()); }; - log::debug!(target: "dip-provider", "18"); Ok(revealed_did_info) } diff --git a/dip-template/runtimes/dip-consumer/Cargo.toml b/dip-template/runtimes/dip-consumer/Cargo.toml index 2e9041158b..77258cf689 100644 --- a/dip-template/runtimes/dip-consumer/Cargo.toml +++ b/dip-template/runtimes/dip-consumer/Cargo.toml @@ -16,6 +16,7 @@ substrate-wasm-builder.workspace = true [dependencies] parity-scale-codec = {workspace = true, features = ["derive"]} scale-info = {workspace = true, features = ["derive"]} +cfg-if.workspace = true # DIP dip-provider-runtime-template.workspace = true diff --git a/dip-template/runtimes/dip-consumer/src/dip.rs b/dip-template/runtimes/dip-consumer/src/dip.rs index db079e7b49..b9772d74d7 100644 --- a/dip-template/runtimes/dip-consumer/src/dip.rs +++ b/dip-template/runtimes/dip-consumer/src/dip.rs @@ -97,6 +97,8 @@ impl Contains for PreliminaryDipOriginFilter { fn derive_verification_key_relationship(call: &RuntimeCall) -> Option { match call { RuntimeCall::PostIt { .. } => Some(DidVerificationKeyRelationship::Authentication), + #[cfg(feature = "runtime-benchmarks")] + RuntimeCall::System(frame_system::Call::remark { .. }) => Some(DidVerificationKeyRelationship::Authentication), RuntimeCall::Utility(pallet_utility::Call::batch { calls }) => single_key_relationship(calls.iter()).ok(), RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => single_key_relationship(calls.iter()).ok(), RuntimeCall::Utility(pallet_utility::Call::force_batch { calls }) => single_key_relationship(calls.iter()).ok(), From 9da230e252ce4bdab618cf6f406fd63caeef4044 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Wed, 31 Jan 2024 14:53:03 +0100 Subject: [PATCH 33/45] Add valid_unlid_until to signed payload --- crates/kilt-dip-primitives/src/merkle/v0.rs | 6 ++++++ crates/kilt-dip-primitives/src/verifier/parachain.rs | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index 01134c2bf0..eccb980ae9 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -220,6 +220,12 @@ impl From for u8 { } } +//TODO: steps: +// 1. Create a DID with a web3name and the maximum number of allowed linked +// accounts +// 2. Create an identity commitment +// 3. Call the cross-chain operation, and take not of the generated proof. + /// A DIP proof submitted to a relaychain consumer. /// /// The generic types indicate the following: diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index d96479fa61..8b95fcd97d 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -449,7 +449,15 @@ pub mod v0 { let consumer_genesis_hash = frame_system::Pallet::::block_hash(BlockNumberFor::::zero()); let signed_extra = SignedExtra::get(); - let encoded_payload = (call, &identity_details, submitter, consumer_genesis_hash, signed_extra).encode(); + let encoded_payload = ( + call, + &identity_details, + submitter, + proof_without_dip_merkle.signature.valid_until, + consumer_genesis_hash, + signed_extra, + ) + .encode(); let revealed_did_info = proof_without_dip_merkle .verify_signature_time(¤t_block_number) .and_then(|p| p.retrieve_signing_leaf_for_payload(&encoded_payload[..])) From 7c9645a25b1ac467c14cbf57eb67398aee5e3263 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 9 Feb 2024 12:04:33 +0100 Subject: [PATCH 34/45] Fix regression bug --- crates/kilt-dip-primitives/src/merkle/v0.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index eccb980ae9..51981ad804 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -808,20 +808,21 @@ impl< where DidMerkleHasher: Hash, { - let mut revealed_leaves_iter = self.dip_proof.revealed.iter(); - // If more than `max_revealed_leaves_count` are revealed, return an error. ensure!( - revealed_leaves_iter.by_ref().count() <= MAX_REVEALED_LEAVES_COUNT.saturated_into(), + self.dip_proof.revealed.len() <= MAX_REVEALED_LEAVES_COUNT.saturated_into(), Error::TooManyLeavesRevealed ); - let proof_leaves_key_value_pairs: Vec<(Vec, Option>)> = revealed_leaves_iter + let proof_leaves_key_value_pairs = self + .dip_proof + .revealed + .iter() .map(|revealed_leaf| (revealed_leaf.encoded_key(), Some(revealed_leaf.encoded_value()))) - .collect(); + .collect::>(); let proof_verification_result = verify_trie_proof::, _, _, _>( &self.dip_commitment, self.dip_proof.blinded.as_slice(), - &proof_leaves_key_value_pairs, + proof_leaves_key_value_pairs.as_slice(), ); cfg_if::cfg_if! { From d63ee4ac7a5a51eb70e9ec28108c793971e4d8b7 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 9 Feb 2024 12:06:39 +0100 Subject: [PATCH 35/45] Increase limits for Merkle proof leaves size --- crates/kilt-dip-primitives/src/verifier/parachain.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 8b95fcd97d..dd5c8bc107 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -132,11 +132,11 @@ pub struct KiltVersionedParachainVerifier< DidCallVerifier, SignedExtra = (), const MAX_PROVIDER_HEAD_PROOF_LEAVE_COUNT: u32 = 64, - const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_PROVIDER_HEAD_PROOF_LEAVE_SIZE: u32 = 1024, const MAX_DIP_COMMITMENT_PROOF_LEAVE_COUNT: u32 = 64, - const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DIP_COMMITMENT_PROOF_LEAVE_SIZE: u32 = 1024, const MAX_DID_MERKLE_PROOF_LEAVE_COUNT: u32 = 64, - const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 128, + const MAX_DID_MERKLE_PROOF_LEAVE_SIZE: u32 = 1024, const MAX_DID_MERKLE_LEAVES_REVEALED: u32 = 64, >( PhantomData<( From 20291a1b29e8fdc10b62ff346334fa6580cb741e Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 9 Feb 2024 12:29:06 +0100 Subject: [PATCH 36/45] Add state proof verification function with custom decoder --- crates/kilt-dip-primitives/src/merkle/v0.rs | 12 +++++-- .../src/state_proofs/mod.rs | 33 +++++++++++++++++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index 51981ad804..b74f8e3131 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -35,7 +35,7 @@ use sp_std::vec::Vec; use sp_trie::{verify_trie_proof, LayoutV1}; use crate::{ - state_proofs::{verify_storage_value_proof, MerkleProofError}, + state_proofs::{verify_storage_value_proof, verify_storage_value_proof_with_decoder, MerkleProofError}, traits::{BenchmarkDefault, GetWithArg}, utils::{ calculate_dip_identity_commitment_storage_key_for_runtime, calculate_parachain_head_storage_key, @@ -557,10 +557,18 @@ impl< ProviderHeader: Decode + HeaderT, Number = KiltBlockNumber>, { let provider_head_storage_key = calculate_parachain_head_storage_key(provider_para_id); - let provider_header_result = verify_storage_value_proof::<_, RelayHasher, ProviderHeader>( + // TODO: Figure out why RPC call returns 2 bytes in front which we don't need + let provider_header_result = verify_storage_value_proof_with_decoder::<_, RelayHasher, ProviderHeader>( &provider_head_storage_key, *relay_state_root, self.provider_head_proof.proof, + |input| { + if input.len() < 2 { + return None; + } + let mut trimmed_input = &input[2..]; + ProviderHeader::decode(&mut trimmed_input).ok() + }, ); cfg_if::cfg_if! { if #[cfg(feature = "runtime-benchmarks")] { diff --git a/crates/kilt-dip-primitives/src/state_proofs/mod.rs b/crates/kilt-dip-primitives/src/state_proofs/mod.rs index 84c6492547..ccd47ea864 100644 --- a/crates/kilt-dip-primitives/src/state_proofs/mod.rs +++ b/crates/kilt-dip-primitives/src/state_proofs/mod.rs @@ -62,9 +62,35 @@ where MerkleHasher: Hash, OutputOf: Ord, Success: Decode, +{ + verify_storage_value_proof_with_decoder::<_, MerkleHasher, _>(storage_key, state_root, state_proof, |input| { + Success::decode(input).ok() + }) +} + +/// Verify a Merkle-based storage proof for a given storage key according to the +/// provided state root. The generic types indicate the following: +/// * `StorageKey`: defines the type of the storage key included in the proof. +/// * `MerkleHasher`: defines the hashing algorithm used to calculate the Merkle +/// root. +/// * `TransformResult`: the type returned by the provided decoding function, if +/// successful. The `None` result is interpreted as an error, so it is not possible to return a type for which `None` would be a correct decoding, for now. See https://github.com/rust-lang/rust/issues/103765 for more details. +pub fn verify_storage_value_proof_with_decoder( + storage_key: &StorageKey, + state_root: OutputOf, + state_proof: impl IntoIterator>, + // TODO: Switch to `Error` from `Option` for the closure. + // `Error` is not yet available in core. + // It was merged recently and will be stabilized at some point. See https://github.com/rust-lang/rust/issues/103765 for more. + mut transform: impl FnMut(&mut &[u8]) -> Option, +) -> Result +where + StorageKey: AsRef<[u8]>, + MerkleHasher: Hash, + OutputOf: Ord, { let storage_proof = StorageProof::new(state_proof); - let revealed_leaves = read_proof_check::(state_root, storage_proof, [storage_key].iter()) + let mut revealed_leaves = read_proof_check::(state_root, storage_proof, [storage_key].iter()) .map_err(|_| MerkleProofError::InvalidProof)?; debug_assert!( @@ -76,11 +102,12 @@ where "Proof does not include the expected storage key." ); - let Some(Some(encoded_revealed_leaf)) = revealed_leaves.get(storage_key.as_ref()) else { + let Some(Some(encoded_revealed_leaf)) = revealed_leaves.get_mut(storage_key.as_ref()) else { return Err(MerkleProofError::RequiredLeafNotRevealed); }; - Success::decode(&mut &encoded_revealed_leaf[..]).map_err(|_| MerkleProofError::ResultDecoding) + let input = &mut &encoded_revealed_leaf[..]; + transform(input).ok_or(MerkleProofError::ResultDecoding) } #[cfg(test)] From f20d24ef1cac2ff80063013fd00ea14baf059975 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 9 Feb 2024 13:21:43 +0100 Subject: [PATCH 37/45] Refactor visibility of struct fields --- crates/kilt-dip-primitives/src/merkle/v0.rs | 40 +++++++++---------- .../src/state_proofs/mod.rs | 3 +- crates/kilt-dip-primitives/src/utils.rs | 6 +-- .../src/verifier/parachain.rs | 4 +- .../src/verifier/relaychain.rs | 6 +-- pallets/did/src/did_details.rs | 8 ++-- 6 files changed, 34 insertions(+), 33 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index b74f8e3131..a7695f58c7 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -21,7 +21,7 @@ use did::{ did_details::{DidPublicKey, DidPublicKeyDetails}, DidSignature, DidVerificationKeyRelationship, }; -use frame_support::{ensure, RuntimeDebug}; +use frame_support::ensure; use pallet_dip_provider::IdentityCommitmentOf; use parity_scale_codec::{Codec, Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; @@ -31,7 +31,7 @@ use sp_runtime::{ traits::{AtLeast32BitUnsigned, Hash, Header as HeaderT, MaybeDisplay, Member}, BoundedVec, SaturatedConversion, }; -use sp_std::vec::Vec; +use sp_std::{fmt::Debug, vec::Vec}; use sp_trie::{verify_trie_proof, LayoutV1}; use crate::{ @@ -47,7 +47,7 @@ use crate::{ /// /// The generic types indicate the following: /// * `RelayBlockNumber`: The `BlockNumber` definition of the relaychain. -#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] +#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct ProviderHeadStateProof { pub(crate) relay_block_number: RelayBlockNumber, pub(crate) proof: BoundedBlindedValue, @@ -67,7 +67,7 @@ where } /// The state proof for a DIP commitment. -#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] +#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct DipCommitmentStateProof(pub(crate) BoundedBlindedValue); #[cfg(feature = "runtime-benchmarks")] @@ -86,7 +86,7 @@ impl kilt_support::traits::GetWorstCase for DipCommitmentState /// * `ProviderWeb3Name`: The web3name type configured by the provider. /// * `ProviderLinkableAccountId`: The linkable account ID type configured by /// the provider. -#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] +#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct DidMerkleProof< ProviderDidKeyId, ProviderAccountId, @@ -160,7 +160,7 @@ impl< /// The generic types indicate the following: /// * `BlockNumber`: The `BlockNumber` definition of the chain consuming (i.e., /// validating) this signature. -#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] +#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct TimeBoundDidSignature { /// The signature. pub(crate) signature: DidSignature, @@ -182,6 +182,7 @@ where } } +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, TypeInfo)] pub enum Error { InvalidRelayHeader, RelayBlockNotFound, @@ -220,12 +221,6 @@ impl From for u8 { } } -//TODO: steps: -// 1. Create a DID with a web3name and the maximum number of allowed linked -// accounts -// 2. Create an identity commitment -// 3. Call the cross-chain operation, and take not of the generated proof. - /// A DIP proof submitted to a relaychain consumer. /// /// The generic types indicate the following: @@ -237,7 +232,7 @@ impl From for u8 { /// * `KiltWeb3Name`: The web3name type configured by the KILT chain. /// * `KiltLinkableAccountId`: The linkable account ID type configured by the /// KILT chain. -#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] +#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct RelayDipDidProof< RelayBlockNumber: Copy + Into + TryFrom, RelayHasher: Hash, @@ -352,6 +347,7 @@ impl< /// * `KiltWeb3Name`: The web3name type configured by the KILT chain. /// * `KiltLinkableAccountId`: The linkable account ID type configured by the /// KILT chain. +#[derive(Debug)] pub struct DipDidProofWithVerifiedRelayStateRoot< StateRoot, RelayBlockNumber, @@ -448,7 +444,7 @@ impl< /// KILT chain. /// * `ConsumerBlockNumber`: The `BlockNumber` definition of the consumer /// parachain. -#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] +#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct ParachainDipDidProof< RelayBlockNumber, KiltDidKeyId, @@ -645,6 +641,7 @@ impl< /// KILT chain. /// * `ConsumerBlockNumber`: The `BlockNumber` definition of the consumer /// parachain. +#[derive(Debug)] pub struct DipDidProofWithoutRelayProof< StateRoot, KiltDidKeyId, @@ -750,6 +747,7 @@ impl< /// KILT chain. /// * `ConsumerBlockNumber`: The `BlockNumber` definition of the consumer /// parachain. +#[derive(Debug)] pub struct DipDidProofWithVerifiedCommitment< Commitment, KiltDidKeyId, @@ -866,6 +864,7 @@ impl< /// parachain. /// * `MAX_REVEALED_LEAVES_COUNT`: The maximum number of leaves revealable in /// the proof. +#[derive(Debug)] pub struct DipDetailsAndUnverifiedDidSignatureTime< KiltDidKeyId, KiltAccountId, @@ -947,6 +946,7 @@ impl< /// KILT chain. /// * `MAX_REVEALED_LEAVES_COUNT`: The maximum number of leaves revealable in /// the proof. +#[derive(Debug)] pub struct DipDetailsAndUnverifiedDidSignaturePayload< KiltDidKeyId, KiltAccountId, @@ -1047,7 +1047,7 @@ impl< /// Information, available as an origin, after the whole DIP proof has been /// verified. -#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub struct DipVerifiedInfo< KiltDidKeyId, KiltAccountId, @@ -1160,7 +1160,7 @@ impl< } /// Relationship of a key to a DID Document. -#[derive(Clone, Copy, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[derive(Clone, Copy, Debug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub enum DidKeyRelationship { Encryption, Verification(DidVerificationKeyRelationship), @@ -1186,7 +1186,7 @@ impl TryFrom for DidVerificationKeyRelationship { /// All possible Merkle leaf types that can be revealed as part of a DIP /// identity Merkle proof. -#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[derive(Clone, Copy, Debug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub enum RevealedDidMerkleProofLeaf { DidKey(RevealedDidKey), Web3Name(RevealedWeb3Name), @@ -1271,7 +1271,7 @@ where /// The details of a DID key after it has been successfully verified in a Merkle /// proof. -#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, RuntimeDebug, TypeInfo)] +#[derive(Clone, Copy, Debug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub struct RevealedDidKey { /// The key ID, according to the provider's definition. pub id: KeyId, @@ -1284,7 +1284,7 @@ pub struct RevealedDidKey { /// The details of a web3name after it has been successfully verified in a /// Merkle proof. -#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, RuntimeDebug, TypeInfo)] +#[derive(Clone, Copy, Debug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub struct RevealedWeb3Name { /// The web3name. pub web3_name: Web3Name, @@ -1295,5 +1295,5 @@ pub struct RevealedWeb3Name { /// The details of an account after it has been successfully verified in a /// Merkle proof. -#[derive(Clone, Encode, Decode, PartialEq, MaxEncodedLen, Eq, RuntimeDebug, TypeInfo)] +#[derive(Clone, Copy, Debug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub struct RevealedAccountId(pub AccountId); diff --git a/crates/kilt-dip-primitives/src/state_proofs/mod.rs b/crates/kilt-dip-primitives/src/state_proofs/mod.rs index ccd47ea864..456ad06756 100644 --- a/crates/kilt-dip-primitives/src/state_proofs/mod.rs +++ b/crates/kilt-dip-primitives/src/state_proofs/mod.rs @@ -17,6 +17,7 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org use parity_scale_codec::Decode; +use scale_info::TypeInfo; use sp_runtime::traits::Hash; use sp_std::vec::Vec; use sp_trie::StorageProof; @@ -28,7 +29,7 @@ use crate::{state_proofs::substrate_no_std_port::read_proof_check, utils::Output // kept up-to-date with upstream. mod substrate_no_std_port; -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, TypeInfo)] pub enum MerkleProofError { InvalidProof, RequiredLeafNotRevealed, diff --git a/crates/kilt-dip-primitives/src/utils.rs b/crates/kilt-dip-primitives/src/utils.rs index 0296b3c12c..7d71fb9cc7 100644 --- a/crates/kilt-dip-primitives/src/utils.rs +++ b/crates/kilt-dip-primitives/src/utils.rs @@ -19,15 +19,15 @@ use pallet_dip_provider::IdentityCommitmentVersion; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_core::{storage::StorageKey, RuntimeDebug}; -use sp_std::vec::Vec; +use sp_core::storage::StorageKey; +use sp_std::{fmt::Debug, vec::Vec}; /// The output of a type implementing the [`sp_runtime::traits::Hash`] trait. pub type OutputOf = ::Output; /// The vector of vectors that implements a statically-configured maximum length /// without requiring const generics, used in benchmarking worst cases. -#[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, Clone)] +#[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Debug, TypeInfo, Clone)] pub struct BoundedBlindedValue(Vec>); impl BoundedBlindedValue { diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index dd5c8bc107..89568698c0 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -24,7 +24,7 @@ use pallet_dip_provider::traits::IdentityCommitmentGenerator; use pallet_web3_names::Web3NameOf; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_core::RuntimeDebug; +use sp_std::fmt::Debug; use sp_std::marker::PhantomData; use crate::{ @@ -38,7 +38,7 @@ use crate::{ /// versioning. /// /// For more info, refer to the version-specific proofs. -#[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)] +#[derive(Encode, Decode, PartialEq, Eq, Debug, TypeInfo, Clone)] pub enum VersionedDipParachainStateProof< RelayBlockNumber, KiltDidKeyId, diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index b21d3e8197..8fb2ac6892 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -24,9 +24,9 @@ use pallet_dip_provider::{traits::IdentityCommitmentGenerator, IdentityCommitmen use pallet_web3_names::Web3NameOf; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_core::{RuntimeDebug, U256}; +use sp_core::U256; use sp_runtime::traits::Hash; -use sp_std::marker::PhantomData; +use sp_std::{fmt::Debug, marker::PhantomData}; use crate::{ merkle::v0::RevealedDidKey, @@ -39,7 +39,7 @@ use crate::{ /// versioning. /// /// For more info, refer to the version-specific proofs. -#[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)] +#[derive(Encode, Decode, PartialEq, Eq, Debug, TypeInfo, Clone)] pub enum VersionedRelaychainStateProof< ConsumerBlockNumber: Copy + Into + TryFrom, ConsumerBlockHasher: Hash, diff --git a/pallets/did/src/did_details.rs b/pallets/did/src/did_details.rs index 86f7150b0b..d28291f96d 100644 --- a/pallets/did/src/did_details.rs +++ b/pallets/did/src/did_details.rs @@ -39,7 +39,7 @@ use crate::{ }; /// Public verification key that a DID can control. -#[derive(Clone, Decode, RuntimeDebug, Encode, Eq, Ord, PartialEq, PartialOrd, TypeInfo, MaxEncodedLen)] +#[derive(Clone, Copy, Decode, RuntimeDebug, Encode, Eq, Ord, PartialEq, PartialOrd, TypeInfo, MaxEncodedLen)] pub enum DidVerificationKey { /// An Ed25519 public key. Ed25519(ed25519::Public), @@ -118,7 +118,7 @@ pub enum DidEncryptionKey { } /// A general public key under the control of the DID. -#[derive(Clone, Decode, RuntimeDebug, Encode, Eq, Ord, PartialEq, PartialOrd, TypeInfo, MaxEncodedLen)] +#[derive(Clone, Copy, Decode, RuntimeDebug, Encode, Eq, Ord, PartialEq, PartialOrd, TypeInfo, MaxEncodedLen)] pub enum DidPublicKey { /// A verification key, used to generate and verify signatures. PublicVerificationKey(DidVerificationKey), @@ -153,7 +153,7 @@ pub enum DidVerificationKeyRelationship { } /// Types of signatures supported by this pallet. -#[derive(Clone, Decode, RuntimeDebug, Encode, Eq, PartialEq, TypeInfo)] +#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum DidSignature { /// A Ed25519 signature. Ed25519(ed25519::Signature), @@ -264,7 +264,7 @@ impl, AccountId> DidVerifiableIdentifier for I { /// /// It is currently used to keep track of all the past and current /// attestation keys a DID might control. -#[derive(Clone, RuntimeDebug, Decode, Encode, PartialEq, Ord, PartialOrd, Eq, TypeInfo, MaxEncodedLen)] +#[derive(Clone, Copy, RuntimeDebug, Decode, Encode, PartialEq, Ord, PartialOrd, Eq, TypeInfo, MaxEncodedLen)] pub struct DidPublicKeyDetails { /// A public key the DID controls. pub key: DidPublicKey, From c02de70cd348a0ac300f04f047c9eb09d95c2739 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 9 Feb 2024 14:15:45 +0100 Subject: [PATCH 38/45] Fix dependencies --- Cargo.lock | 20 ------------------- crates/kilt-dip-primitives/Cargo.toml | 13 ------------ dip-template/nodes/dip-consumer/Cargo.toml | 1 - dip-template/nodes/dip-provider/Cargo.toml | 1 - dip-template/runtimes/dip-consumer/Cargo.toml | 20 ++++++------------- dip-template/runtimes/dip-provider/Cargo.toml | 11 ---------- pallets/pallet-dip-consumer/Cargo.toml | 6 +----- pallets/pallet-dip-provider/Cargo.toml | 4 +--- 8 files changed, 8 insertions(+), 68 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 09458d85f5..fc112de481 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2448,7 +2448,6 @@ dependencies = [ "jsonrpsee", "log", "pallet-transaction-payment-rpc", - "parity-scale-codec", "polkadot-cli", "polkadot-primitives", "sc-basic-authorship", @@ -2486,11 +2485,9 @@ name = "dip-consumer-runtime-template" version = "1.12.0-dev" dependencies = [ "cumulus-pallet-aura-ext", - "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-primitives-core", "cumulus-primitives-timestamp", - "cumulus-primitives-utility", "did", "dip-provider-runtime-template", "frame-benchmarking", @@ -2499,13 +2496,11 @@ dependencies = [ "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", - "hex-literal 0.3.4", "kilt-dip-primitives", "pallet-aura", "pallet-authorship", "pallet-balances", "pallet-collator-selection", - "pallet-did-lookup", "pallet-dip-consumer", "pallet-postit", "pallet-relay-store", @@ -2517,9 +2512,7 @@ dependencies = [ "pallet-utility", "parachain-info", "parity-scale-codec", - "polkadot-parachain", "rococo-runtime", - "runtime-common", "scale-info", "sp-api", "sp-block-builder", @@ -2555,7 +2548,6 @@ dependencies = [ "jsonrpsee", "log", "pallet-transaction-payment-rpc", - "parity-scale-codec", "polkadot-cli", "polkadot-primitives", "sc-basic-authorship", @@ -2593,11 +2585,9 @@ name = "dip-provider-runtime-template" version = "1.12.0-dev" dependencies = [ "cumulus-pallet-aura-ext", - "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-primitives-core", "cumulus-primitives-timestamp", - "cumulus-primitives-utility", "did", "frame-benchmarking", "frame-executive", @@ -2605,11 +2595,8 @@ dependencies = [ "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", - "hex-literal 0.3.4", - "kilt-dip-primitives", "kilt-runtime-api-did", "kilt-runtime-api-dip-provider", - "kilt-support", "log", "pallet-aura", "pallet-authorship", @@ -4615,7 +4602,6 @@ name = "kilt-dip-primitives" version = "1.12.0-dev" dependencies = [ "cfg-if", - "cumulus-pallet-parachain-system", "cumulus-primitives-core", "did", "frame-support", @@ -4629,9 +4615,7 @@ dependencies = [ "pallet-dip-provider", "pallet-relay-store", "pallet-web3-names", - "parachain-info", "parity-scale-codec", - "rococo-runtime", "scale-info", "sp-core", "sp-io", @@ -4639,8 +4623,6 @@ dependencies = [ "sp-state-machine", "sp-std", "sp-trie", - "xcm", - "xcm-executor", ] [[package]] @@ -6601,7 +6583,6 @@ dependencies = [ "kilt-support", "parity-scale-codec", "scale-info", - "sp-core", "sp-io", "sp-keystore", "sp-runtime", @@ -6619,7 +6600,6 @@ dependencies = [ "kilt-support", "parity-scale-codec", "scale-info", - "sp-core", "sp-io", "sp-keystore", "sp-runtime", diff --git a/crates/kilt-dip-primitives/Cargo.toml b/crates/kilt-dip-primitives/Cargo.toml index 2afec4987c..2b7f4adce1 100644 --- a/crates/kilt-dip-primitives/Cargo.toml +++ b/crates/kilt-dip-primitives/Cargo.toml @@ -39,15 +39,8 @@ sp-state-machine.workspace = true sp-std.workspace = true sp-trie.workspace = true -# Polkadot dependencies -rococo-runtime.workspace = true -xcm.workspace = true -xcm-executor.workspace = true - # Cumulus dependencies -cumulus-pallet-parachain-system.workspace = true cumulus-primitives-core.workspace = true -parachain-info.workspace = true [dev-dependencies] hex-literal.workspace = true @@ -75,16 +68,10 @@ std = [ "sp-state-machine/std", "sp-std/std", "sp-trie/std", - "rococo-runtime/std", - "xcm/std", - "xcm-executor/std", - "cumulus-pallet-parachain-system/std", "cumulus-primitives-core/std", - "parachain-info/std", ] runtime-benchmarks = [ "kilt-support/runtime-benchmarks", "pallet-dip-consumer/runtime-benchmarks", "pallet-dip-provider/runtime-benchmarks", - "rococo-runtime/runtime-benchmarks" ] diff --git a/dip-template/nodes/dip-consumer/Cargo.toml b/dip-template/nodes/dip-consumer/Cargo.toml index 76fcdebdca..e00bb993d2 100644 --- a/dip-template/nodes/dip-consumer/Cargo.toml +++ b/dip-template/nodes/dip-consumer/Cargo.toml @@ -15,7 +15,6 @@ build = "build.rs" clap = {workspace = true, features = ["std", "derive"]} futures = { workspace = true } log = { workspace = true, features = ["std"] } -parity-scale-codec = { workspace = true, features = ["std"] } serde = {workspace = true, features = ["std", "derive"]} jsonrpsee = {workspace = true, features = ["server"]} diff --git a/dip-template/nodes/dip-provider/Cargo.toml b/dip-template/nodes/dip-provider/Cargo.toml index 6ca76df480..e792a8236b 100644 --- a/dip-template/nodes/dip-provider/Cargo.toml +++ b/dip-template/nodes/dip-provider/Cargo.toml @@ -15,7 +15,6 @@ build = "build.rs" clap = {workspace = true, features = ["std", "derive"]} futures = { workspace = true } log = { workspace = true, features = ["std"] } -parity-scale-codec = { workspace = true, features = ["std"] } serde = {workspace = true, features = ["std", "derive"]} jsonrpsee = {workspace = true, features = ["server"]} diff --git a/dip-template/runtimes/dip-consumer/Cargo.toml b/dip-template/runtimes/dip-consumer/Cargo.toml index 2e9041158b..50826ec7bc 100644 --- a/dip-template/runtimes/dip-consumer/Cargo.toml +++ b/dip-template/runtimes/dip-consumer/Cargo.toml @@ -21,11 +21,9 @@ scale-info = {workspace = true, features = ["derive"]} dip-provider-runtime-template.workspace = true did.workspace = true kilt-dip-primitives.workspace = true -pallet-did-lookup.workspace = true pallet-dip-consumer.workspace = true pallet-postit.workspace = true pallet-relay-store.workspace = true -runtime-common.workspace = true # Substrate frame-executive.workspace = true @@ -41,7 +39,6 @@ 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 sp-consensus-aura.workspace = true @@ -57,11 +54,9 @@ sp-weights.workspace = true # Cumulus cumulus-pallet-aura-ext.workspace = true -cumulus-pallet-dmp-queue.workspace = true cumulus-pallet-parachain-system.workspace = true cumulus-primitives-core.workspace = true cumulus-primitives-timestamp.workspace = true -cumulus-primitives-utility.workspace = true pallet-collator-selection.workspace = true parachain-info.workspace = true @@ -71,7 +66,6 @@ rococo-runtime.workspace = true # Benchmarks frame-benchmarking = {workspace = true, optional = true} frame-system-benchmarking = {workspace = true, optional = true} -hex-literal = {workspace = true, optional = true} [features] default = [ @@ -83,11 +77,9 @@ std = [ "dip-provider-runtime-template/std", "did/std", "kilt-dip-primitives/std", - "pallet-did-lookup/std", "pallet-dip-consumer/std", "pallet-postit/std", "pallet-relay-store/std", - "runtime-common/std", "frame-executive/std", "frame-support/std", "frame-system/std", @@ -101,7 +93,6 @@ 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", "sp-consensus-aura/std", @@ -115,21 +106,22 @@ std = [ "sp-version/std", "sp-weights/std", "cumulus-pallet-aura-ext/std", - "cumulus-pallet-dmp-queue/std", "cumulus-pallet-parachain-system/std", "cumulus-primitives-core/std", "cumulus-primitives-timestamp/std", - "cumulus-primitives-utility/std", "pallet-collator-selection/std", - "parachain-info/std" + "parachain-info/std", + "rococo-runtime/std", + "frame-benchmarking/std", + "frame-system-benchmarking/std", ] runtime-benchmarks = [ "dip-provider-runtime-template/runtime-benchmarks", + "did/runtime-benchmarks", "kilt-dip-primitives/runtime-benchmarks", "pallet-dip-consumer/runtime-benchmarks", "pallet-relay-store/runtime-benchmarks", - "runtime-common/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", @@ -138,7 +130,7 @@ runtime-benchmarks = [ "pallet-timestamp/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "sp-runtime/runtime-benchmarks", + "rococo-runtime/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-system-benchmarking/runtime-benchmarks", - "hex-literal" ] diff --git a/dip-template/runtimes/dip-provider/Cargo.toml b/dip-template/runtimes/dip-provider/Cargo.toml index 63b4302ffe..951ec323fc 100644 --- a/dip-template/runtimes/dip-provider/Cargo.toml +++ b/dip-template/runtimes/dip-provider/Cargo.toml @@ -20,8 +20,6 @@ scale-info = {workspace = true, features = ["derive"]} # DIP did.workspace = true -kilt-support.workspace = true -kilt-dip-primitives.workspace = true kilt-runtime-api-did.workspace = true kilt-runtime-api-dip-provider.workspace = true pallet-deposit-storage.workspace = true @@ -59,18 +57,15 @@ sp-weights.workspace = true # Cumulus cumulus-pallet-aura-ext.workspace = true -cumulus-pallet-dmp-queue.workspace = true cumulus-pallet-parachain-system.workspace = true cumulus-primitives-core.workspace = true cumulus-primitives-timestamp.workspace = true -cumulus-primitives-utility.workspace = true pallet-collator-selection.workspace = true parachain-info.workspace = true # Benchmarks frame-benchmarking = {workspace = true, optional = true} frame-system-benchmarking = {workspace = true, optional = true} -hex-literal = {workspace = true, optional = true} [features] default = [ @@ -81,8 +76,6 @@ std = [ "parity-scale-codec/std", "scale-info/std", "did/std", - "kilt-support/std", - "kilt-dip-primitives/std", "kilt-runtime-api-did/std", "kilt-runtime-api-dip-provider/std", "pallet-deposit-storage/std", @@ -116,18 +109,15 @@ std = [ "sp-version/std", "sp-weights/std", "cumulus-pallet-aura-ext/std", - "cumulus-pallet-dmp-queue/std", "cumulus-pallet-parachain-system/std", "cumulus-primitives-core/std", "cumulus-primitives-timestamp/std", - "cumulus-primitives-utility/std", "pallet-collator-selection/std", "parachain-info/std", "frame-benchmarking?/std", ] runtime-benchmarks = [ "did/runtime-benchmarks", - "kilt-dip-primitives/runtime-benchmarks", "pallet-deposit-storage/runtime-benchmarks", "pallet-did-lookup/runtime-benchmarks", "pallet-dip-provider/runtime-benchmarks", @@ -143,5 +133,4 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-system-benchmarking/runtime-benchmarks", - "hex-literal" ] diff --git a/pallets/pallet-dip-consumer/Cargo.toml b/pallets/pallet-dip-consumer/Cargo.toml index ac4758d3f1..edfd082d6f 100644 --- a/pallets/pallet-dip-consumer/Cargo.toml +++ b/pallets/pallet-dip-consumer/Cargo.toml @@ -25,12 +25,10 @@ frame-system.workspace = true kilt-support.workspace = true parity-scale-codec = {workspace = true, features = ["derive"]} scale-info = {workspace = true, features = ["derive"]} -sp-core.workspace = true sp-std.workspace = true # Benchmarks frame-benchmarking = {workspace = true, optional = true} -sp-runtime = {workspace = true, optional = true} [features] default = [ "std" ] @@ -48,10 +46,8 @@ std = [ "kilt-support/std", "parity-scale-codec/std", "scale-info/std", - "sp-core/std", "sp-std/std", "frame-benchmarking?/std", - "sp-runtime?/std", ] -try-runtime = [] +try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/pallet-dip-provider/Cargo.toml b/pallets/pallet-dip-provider/Cargo.toml index 6e284e0d1c..e6784055b6 100644 --- a/pallets/pallet-dip-provider/Cargo.toml +++ b/pallets/pallet-dip-provider/Cargo.toml @@ -26,7 +26,6 @@ frame-system.workspace = true kilt-support.workspace = true parity-scale-codec = {workspace = true, features = ["derive"]} scale-info = {workspace = true, features = ["derive"]} -sp-core.workspace = true sp-std.workspace = true # Benchmarks @@ -51,10 +50,9 @@ std = [ "kilt-support/std", "parity-scale-codec/std", "scale-info/std", - "sp-core/std", "sp-std/std", "frame-benchmarking?/std", "sp-runtime?/std", ] -try-runtime = [ "did/try-runtime", "kilt-support/try-runtime" ] +try-runtime = [ "did/try-runtime", "frame-support/try-runtime", "kilt-support/try-runtime" ] From c5aa5a9e7bbc83ba9078c23abbae6f618f229e41 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Fri, 9 Feb 2024 14:27:59 +0100 Subject: [PATCH 39/45] Rename intermediate structs --- crates/kilt-dip-primitives/src/merkle/v0.rs | 58 +++++++++---------- .../src/verifier/parachain.rs | 9 ++- .../src/verifier/relaychain.rs | 6 +- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index a7695f58c7..f3afacc34e 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -282,7 +282,7 @@ impl< self, block_hash: &OutputOf, ) -> Result< - DipDidProofWithVerifiedRelayStateRoot< + RelayDipDidProofWithVerifiedRelayStateRoot< OutputOf, RelayBlockNumber, KiltDidKeyId, @@ -297,7 +297,7 @@ impl< return Err(Error::InvalidRelayHeader); } - Ok(DipDidProofWithVerifiedRelayStateRoot { + Ok(RelayDipDidProofWithVerifiedRelayStateRoot { relay_state_root: self.relay_header.state_root, provider_head_proof: self.provider_head_proof, dip_commitment_proof: self.dip_commitment_proof, @@ -316,7 +316,7 @@ impl< pub fn verify_relay_header( self, ) -> Result< - DipDidProofWithVerifiedRelayStateRoot< + RelayDipDidProofWithVerifiedRelayStateRoot< OutputOf, RelayBlockNumber, KiltDidKeyId, @@ -348,7 +348,7 @@ impl< /// * `KiltLinkableAccountId`: The linkable account ID type configured by the /// KILT chain. #[derive(Debug)] -pub struct DipDidProofWithVerifiedRelayStateRoot< +pub struct RelayDipDidProofWithVerifiedRelayStateRoot< StateRoot, RelayBlockNumber, KiltDidKeyId, @@ -380,7 +380,7 @@ impl< KiltWeb3Name, KiltLinkableAccountId, > - DipDidProofWithVerifiedRelayStateRoot< + RelayDipDidProofWithVerifiedRelayStateRoot< StateRoot, RelayBlockNumber, KiltDidKeyId, @@ -403,7 +403,7 @@ impl< self, provider_para_id: u32, ) -> Result< - DipDidProofWithoutRelayProof< + DipDidProofWithVerifiedRelayStateRoot< OutputOf, KiltDidKeyId, KiltAccountId, @@ -537,7 +537,7 @@ impl< provider_para_id: u32, relay_state_root: &OutputOf, ) -> Result< - DipDidProofWithoutRelayProof< + DipDidProofWithVerifiedRelayStateRoot< OutputOf, KiltDidKeyId, KiltAccountId, @@ -573,7 +573,7 @@ impl< let provider_header = provider_header_result.map_err(Error::ParaHeadMerkleProof)?; } } - Ok(DipDidProofWithoutRelayProof { + Ok(DipDidProofWithVerifiedRelayStateRoot { state_root: *provider_header.state_root(), dip_commitment_proof: self.dip_commitment_proof, dip_proof: self.dip_proof, @@ -597,7 +597,7 @@ impl< self, provider_para_id: u32, ) -> Result< - DipDidProofWithoutRelayProof< + DipDidProofWithVerifiedRelayStateRoot< OutputOf, KiltDidKeyId, KiltAccountId, @@ -642,7 +642,7 @@ impl< /// * `ConsumerBlockNumber`: The `BlockNumber` definition of the consumer /// parachain. #[derive(Debug)] -pub struct DipDidProofWithoutRelayProof< +pub struct DipDidProofWithVerifiedRelayStateRoot< StateRoot, KiltDidKeyId, KiltAccountId, @@ -671,7 +671,7 @@ impl< KiltLinkableAccountId, ConsumerBlockNumber, > - DipDidProofWithoutRelayProof< + DipDidProofWithVerifiedRelayStateRoot< StateRoot, KiltDidKeyId, KiltAccountId, @@ -693,7 +693,7 @@ impl< self, subject: &ProviderRuntime::Identifier, ) -> Result< - DipDidProofWithVerifiedCommitment< + DipDidProofWithVerifiedSubjectCommitment< IdentityCommitmentOf, KiltDidKeyId, KiltAccountId, @@ -725,7 +725,7 @@ impl< let dip_commitment = dip_commitment_result.map_err(Error::DipCommitmentMerkleProof)?; } } - Ok(DipDidProofWithVerifiedCommitment { + Ok(DipDidProofWithVerifiedSubjectCommitment { dip_commitment, dip_proof: self.dip_proof, signature: self.signature, @@ -748,7 +748,7 @@ impl< /// * `ConsumerBlockNumber`: The `BlockNumber` definition of the consumer /// parachain. #[derive(Debug)] -pub struct DipDidProofWithVerifiedCommitment< +pub struct DipDidProofWithVerifiedSubjectCommitment< Commitment, KiltDidKeyId, KiltAccountId, @@ -775,7 +775,7 @@ impl< KiltLinkableAccountId, ConsumerBlockNumber, > - DipDidProofWithVerifiedCommitment< + DipDidProofWithVerifiedSubjectCommitment< Commitment, KiltDidKeyId, KiltAccountId, @@ -800,7 +800,7 @@ impl< pub fn verify_dip_proof( self, ) -> Result< - DipDetailsAndUnverifiedDidSignatureTime< + DipRevealedDetailsAndUnverifiedDidSignature< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -843,7 +843,7 @@ impl< Error::Internal })?; - Ok(DipDetailsAndUnverifiedDidSignatureTime { + Ok(DipRevealedDetailsAndUnverifiedDidSignature { revealed_leaves, signature: self.signature, }) @@ -865,7 +865,7 @@ impl< /// * `MAX_REVEALED_LEAVES_COUNT`: The maximum number of leaves revealable in /// the proof. #[derive(Debug)] -pub struct DipDetailsAndUnverifiedDidSignatureTime< +pub struct DipRevealedDetailsAndUnverifiedDidSignature< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -892,7 +892,7 @@ impl< ConsumerBlockNumber, const MAX_REVEALED_LEAVES_COUNT: u32, > - DipDetailsAndUnverifiedDidSignatureTime< + DipRevealedDetailsAndUnverifiedDidSignature< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -909,7 +909,7 @@ impl< self, block_number: &ConsumerBlockNumber, ) -> Result< - DipDetailsAndUnverifiedDidSignaturePayload< + DipRevealedDetailsAndVerifiedDidSignatureFreshness< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -926,7 +926,7 @@ impl< frame_support::ensure!(self.signature.valid_until >= *block_number, Error::InvalidSignatureTime); } } - Ok(DipDetailsAndUnverifiedDidSignaturePayload { + Ok(DipRevealedDetailsAndVerifiedDidSignatureFreshness { revealed_leaves: self.revealed_leaves, signature: self.signature.signature, }) @@ -947,7 +947,7 @@ impl< /// * `MAX_REVEALED_LEAVES_COUNT`: The maximum number of leaves revealable in /// the proof. #[derive(Debug)] -pub struct DipDetailsAndUnverifiedDidSignaturePayload< +pub struct DipRevealedDetailsAndVerifiedDidSignatureFreshness< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -972,7 +972,7 @@ impl< KiltLinkableAccountId, const MAX_REVEALED_LEAVES_COUNT: u32, > - DipDetailsAndUnverifiedDidSignaturePayload< + DipRevealedDetailsAndVerifiedDidSignatureFreshness< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -989,7 +989,7 @@ impl< self, payload: &[u8], ) -> Result< - DipVerifiedInfo< + DipOriginInfo< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -1031,14 +1031,14 @@ impl< } else { cfg_if::cfg_if! { if #[cfg(feature = "runtime-benchmarks")] { - return Ok(DipVerifiedInfo::default()); + return Ok(DipOriginInfo::default()); } else { return Err(Error::InvalidDidKeyRevealed); } } }; - Ok(DipVerifiedInfo { + Ok(DipOriginInfo { revealed_leaves: signing_key_entry.0, signing_leaf_index: signing_key_entry.1, }) @@ -1048,7 +1048,7 @@ impl< /// Information, available as an origin, after the whole DIP proof has been /// verified. #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] -pub struct DipVerifiedInfo< +pub struct DipOriginInfo< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -1073,7 +1073,7 @@ impl< KiltLinkableAccountId, const MAX_REVEALED_LEAVES_COUNT: u32, > - DipVerifiedInfo< + DipOriginInfo< KiltDidKeyId, KiltAccountId, KiltBlockNumber, @@ -1125,7 +1125,7 @@ impl< KiltLinkableAccountId, const MAX_REVEALED_LEAVES_COUNT: u32, > Default - for DipVerifiedInfo< + for DipOriginInfo< KiltDidKeyId, KiltAccountId, KiltBlockNumber, diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 89568698c0..79ccd1bf1b 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -24,14 +24,13 @@ use pallet_dip_provider::traits::IdentityCommitmentGenerator; use pallet_web3_names::Web3NameOf; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_std::fmt::Debug; -use sp_std::marker::PhantomData; +use sp_std::{fmt::Debug, marker::PhantomData}; use crate::{ merkle::v0::RevealedDidKey, traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, - DipVerifiedInfo, Error, + DipOriginInfo, Error, }; /// A KILT-specific DIP identity proof for a sibling consumer that supports @@ -209,7 +208,7 @@ impl< LinkableAccountId, BlockNumberFor, >; - type VerificationResult = DipVerifiedInfo< + type VerificationResult = DipOriginInfo< KeyIdOf, KiltRuntime::AccountId, BlockNumberFor, @@ -374,7 +373,7 @@ pub mod v0 { BlockNumberFor, >; - type VerificationResult = DipVerifiedInfo< + type VerificationResult = DipOriginInfo< KeyIdOf, KiltRuntime::AccountId, BlockNumberFor, diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index 8fb2ac6892..a034454387 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -32,7 +32,7 @@ use crate::{ merkle::v0::RevealedDidKey, traits::{DipCallOriginFilter, GetWithArg, GetWithoutArg, Incrementable}, utils::OutputOf, - DipVerifiedInfo, Error, + DipOriginInfo, Error, }; /// A KILT-specific DIP identity proof for a parent consumer that supports @@ -164,7 +164,7 @@ impl< Web3NameOf, LinkableAccountId, >; - type VerificationResult = DipVerifiedInfo< + type VerificationResult = DipOriginInfo< KeyIdOf, KiltRuntime::AccountId, BlockNumberFor, @@ -320,7 +320,7 @@ pub mod v0 { Web3NameOf, LinkableAccountId, >; - type VerificationResult = DipVerifiedInfo< + type VerificationResult = DipOriginInfo< KeyIdOf, KiltRuntime::AccountId, BlockNumberFor, From 72fc3cb7b6642b7e1690d3b2fcc328d66af12839 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 22 Feb 2024 07:51:23 +0100 Subject: [PATCH 40/45] Add comment about relaychain being Rococo --- dip-template/runtimes/dip-consumer/src/dip.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dip-template/runtimes/dip-consumer/src/dip.rs b/dip-template/runtimes/dip-consumer/src/dip.rs index 88ceb21368..7699f5beed 100644 --- a/dip-template/runtimes/dip-consumer/src/dip.rs +++ b/dip-template/runtimes/dip-consumer/src/dip.rs @@ -31,7 +31,7 @@ use sp_std::marker::PhantomData; use crate::{weights, AccountId, DidIdentifier, Runtime, RuntimeCall, RuntimeOrigin}; pub type MerkleProofVerifierOutput = >::VerificationResult; -/// The verifier logic assumes the provider is a sibling KILT parachain, and +/// The verifier logic assumes the provider is a sibling KILT parachain, the relaychain is a Rococo relaychain, and /// that a KILT subject can provide DIP proof that reveal at most 10 DID keys /// and 10 linked accounts (defaults provided by the /// `KiltVersionedParachainVerifier` type). Calls that do not pass the From 51ac90248dee095f66e6fba3488829e8b49acc40 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 22 Feb 2024 07:55:53 +0100 Subject: [PATCH 41/45] Add comments about 0 value --- crates/kilt-dip-primitives/src/merkle/v0.rs | 4 ++++ crates/kilt-dip-primitives/src/state_proofs/mod.rs | 4 ++++ crates/kilt-dip-primitives/src/verifier/parachain.rs | 4 ++++ crates/kilt-dip-primitives/src/verifier/relaychain.rs | 4 ++++ dip-template/runtimes/dip-consumer/src/dip.rs | 4 ++++ dip-template/runtimes/dip-provider/src/dip.rs | 4 ++++ pallets/pallet-deposit-storage/src/deposit.rs | 4 ++++ runtimes/common/src/dip/did.rs | 4 ++++ runtimes/common/src/dip/merkle.rs | 4 ++++ runtimes/peregrine/src/dip/deposit.rs | 4 ++++ 10 files changed, 40 insertions(+) diff --git a/crates/kilt-dip-primitives/src/merkle/v0.rs b/crates/kilt-dip-primitives/src/merkle/v0.rs index f3afacc34e..d6124bb767 100644 --- a/crates/kilt-dip-primitives/src/merkle/v0.rs +++ b/crates/kilt-dip-primitives/src/merkle/v0.rs @@ -199,6 +199,10 @@ pub enum Error { impl From for u8 { fn from(value: Error) -> Self { match value { + // DO NOT USE 0 + // Errors of different sub-parts are separated by a `u8::MAX`. + // A value of 0 would make it confusing whether it's the previous sub-part error (u8::MAX) + // or the new sub-part error (u8::MAX + 0). Error::InvalidRelayHeader => 1, Error::RelayBlockNotFound => 2, Error::RelayStateRootNotFound => 3, diff --git a/crates/kilt-dip-primitives/src/state_proofs/mod.rs b/crates/kilt-dip-primitives/src/state_proofs/mod.rs index 456ad06756..72a5a9c818 100644 --- a/crates/kilt-dip-primitives/src/state_proofs/mod.rs +++ b/crates/kilt-dip-primitives/src/state_proofs/mod.rs @@ -39,6 +39,10 @@ pub enum MerkleProofError { impl From for u8 { fn from(value: MerkleProofError) -> Self { match value { + // DO NOT USE 0 + // Errors of different sub-parts are separated by a `u8::MAX`. + // A value of 0 would make it confusing whether it's the previous sub-part error (u8::MAX) + // or the new sub-part error (u8::MAX + 0). MerkleProofError::InvalidProof => 1, MerkleProofError::RequiredLeafNotRevealed => 2, MerkleProofError::ResultDecoding => 3, diff --git a/crates/kilt-dip-primitives/src/verifier/parachain.rs b/crates/kilt-dip-primitives/src/verifier/parachain.rs index 79ccd1bf1b..817e4ad8f9 100644 --- a/crates/kilt-dip-primitives/src/verifier/parachain.rs +++ b/crates/kilt-dip-primitives/src/verifier/parachain.rs @@ -108,6 +108,10 @@ where { fn from(value: DipParachainStateProofVerifierError) -> Self { match value { + // DO NOT USE 0 + // Errors of different sub-parts are separated by a `u8::MAX`. + // A value of 0 would make it confusing whether it's the previous sub-part error (u8::MAX) + // or the new sub-part error (u8::MAX + 0). DipParachainStateProofVerifierError::UnsupportedVersion => 1, DipParachainStateProofVerifierError::ProofComponentTooLarge(component_id) => { u8::MAX as u16 + component_id as u16 diff --git a/crates/kilt-dip-primitives/src/verifier/relaychain.rs b/crates/kilt-dip-primitives/src/verifier/relaychain.rs index a034454387..a97d2e7e1e 100644 --- a/crates/kilt-dip-primitives/src/verifier/relaychain.rs +++ b/crates/kilt-dip-primitives/src/verifier/relaychain.rs @@ -76,6 +76,10 @@ where { fn from(value: DipRelaychainStateProofVerifierError) -> Self { match value { + // DO NOT USE 0 + // Errors of different sub-parts are separated by a `u8::MAX`. + // A value of 0 would make it confusing whether it's the previous sub-part error (u8::MAX) + // or the new sub-part error (u8::MAX + 0). DipRelaychainStateProofVerifierError::UnsupportedVersion => 1, DipRelaychainStateProofVerifierError::ProofComponentTooLarge(component_id) => { u8::MAX as u16 + component_id as u16 diff --git a/dip-template/runtimes/dip-consumer/src/dip.rs b/dip-template/runtimes/dip-consumer/src/dip.rs index 7699f5beed..1e6ec1daee 100644 --- a/dip-template/runtimes/dip-consumer/src/dip.rs +++ b/dip-template/runtimes/dip-consumer/src/dip.rs @@ -132,6 +132,10 @@ pub enum DipCallFilterError { impl From for u8 { fn from(value: DipCallFilterError) -> Self { match value { + // DO NOT USE 0 + // Errors of different sub-parts are separated by a `u8::MAX`. + // A value of 0 would make it confusing whether it's the previous sub-part error (u8::MAX) + // or the new sub-part error (u8::MAX + 0). DipCallFilterError::BadOrigin => 1, DipCallFilterError::WrongVerificationRelationship => 2, } diff --git a/dip-template/runtimes/dip-provider/src/dip.rs b/dip-template/runtimes/dip-provider/src/dip.rs index c304dfd023..4480940671 100644 --- a/dip-template/runtimes/dip-provider/src/dip.rs +++ b/dip-template/runtimes/dip-provider/src/dip.rs @@ -127,6 +127,10 @@ pub mod deposit { impl From for u16 { fn from(value: CommitmentDepositRemovalHookError) -> Self { match value { + // DO NOT USE 0 + // Errors of different sub-parts are separated by a `u8::MAX`. + // A value of 0 would make it confusing whether it's the previous sub-part error (u8::MAX) + // or the new sub-part error (u8::MAX + 0). CommitmentDepositRemovalHookError::DecodeKey => 1, CommitmentDepositRemovalHookError::Internal => u16::MAX, } diff --git a/pallets/pallet-deposit-storage/src/deposit.rs b/pallets/pallet-deposit-storage/src/deposit.rs index 968bdee151..53f1a25859 100644 --- a/pallets/pallet-deposit-storage/src/deposit.rs +++ b/pallets/pallet-deposit-storage/src/deposit.rs @@ -59,6 +59,10 @@ pub enum FixedDepositCollectorViaDepositsPalletError { impl From for u16 { fn from(value: FixedDepositCollectorViaDepositsPalletError) -> Self { match value { + // DO NOT USE 0 + // Errors of different sub-parts are separated by a `u8::MAX`. + // A value of 0 would make it confusing whether it's the previous sub-part error (u8::MAX) + // or the new sub-part error (u8::MAX + 0). FixedDepositCollectorViaDepositsPalletError::DepositAlreadyTaken => 1, FixedDepositCollectorViaDepositsPalletError::DepositNotFound => 2, FixedDepositCollectorViaDepositsPalletError::FailedToHold => 3, diff --git a/runtimes/common/src/dip/did.rs b/runtimes/common/src/dip/did.rs index fe3297c7c3..212166cdc1 100644 --- a/runtimes/common/src/dip/did.rs +++ b/runtimes/common/src/dip/did.rs @@ -42,6 +42,10 @@ pub enum LinkedDidInfoProviderError { impl From for u16 { fn from(value: LinkedDidInfoProviderError) -> Self { match value { + // DO NOT USE 0 + // Errors of different sub-parts are separated by a `u8::MAX`. + // A value of 0 would make it confusing whether it's the previous sub-part error (u8::MAX) + // or the new sub-part error (u8::MAX + 0). LinkedDidInfoProviderError::DidNotFound => 1, LinkedDidInfoProviderError::DidDeleted => 2, LinkedDidInfoProviderError::TooManyLinkedAccounts => 3, diff --git a/runtimes/common/src/dip/merkle.rs b/runtimes/common/src/dip/merkle.rs index 5a0845d3a0..73f92e83d6 100644 --- a/runtimes/common/src/dip/merkle.rs +++ b/runtimes/common/src/dip/merkle.rs @@ -64,6 +64,10 @@ pub enum DidMerkleProofError { impl From for u16 { fn from(value: DidMerkleProofError) -> Self { match value { + // DO NOT USE 0 + // Errors of different sub-parts are separated by a `u8::MAX`. + // A value of 0 would make it confusing whether it's the previous sub-part error (u8::MAX) + // or the new sub-part error (u8::MAX + 0). DidMerkleProofError::UnsupportedVersion => 1, DidMerkleProofError::KeyNotFound => 2, DidMerkleProofError::LinkedAccountNotFound => 3, diff --git a/runtimes/peregrine/src/dip/deposit.rs b/runtimes/peregrine/src/dip/deposit.rs index 56eeebb36f..4cec3f934a 100644 --- a/runtimes/peregrine/src/dip/deposit.rs +++ b/runtimes/peregrine/src/dip/deposit.rs @@ -74,6 +74,10 @@ pub enum CommitmentDepositRemovalHookError { impl From for u16 { fn from(value: CommitmentDepositRemovalHookError) -> Self { match value { + // DO NOT USE 0 + // Errors of different sub-parts are separated by a `u8::MAX`. + // A value of 0 would make it confusing whether it's the previous sub-part error (u8::MAX) + // or the new sub-part error (u8::MAX + 0). CommitmentDepositRemovalHookError::DecodeKey => 1, CommitmentDepositRemovalHookError::Internal => u16::MAX, } From aea6b93cd22f7e3aaf31bbf65a44b94b93e418cc Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 22 Feb 2024 07:56:24 +0100 Subject: [PATCH 42/45] Grammar fix --- crates/kilt-dip-primitives/src/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/kilt-dip-primitives/src/traits.rs b/crates/kilt-dip-primitives/src/traits.rs index 1b53ccb388..f6425ba164 100644 --- a/crates/kilt-dip-primitives/src/traits.rs +++ b/crates/kilt-dip-primitives/src/traits.rs @@ -65,7 +65,7 @@ pub trait GetWithArg { fn get(arg: &Arg) -> Self::Result; } -/// Implementor of the [`GetWithArg`] trait that return the state +/// Implementer of the [`GetWithArg`] trait that return the state /// root of a relaychain block with a given number by retrieving it from the /// [`pallet_relay_store::Pallet`] pallet storage. It hardcodes the /// relaychain `BlockNumber`, `Hasher`, `StorageKey`, and `ParaId` to the From e20c96d21fb38dc1a812dac90dd7c1b2b2db70d0 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 22 Feb 2024 08:03:38 +0100 Subject: [PATCH 43/45] Add copyright notice about Parity source code --- crates/kilt-dip-primitives/src/state_proofs/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/kilt-dip-primitives/src/state_proofs/mod.rs b/crates/kilt-dip-primitives/src/state_proofs/mod.rs index 72a5a9c818..b367ab6371 100644 --- a/crates/kilt-dip-primitives/src/state_proofs/mod.rs +++ b/crates/kilt-dip-primitives/src/state_proofs/mod.rs @@ -24,7 +24,8 @@ use sp_trie::StorageProof; use crate::{state_proofs::substrate_no_std_port::read_proof_check, utils::OutputOf}; -// Ported from https://github.com/paritytech/substrate/blob/b27c470eaff379f512d1dec052aff5d551ed3b03/primitives/state-machine/src/lib.rs#L1076 +// Ported and adapted from [https://github.com/paritytech/substrate/blob/polkadot-v1.0.0/primitives/state-machine/src/lib.rs](https://github.com/paritytech/substrate/blob/polkadot-v1.0.0/primitives/state-machine/src/lib.rs). +// Refer to the original source file for full license details. // Needs to be replaced with its runtime-friendly version when available, or be // kept up-to-date with upstream. mod substrate_no_std_port; From 287116e1ee7f8e90bfbe6b30a0d81f14a7f1c37b Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 22 Feb 2024 08:39:22 +0100 Subject: [PATCH 44/45] Fix benchmarking feature --- dip-template/runtimes/dip-consumer/Cargo.toml | 2 +- dip-template/runtimes/dip-provider/Cargo.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dip-template/runtimes/dip-consumer/Cargo.toml b/dip-template/runtimes/dip-consumer/Cargo.toml index 50826ec7bc..e2f22e4f76 100644 --- a/dip-template/runtimes/dip-consumer/Cargo.toml +++ b/dip-template/runtimes/dip-consumer/Cargo.toml @@ -113,7 +113,7 @@ std = [ "parachain-info/std", "rococo-runtime/std", "frame-benchmarking/std", - "frame-system-benchmarking/std", + "frame-system-benchmarking?/std", ] runtime-benchmarks = [ diff --git a/dip-template/runtimes/dip-provider/Cargo.toml b/dip-template/runtimes/dip-provider/Cargo.toml index 951ec323fc..94a736ad75 100644 --- a/dip-template/runtimes/dip-provider/Cargo.toml +++ b/dip-template/runtimes/dip-provider/Cargo.toml @@ -115,6 +115,7 @@ std = [ "pallet-collator-selection/std", "parachain-info/std", "frame-benchmarking?/std", + "frame-system-benchmarking?/std", ] runtime-benchmarks = [ "did/runtime-benchmarks", From 493fda8d9dfac7383bcabaff2988fad66bfb25b6 Mon Sep 17 00:00:00 2001 From: Antonio Antonino Date: Thu, 22 Feb 2024 08:42:04 +0100 Subject: [PATCH 45/45] Fix docs generation --- crates/kilt-dip-primitives/src/state_proofs/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/kilt-dip-primitives/src/state_proofs/mod.rs b/crates/kilt-dip-primitives/src/state_proofs/mod.rs index b367ab6371..2f8eb4c531 100644 --- a/crates/kilt-dip-primitives/src/state_proofs/mod.rs +++ b/crates/kilt-dip-primitives/src/state_proofs/mod.rs @@ -24,7 +24,7 @@ use sp_trie::StorageProof; use crate::{state_proofs::substrate_no_std_port::read_proof_check, utils::OutputOf}; -// Ported and adapted from [https://github.com/paritytech/substrate/blob/polkadot-v1.0.0/primitives/state-machine/src/lib.rs](https://github.com/paritytech/substrate/blob/polkadot-v1.0.0/primitives/state-machine/src/lib.rs). +// Ported and adapted from . // Refer to the original source file for full license details. // Needs to be replaced with its runtime-friendly version when available, or be // kept up-to-date with upstream. @@ -80,7 +80,7 @@ where /// * `MerkleHasher`: defines the hashing algorithm used to calculate the Merkle /// root. /// * `TransformResult`: the type returned by the provided decoding function, if -/// successful. The `None` result is interpreted as an error, so it is not possible to return a type for which `None` would be a correct decoding, for now. See https://github.com/rust-lang/rust/issues/103765 for more details. +/// successful. The `None` result is interpreted as an error, so it is not possible to return a type for which `None` would be a correct decoding, for now. See for more details. pub fn verify_storage_value_proof_with_decoder( storage_key: &StorageKey, state_root: OutputOf,