diff --git a/Cargo.lock b/Cargo.lock
index a5aef17c56..8915054d6e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6491,6 +6491,7 @@ dependencies = [
"frame-system",
"parity-scale-codec",
"scale-info",
+ "sp-io",
"sp-std",
]
diff --git a/crates/kilt-dip-support/src/export/child.rs b/crates/kilt-dip-support/src/export/child.rs
new file mode 100644
index 0000000000..c238080099
--- /dev/null
+++ b/crates/kilt-dip-support/src/export/child.rs
@@ -0,0 +1,553 @@
+// 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 did::{did_details::DidVerificationKey, DidVerificationKeyRelationship};
+use pallet_dip_consumer::traits::IdentityProofVerifier;
+use parity_scale_codec::{Codec, Decode, Encode, HasCompact};
+use scale_info::TypeInfo;
+use sp_core::{RuntimeDebug, U256};
+use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedSub, Get, Hash, MaybeDisplay, Member, SimpleBitOps};
+use sp_std::{marker::PhantomData, vec::Vec};
+
+use crate::{
+ did::RevealedDidKeysSignatureAndCallVerifierError,
+ merkle::{DidMerkleProofVerifierError, RevealedDidMerkleProofLeaf, RevealedDidMerkleProofLeaves},
+ state_proofs::{parachain::DipIdentityCommitmentProofVerifierError, relay_chain::ParachainHeadProofVerifierError},
+ traits::{
+ Bump, DidSignatureVerifierContext, DipCallOriginFilter, HistoricalBlockRegistry, ProviderParachainStateInfo,
+ RelayChainStorageInfo,
+ },
+ utils::OutputOf,
+};
+
+#[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)]
+#[non_exhaustive]
+pub enum VersionedChildParachainDipStateProof<
+ ParentBlockHeight: Copy + Into + TryFrom,
+ ParentBlockHasher: Hash,
+ DipMerkleProofBlindedValues,
+ DipMerkleProofRevealedLeaf,
+> {
+ V0(
+ v0::ChildParachainDipStateProof<
+ ParentBlockHeight,
+ ParentBlockHasher,
+ DipMerkleProofBlindedValues,
+ DipMerkleProofRevealedLeaf,
+ >,
+ ),
+}
+
+pub enum DipChildProviderStateProofVerifierError<
+ ParachainHeadMerkleProofVerificationError,
+ IdentityCommitmentMerkleProofVerificationError,
+ DipProofVerificationError,
+ DidSignatureVerificationError,
+> {
+ UnsupportedVersion,
+ InvalidBlockHeight,
+ InvalidBlockHash,
+ ParachainHeadMerkleProof(ParachainHeadMerkleProofVerificationError),
+ IdentityCommitmentMerkleProof(IdentityCommitmentMerkleProofVerificationError),
+ DipProof(DipProofVerificationError),
+ DidSignature(DidSignatureVerificationError),
+}
+
+impl<
+ ParachainHeadMerkleProofVerificationError,
+ IdentityCommitmentMerkleProofVerificationError,
+ DipProofVerificationError,
+ DidSignatureVerificationError,
+ >
+ From<
+ DipChildProviderStateProofVerifierError<
+ ParachainHeadMerkleProofVerificationError,
+ IdentityCommitmentMerkleProofVerificationError,
+ DipProofVerificationError,
+ DidSignatureVerificationError,
+ >,
+ > for u16
+where
+ ParachainHeadMerkleProofVerificationError: Into,
+ IdentityCommitmentMerkleProofVerificationError: Into,
+ DipProofVerificationError: Into,
+ DidSignatureVerificationError: Into,
+{
+ fn from(
+ value: DipChildProviderStateProofVerifierError<
+ ParachainHeadMerkleProofVerificationError,
+ IdentityCommitmentMerkleProofVerificationError,
+ DipProofVerificationError,
+ DidSignatureVerificationError,
+ >,
+ ) -> Self {
+ match value {
+ DipChildProviderStateProofVerifierError::UnsupportedVersion => 0,
+ DipChildProviderStateProofVerifierError::InvalidBlockHeight => 1,
+ DipChildProviderStateProofVerifierError::InvalidBlockHash => 2,
+ DipChildProviderStateProofVerifierError::ParachainHeadMerkleProof(error) => {
+ u8::MAX as u16 + error.into() as u16
+ }
+ DipChildProviderStateProofVerifierError::IdentityCommitmentMerkleProof(error) => {
+ u8::MAX as u16 * 2 + error.into() as u16
+ }
+ DipChildProviderStateProofVerifierError::DipProof(error) => u8::MAX as u16 * 3 + error.into() as u16,
+ DipChildProviderStateProofVerifierError::DidSignature(error) => u8::MAX as u16 * 4 + error.into() as u16,
+ }
+ }
+}
+
+pub struct VersionedDipChildProviderStateProofVerifier<
+ RelayChainInfo,
+ ChildProviderParachainId,
+ ChildProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ const MAX_REVEALED_KEYS_COUNT: u32,
+ const MAX_REVEALED_ACCOUNTS_COUNT: u32,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+>(
+ #[allow(clippy::type_complexity)]
+ PhantomData<(
+ RelayChainInfo,
+ ChildProviderParachainId,
+ ChildProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ )>,
+);
+
+impl<
+ Call,
+ Subject,
+ RelayChainInfo,
+ ChildProviderParachainId,
+ ChildProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ const MAX_REVEALED_KEYS_COUNT: u32,
+ const MAX_REVEALED_ACCOUNTS_COUNT: u32,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ > IdentityProofVerifier
+ for VersionedDipChildProviderStateProofVerifier<
+ RelayChainInfo,
+ ChildProviderParachainId,
+ ChildProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ > where
+ Call: Encode,
+ TxSubmitter: Encode,
+
+ RelayChainInfo: RelayChainStorageInfo
+ + HistoricalBlockRegistry<
+ BlockNumber = ::BlockNumber,
+ Hasher = ::Hasher,
+ >,
+ 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,
+ RelayChainInfo::Key: AsRef<[u8]>,
+
+ ChildProviderParachainId: Get,
+
+ ChildProviderStateInfo: ProviderParachainStateInfo,
+ OutputOf: Ord + From::Hasher>>,
+ ChildProviderStateInfo::BlockNumber: Encode + Clone,
+ ChildProviderStateInfo::Commitment: Decode,
+ ChildProviderStateInfo::Key: AsRef<[u8]>,
+
+ LocalContextProvider:
+ DidSignatureVerifierContext::BlockNumber>,
+ LocalContextProvider::BlockNumber: CheckedSub + From,
+ LocalContextProvider::Hash: Encode,
+ LocalContextProvider::SignedExtra: Encode,
+ LocalDidDetails: Bump + Default + Encode,
+ LocalDidCallVerifier:
+ DipCallOriginFilter, DidVerificationKeyRelationship)>,
+
+ ProviderDipMerkleHasher: sp_core::Hasher,
+ ProviderDidKeyId: Encode + Clone + Into,
+ ProviderAccountId: Encode + Clone,
+ ProviderLinkedAccountId: Encode + Clone,
+ ProviderWeb3Name: Encode + Clone,
+{
+ type Error = DipChildProviderStateProofVerifierError<
+ ParachainHeadProofVerifierError,
+ DipIdentityCommitmentProofVerifierError,
+ DidMerkleProofVerifierError,
+ RevealedDidKeysSignatureAndCallVerifierError,
+ >;
+ type IdentityDetails = LocalDidDetails;
+ type Proof = VersionedChildParachainDipStateProof<
+ ::BlockNumber,
+ ::Hasher,
+ Vec>,
+ RevealedDidMerkleProofLeaf<
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ChildProviderStateInfo::BlockNumber,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ >,
+ >;
+ type Submitter = TxSubmitter;
+ type VerificationResult = RevealedDidMerkleProofLeaves<
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ChildProviderStateInfo::BlockNumber,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ >;
+
+ fn verify_proof_for_call_against_details(
+ call: &Call,
+ subject: &Subject,
+ submitter: &Self::Submitter,
+ identity_details: &mut Option,
+ proof: Self::Proof,
+ ) -> Result {
+ match proof {
+ VersionedChildParachainDipStateProof::V0(v0_proof) => {
+ v0::DipChildProviderStateProofVerifier::<
+ RelayChainInfo,
+ ChildProviderParachainId,
+ ChildProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ >::verify_proof_for_call_against_details(call, subject, submitter, identity_details, v0_proof)
+ }
+ }
+ }
+}
+
+pub mod latest {
+ pub use super::v0::ChildParachainDipStateProof;
+}
+
+mod v0 {
+ use super::*;
+
+ use parity_scale_codec::Codec;
+ use sp_runtime::{
+ generic::Header,
+ traits::{AtLeast32BitUnsigned, Hash, MaybeDisplay, Member, SimpleBitOps},
+ };
+ use sp_std::{borrow::Borrow, vec::Vec};
+
+ use crate::{
+ did::{
+ RevealedDidKeysAndSignature, RevealedDidKeysSignatureAndCallVerifier,
+ RevealedDidKeysSignatureAndCallVerifierError,
+ },
+ export::common::v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof},
+ merkle::{
+ DidMerkleProofVerifier, DidMerkleProofVerifierError, RevealedDidMerkleProofLeaf,
+ RevealedDidMerkleProofLeaves,
+ },
+ state_proofs::{
+ parachain::{DipIdentityCommitmentProofVerifier, DipIdentityCommitmentProofVerifierError},
+ relay_chain::{ParachainHeadProofVerifier, ParachainHeadProofVerifierError},
+ },
+ traits::{
+ Bump, DidSignatureVerifierContext, DipCallOriginFilter, HistoricalBlockRegistry,
+ ProviderParachainStateInfo, RelayChainStorageInfo,
+ },
+ utils::OutputOf,
+ };
+
+ #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
+ pub struct ChildParachainDipStateProof<
+ ParentBlockHeight: Copy + Into + TryFrom,
+ ParentBlockHasher: Hash,
+ DipMerkleProofBlindedValues,
+ DipMerkleProofRevealedLeaf,
+ > {
+ para_state_root: ParachainRootStateProof,
+ relay_header: Header,
+ dip_identity_commitment: Vec>,
+ did: DipMerkleProofAndDidSignature,
+ }
+
+ pub struct DipChildProviderStateProofVerifier<
+ RelayChainInfo,
+ ChildProviderParachainId,
+ ChildProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ const MAX_REVEALED_KEYS_COUNT: u32,
+ const MAX_REVEALED_ACCOUNTS_COUNT: u32,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ >(
+ #[allow(clippy::type_complexity)]
+ PhantomData<(
+ RelayChainInfo,
+ ChildProviderParachainId,
+ ChildProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ )>,
+ );
+
+ impl<
+ Call,
+ Subject,
+ RelayChainInfo,
+ ChildProviderParachainId,
+ ChildProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ const MAX_REVEALED_KEYS_COUNT: u32,
+ const MAX_REVEALED_ACCOUNTS_COUNT: u32,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ > IdentityProofVerifier
+ for DipChildProviderStateProofVerifier<
+ RelayChainInfo,
+ ChildProviderParachainId,
+ ChildProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ > where
+ Call: Encode,
+ TxSubmitter: Encode,
+
+ RelayChainInfo: RelayChainStorageInfo
+ + HistoricalBlockRegistry<
+ BlockNumber = ::BlockNumber,
+ Hasher = ::Hasher,
+ >,
+ 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,
+ RelayChainInfo::Key: AsRef<[u8]>,
+
+ ChildProviderParachainId: Get,
+
+ ChildProviderStateInfo:
+ ProviderParachainStateInfo,
+ OutputOf:
+ Ord + From::Hasher>>,
+ ChildProviderStateInfo::BlockNumber: Encode + Clone,
+ ChildProviderStateInfo::Commitment: Decode,
+ ChildProviderStateInfo::Key: AsRef<[u8]>,
+
+ LocalContextProvider:
+ DidSignatureVerifierContext::BlockNumber>,
+ LocalContextProvider::BlockNumber: CheckedSub + From,
+ LocalContextProvider::Hash: Encode,
+ LocalContextProvider::SignedExtra: Encode,
+ LocalDidDetails: Bump + Default + Encode,
+ LocalDidCallVerifier: DipCallOriginFilter<
+ Call,
+ OriginInfo = (DidVerificationKey, DidVerificationKeyRelationship),
+ >,
+
+ ProviderDipMerkleHasher: sp_core::Hasher,
+ ProviderDidKeyId: Encode + Clone + Into,
+ ProviderAccountId: Encode + Clone,
+ ProviderLinkedAccountId: Encode + Clone,
+ ProviderWeb3Name: Encode + Clone,
+ {
+ type Error = DipChildProviderStateProofVerifierError<
+ ParachainHeadProofVerifierError,
+ DipIdentityCommitmentProofVerifierError,
+ DidMerkleProofVerifierError,
+ RevealedDidKeysSignatureAndCallVerifierError,
+ >;
+ type IdentityDetails = LocalDidDetails;
+ type Proof = ChildParachainDipStateProof<
+ ::BlockNumber,
+ ::Hasher,
+ Vec>,
+ RevealedDidMerkleProofLeaf<
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ChildProviderStateInfo::BlockNumber,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ >,
+ >;
+ type Submitter = TxSubmitter;
+ type VerificationResult = RevealedDidMerkleProofLeaves<
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ChildProviderStateInfo::BlockNumber,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ >;
+
+ fn verify_proof_for_call_against_details(
+ call: &Call,
+ subject: &Subject,
+ submitter: &Self::Submitter,
+ identity_details: &mut Option,
+ 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(DipChildProviderStateProofVerifierError::InvalidBlockHeight)?;
+
+ // 1.1 Verify that the provided header hashes to the same block has retrieved
+ if block_hash_at_height != proof.relay_header.hash() {
+ return Err(DipChildProviderStateProofVerifierError::InvalidBlockHash);
+ }
+ // 1.2 If so, extract the state root from the header
+ let state_root_at_height = proof.relay_header.state_root;
+
+ // FIXME: Compilation error
+ // 2. Verify relay chain proof
+ let provider_parachain_header =
+ ParachainHeadProofVerifier::::verify_proof_for_parachain_with_root(
+ &ChildProviderParachainId::get(),
+ &state_root_at_height,
+ proof.para_state_root.proof,
+ )
+ .map_err(DipChildProviderStateProofVerifierError::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(DipChildProviderStateProofVerifierError::IdentityCommitmentMerkleProof)?;
+
+ // 4. Verify DIP merkle proof.
+ let proof_leaves = DidMerkleProofVerifier::<
+ ProviderDipMerkleHasher,
+ _,
+ _,
+ _,
+ _,
+ _,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ >::verify_dip_merkle_proof(&subject_identity_commitment, proof.did.leaves)
+ .map_err(DipChildProviderStateProofVerifierError::DipProof)?;
+
+ // 5. Verify DID signature.
+ RevealedDidKeysSignatureAndCallVerifier::<
+ _,
+ _,
+ _,
+ _,
+ LocalContextProvider,
+ _,
+ _,
+ _,
+ LocalDidCallVerifier,
+ >::verify_did_signature_for_call(
+ call,
+ submitter,
+ identity_details,
+ RevealedDidKeysAndSignature {
+ merkle_leaves: proof_leaves.borrow(),
+ did_signature: proof.did.signature,
+ },
+ )
+ .map_err(DipChildProviderStateProofVerifierError::DidSignature)?;
+ Ok(proof_leaves)
+ }
+ }
+}
diff --git a/crates/kilt-dip-support/src/export/common.rs b/crates/kilt-dip-support/src/export/common.rs
new file mode 100644
index 0000000000..d0eff66d68
--- /dev/null
+++ b/crates/kilt-dip-support/src/export/common.rs
@@ -0,0 +1,42 @@
+// 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
+
+pub mod latest {
+ pub use super::v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof};
+}
+
+pub mod v0 {
+ use parity_scale_codec::{Decode, Encode};
+ use scale_info::TypeInfo;
+ use sp_core::RuntimeDebug;
+ use sp_std::vec::Vec;
+
+ use crate::{did::TimeBoundDidSignature, merkle::DidMerkleProof};
+
+ #[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, Clone)]
+ pub struct ParachainRootStateProof {
+ pub(crate) relay_block_height: RelayBlockHeight,
+ pub(crate) proof: Vec>,
+ }
+
+ #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)]
+ pub struct DipMerkleProofAndDidSignature {
+ pub(crate) leaves: DidMerkleProof,
+ pub(crate) signature: TimeBoundDidSignature,
+ }
+}
diff --git a/crates/kilt-dip-support/src/export/mod.rs b/crates/kilt-dip-support/src/export/mod.rs
new file mode 100644
index 0000000000..c6a92e7d5b
--- /dev/null
+++ b/crates/kilt-dip-support/src/export/mod.rs
@@ -0,0 +1,34 @@
+// 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
+
+mod child;
+mod common;
+mod sibling;
+
+pub use child::{
+ DipChildProviderStateProofVerifierError, VersionedChildParachainDipStateProof,
+ VersionedDipChildProviderStateProofVerifier,
+};
+pub use sibling::{
+ DipSiblingProviderStateProofVerifierError, VersionedDipSiblingProviderStateProofVerifier,
+ VersionedSiblingParachainDipStateProof,
+};
+
+pub mod latest {
+ pub use super::{child::latest::*, common::latest::*, sibling::latest::*};
+}
diff --git a/crates/kilt-dip-support/src/export/sibling.rs b/crates/kilt-dip-support/src/export/sibling.rs
new file mode 100644
index 0000000000..e0b3154c54
--- /dev/null
+++ b/crates/kilt-dip-support/src/export/sibling.rs
@@ -0,0 +1,497 @@
+// 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 did::{did_details::DidVerificationKey, DidVerificationKeyRelationship};
+use pallet_dip_consumer::traits::IdentityProofVerifier;
+use parity_scale_codec::{Decode, Encode, HasCompact};
+use scale_info::TypeInfo;
+use sp_core::{RuntimeDebug, U256};
+use sp_runtime::traits::{CheckedSub, Get};
+use sp_std::{marker::PhantomData, vec::Vec};
+
+use crate::{
+ did::RevealedDidKeysSignatureAndCallVerifierError,
+ merkle::{DidMerkleProofVerifierError, RevealedDidMerkleProofLeaf, RevealedDidMerkleProofLeaves},
+ state_proofs::{parachain::DipIdentityCommitmentProofVerifierError, relay_chain::ParachainHeadProofVerifierError},
+ traits::{self, Bump, DidSignatureVerifierContext, DipCallOriginFilter},
+ utils::OutputOf,
+};
+
+#[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)]
+#[non_exhaustive]
+pub enum VersionedSiblingParachainDipStateProof<
+ RelayBlockHeight,
+ DipMerkleProofBlindedValues,
+ DipMerkleProofRevealedLeaf,
+ LocalBlockNumber,
+> {
+ V0(
+ v0::SiblingParachainDipStateProof<
+ RelayBlockHeight,
+ DipMerkleProofBlindedValues,
+ DipMerkleProofRevealedLeaf,
+ LocalBlockNumber,
+ >,
+ ),
+}
+
+pub enum DipSiblingProviderStateProofVerifierError<
+ ParachainHeadMerkleProofVerificationError,
+ IdentityCommitmentMerkleProofVerificationError,
+ DipProofVerificationError,
+ DidSignatureVerificationError,
+> {
+ UnsupportedVersion,
+ ParachainHeadMerkleProof(ParachainHeadMerkleProofVerificationError),
+ IdentityCommitmentMerkleProof(IdentityCommitmentMerkleProofVerificationError),
+ DipProof(DipProofVerificationError),
+ DidSignature(DidSignatureVerificationError),
+}
+
+impl<
+ ParachainHeadMerkleProofVerificationError,
+ IdentityCommitmentMerkleProofVerificationError,
+ DipProofVerificationError,
+ DidSignatureVerificationError,
+ >
+ From<
+ DipSiblingProviderStateProofVerifierError<
+ ParachainHeadMerkleProofVerificationError,
+ IdentityCommitmentMerkleProofVerificationError,
+ DipProofVerificationError,
+ DidSignatureVerificationError,
+ >,
+ > for u16
+where
+ ParachainHeadMerkleProofVerificationError: Into,
+ IdentityCommitmentMerkleProofVerificationError: Into,
+ DipProofVerificationError: Into,
+ DidSignatureVerificationError: Into,
+{
+ fn from(
+ value: DipSiblingProviderStateProofVerifierError<
+ ParachainHeadMerkleProofVerificationError,
+ IdentityCommitmentMerkleProofVerificationError,
+ DipProofVerificationError,
+ DidSignatureVerificationError,
+ >,
+ ) -> Self {
+ match value {
+ DipSiblingProviderStateProofVerifierError::UnsupportedVersion => 0,
+ DipSiblingProviderStateProofVerifierError::ParachainHeadMerkleProof(error) => {
+ u8::MAX as u16 + error.into() as u16
+ }
+ DipSiblingProviderStateProofVerifierError::IdentityCommitmentMerkleProof(error) => {
+ u8::MAX as u16 * 2 + error.into() as u16
+ }
+ DipSiblingProviderStateProofVerifierError::DipProof(error) => u8::MAX as u16 * 3 + error.into() as u16,
+ DipSiblingProviderStateProofVerifierError::DidSignature(error) => u8::MAX as u16 * 4 + error.into() as u16,
+ }
+ }
+}
+
+pub struct VersionedDipSiblingProviderStateProofVerifier<
+ RelayChainStateInfo,
+ SiblingProviderParachainId,
+ SiblingProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ const MAX_REVEALED_KEYS_COUNT: u32,
+ const MAX_REVEALED_ACCOUNTS_COUNT: u32,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+>(
+ #[allow(clippy::type_complexity)]
+ PhantomData<(
+ RelayChainStateInfo,
+ SiblingProviderParachainId,
+ SiblingProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ )>,
+);
+
+impl<
+ Call,
+ Subject,
+ RelayChainStateInfo,
+ SiblingProviderParachainId,
+ SiblingProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ const MAX_REVEALED_KEYS_COUNT: u32,
+ const MAX_REVEALED_ACCOUNTS_COUNT: u32,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ > IdentityProofVerifier
+ for VersionedDipSiblingProviderStateProofVerifier<
+ RelayChainStateInfo,
+ SiblingProviderParachainId,
+ SiblingProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ > where
+ Call: Encode,
+ TxSubmitter: Encode,
+
+ RelayChainStateInfo: traits::RelayChainStorageInfo + traits::RelayChainStateInfo,
+ OutputOf: Ord,
+ RelayChainStateInfo::BlockNumber: Copy + Into + TryFrom + HasCompact,
+ RelayChainStateInfo::Key: AsRef<[u8]>,
+
+ SiblingProviderParachainId: Get,
+
+ SiblingProviderStateInfo:
+ traits::ProviderParachainStateInfo,
+ OutputOf: Ord + From>,
+ SiblingProviderStateInfo::BlockNumber: Encode + Clone,
+ SiblingProviderStateInfo::Commitment: Decode,
+ SiblingProviderStateInfo::Key: AsRef<[u8]>,
+
+ LocalContextProvider: DidSignatureVerifierContext,
+ LocalContextProvider::BlockNumber: Encode + CheckedSub + From + PartialOrd,
+ LocalContextProvider::Hash: Encode,
+ LocalContextProvider::SignedExtra: Encode,
+ LocalDidDetails: Bump + Default + Encode,
+ LocalDidCallVerifier:
+ DipCallOriginFilter, DidVerificationKeyRelationship)>,
+
+ ProviderDipMerkleHasher: sp_core::Hasher,
+ ProviderDidKeyId: Encode + Clone + Into,
+ ProviderAccountId: Encode + Clone,
+ ProviderLinkedAccountId: Encode + Clone,
+ ProviderWeb3Name: Encode + Clone,
+{
+ type Error = DipSiblingProviderStateProofVerifierError<
+ ParachainHeadProofVerifierError,
+ DipIdentityCommitmentProofVerifierError,
+ DidMerkleProofVerifierError,
+ RevealedDidKeysSignatureAndCallVerifierError,
+ >;
+ type IdentityDetails = LocalDidDetails;
+ type Proof = VersionedSiblingParachainDipStateProof<
+ RelayChainStateInfo::BlockNumber,
+ Vec>,
+ RevealedDidMerkleProofLeaf<
+ ProviderDidKeyId,
+ ProviderAccountId,
+ SiblingProviderStateInfo::BlockNumber,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ >,
+ LocalContextProvider::BlockNumber,
+ >;
+ type Submitter = TxSubmitter;
+ type VerificationResult = RevealedDidMerkleProofLeaves<
+ ProviderDidKeyId,
+ ProviderAccountId,
+ SiblingProviderStateInfo::BlockNumber,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ >;
+
+ fn verify_proof_for_call_against_details(
+ call: &Call,
+ subject: &Subject,
+ submitter: &Self::Submitter,
+ identity_details: &mut Option,
+ proof: Self::Proof,
+ ) -> Result {
+ match proof {
+ VersionedSiblingParachainDipStateProof::V0(v0_proof) => {
+ v0::DipSiblingProviderStateProofVerifier::<
+ RelayChainStateInfo,
+ SiblingProviderParachainId,
+ SiblingProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ >::verify_proof_for_call_against_details(call, subject, submitter, identity_details, v0_proof)
+ }
+ }
+ }
+}
+
+pub mod latest {
+ pub use super::v0::SiblingParachainDipStateProof;
+}
+
+mod v0 {
+ use super::*;
+
+ use sp_std::borrow::Borrow;
+
+ use crate::{
+ did::{RevealedDidKeysAndSignature, RevealedDidKeysSignatureAndCallVerifier},
+ export::common::v0::{DipMerkleProofAndDidSignature, ParachainRootStateProof},
+ merkle::DidMerkleProofVerifier,
+ state_proofs::{parachain::DipIdentityCommitmentProofVerifier, relay_chain::ParachainHeadProofVerifier},
+ traits::ProviderParachainStateInfo,
+ };
+
+ #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)]
+ pub struct SiblingParachainDipStateProof<
+ RelayBlockHeight,
+ DipMerkleProofBlindedValues,
+ DipMerkleProofRevealedLeaf,
+ LocalBlockNumber,
+ > {
+ para_state_root: ParachainRootStateProof,
+ dip_identity_commitment: Vec>,
+ did: DipMerkleProofAndDidSignature,
+ }
+
+ #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
+ pub struct DipSiblingProviderStateProofVerifier<
+ RelayChainStateInfo,
+ SiblingProviderParachainId,
+ SiblingProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ const MAX_REVEALED_KEYS_COUNT: u32,
+ const MAX_REVEALED_ACCOUNTS_COUNT: u32,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ >(
+ #[allow(clippy::type_complexity)]
+ PhantomData<(
+ RelayChainStateInfo,
+ SiblingProviderParachainId,
+ SiblingProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ )>,
+ );
+
+ impl<
+ Call,
+ Subject,
+ RelayChainStateInfo,
+ SiblingProviderParachainId,
+ SiblingProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ const MAX_REVEALED_KEYS_COUNT: u32,
+ const MAX_REVEALED_ACCOUNTS_COUNT: u32,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ > IdentityProofVerifier
+ for DipSiblingProviderStateProofVerifier<
+ RelayChainStateInfo,
+ SiblingProviderParachainId,
+ SiblingProviderStateInfo,
+ TxSubmitter,
+ ProviderDipMerkleHasher,
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ LocalDidDetails,
+ LocalContextProvider,
+ LocalDidCallVerifier,
+ > where
+ Call: Encode,
+ TxSubmitter: Encode,
+
+ RelayChainStateInfo: traits::RelayChainStorageInfo + traits::RelayChainStateInfo,
+ OutputOf: Ord,
+ RelayChainStateInfo::BlockNumber: Copy + Into + TryFrom + HasCompact,
+ RelayChainStateInfo::Key: AsRef<[u8]>,
+
+ SiblingProviderParachainId: Get,
+
+ SiblingProviderStateInfo:
+ traits::ProviderParachainStateInfo,
+ OutputOf: Ord + From>,
+ SiblingProviderStateInfo::BlockNumber: Encode + Clone,
+ SiblingProviderStateInfo::Commitment: Decode,
+ SiblingProviderStateInfo::Key: AsRef<[u8]>,
+
+ LocalContextProvider: DidSignatureVerifierContext,
+ LocalContextProvider::BlockNumber: Encode + CheckedSub + From + PartialOrd,
+ LocalContextProvider::Hash: Encode,
+ LocalContextProvider::SignedExtra: Encode,
+ LocalDidDetails: Bump + Default + Encode,
+ LocalDidCallVerifier: DipCallOriginFilter<
+ Call,
+ OriginInfo = (DidVerificationKey, DidVerificationKeyRelationship),
+ >,
+
+ ProviderDipMerkleHasher: sp_core::Hasher,
+ ProviderDidKeyId: Encode + Clone + Into,
+ ProviderAccountId: Encode + Clone,
+ ProviderLinkedAccountId: Encode + Clone,
+ ProviderWeb3Name: Encode + Clone,
+ {
+ type Error = DipSiblingProviderStateProofVerifierError<
+ ParachainHeadProofVerifierError,
+ DipIdentityCommitmentProofVerifierError,
+ DidMerkleProofVerifierError,
+ RevealedDidKeysSignatureAndCallVerifierError,
+ >;
+ type IdentityDetails = LocalDidDetails;
+ type Proof = SiblingParachainDipStateProof<
+ RelayChainStateInfo::BlockNumber,
+ Vec>,
+ RevealedDidMerkleProofLeaf<
+ ProviderDidKeyId,
+ ProviderAccountId,
+ SiblingProviderStateInfo::BlockNumber,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ >,
+ LocalContextProvider::BlockNumber,
+ >;
+ type Submitter = TxSubmitter;
+ type VerificationResult = RevealedDidMerkleProofLeaves<
+ ProviderDidKeyId,
+ ProviderAccountId,
+ SiblingProviderStateInfo::BlockNumber,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ >;
+
+ fn verify_proof_for_call_against_details(
+ call: &Call,
+ subject: &Subject,
+ submitter: &Self::Submitter,
+ identity_details: &mut Option,
+ proof: Self::Proof,
+ ) -> Result {
+ // 1. Verify relay chain proof.
+ let provider_parachain_header =
+ ParachainHeadProofVerifier::::verify_proof_for_parachain(
+ &SiblingProviderParachainId::get(),
+ &proof.para_state_root.relay_block_height,
+ proof.para_state_root.proof,
+ )
+ .map_err(DipSiblingProviderStateProofVerifierError::ParachainHeadMerkleProof)?;
+
+ // 2. 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(DipSiblingProviderStateProofVerifierError::IdentityCommitmentMerkleProof)?;
+
+ // 3. Verify DIP merkle proof.
+ let proof_leaves: RevealedDidMerkleProofLeaves<
+ ProviderDidKeyId,
+ ProviderAccountId,
+ ::BlockNumber,
+ ProviderWeb3Name,
+ ProviderLinkedAccountId,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ > = DidMerkleProofVerifier::<
+ ProviderDipMerkleHasher,
+ _,
+ _,
+ _,
+ _,
+ _,
+ MAX_REVEALED_KEYS_COUNT,
+ MAX_REVEALED_ACCOUNTS_COUNT,
+ >::verify_dip_merkle_proof(&subject_identity_commitment, proof.did.leaves)
+ .map_err(DipSiblingProviderStateProofVerifierError::DipProof)?;
+
+ // 4. Verify DID signature.
+ RevealedDidKeysSignatureAndCallVerifier::<
+ _,
+ _,
+ _,
+ _,
+ LocalContextProvider,
+ _,
+ _,
+ _,
+ LocalDidCallVerifier,
+ >::verify_did_signature_for_call(
+ call,
+ submitter,
+ identity_details,
+ RevealedDidKeysAndSignature {
+ merkle_leaves: proof_leaves.borrow(),
+ did_signature: proof.did.signature,
+ },
+ )
+ .map_err(DipSiblingProviderStateProofVerifierError::DidSignature)?;
+
+ Ok(proof_leaves)
+ }
+ }
+}
diff --git a/crates/kilt-dip-support/src/lib.rs b/crates/kilt-dip-support/src/lib.rs
index 0d0e80425e..2daacfc640 100644
--- a/crates/kilt-dip-support/src/lib.rs
+++ b/crates/kilt-dip-support/src/lib.rs
@@ -20,603 +20,13 @@
#![cfg_attr(not(feature = "std"), no_std)]
-use parity_scale_codec::{Codec, Decode, Encode, HasCompact};
-use scale_info::TypeInfo;
-use sp_core::{Get, RuntimeDebug, U256};
-use sp_runtime::{
- generic::Header,
- traits::{AtLeast32BitUnsigned, CheckedSub, Hash, MaybeDisplay, Member, SimpleBitOps},
-};
-use sp_std::{borrow::Borrow, marker::PhantomData, vec::Vec};
-
-use ::did::{did_details::DidVerificationKey, DidVerificationKeyRelationship};
-use pallet_dip_consumer::traits::IdentityProofVerifier;
-
-use crate::{
- did::{
- RevealedDidKeysAndSignature, RevealedDidKeysSignatureAndCallVerifier,
- RevealedDidKeysSignatureAndCallVerifierError, TimeBoundDidSignature,
- },
- merkle::{
- DidMerkleProof, DidMerkleProofVerifier, DidMerkleProofVerifierError, RevealedDidMerkleProofLeaf,
- RevealedDidMerkleProofLeaves,
- },
- state_proofs::{
- parachain::{DipIdentityCommitmentProofVerifier, DipIdentityCommitmentProofVerifierError},
- relay_chain::{ParachainHeadProofVerifier, ParachainHeadProofVerifierError},
- },
- traits::{
- Bump, DidSignatureVerifierContext, DipCallOriginFilter, HistoricalBlockRegistry, ProviderParachainStateInfo,
- RelayChainStorageInfo,
- },
- utils::OutputOf,
-};
-
pub mod did;
pub mod merkle;
pub mod state_proofs;
pub mod traits;
pub mod utils;
-pub use state_proofs::relay_chain::RococoStateRootsViaRelayStorePallet;
-
-#[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)]
-pub struct SiblingParachainDipStateProof<
- RelayBlockHeight,
- DipMerkleProofBlindedValues,
- DipMerkleProofRevealedLeaf,
- LocalBlockNumber,
-> {
- para_state_root: ParachainRootStateProof,
- dip_identity_commitment: Vec>,
- did: DipMerkleProofAndDidSignature,
-}
-
-#[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, Clone)]
-pub struct ParachainRootStateProof {
- relay_block_height: RelayBlockHeight,
- proof: Vec>,
-}
-
-#[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Clone)]
-pub struct DipMerkleProofAndDidSignature {
- leaves: DidMerkleProof,
- signature: TimeBoundDidSignature,
-}
-
-pub enum DipSiblingProviderStateProofVerifierError<
- ParachainHeadMerkleProofVerificationError,
- IdentityCommitmentMerkleProofVerificationError,
- DipProofVerificationError,
- DidSignatureVerificationError,
-> {
- ParachainHeadMerkleProofVerificationError(ParachainHeadMerkleProofVerificationError),
- IdentityCommitmentMerkleProofVerificationError(IdentityCommitmentMerkleProofVerificationError),
- DipProofVerificationError(DipProofVerificationError),
- DidSignatureVerificationError(DidSignatureVerificationError),
-}
-
-impl<
- ParachainHeadMerkleProofVerificationError,
- IdentityCommitmentMerkleProofVerificationError,
- DipProofVerificationError,
- DidSignatureVerificationError,
- >
- From<
- DipSiblingProviderStateProofVerifierError<
- ParachainHeadMerkleProofVerificationError,
- IdentityCommitmentMerkleProofVerificationError,
- DipProofVerificationError,
- DidSignatureVerificationError,
- >,
- > for u16
-where
- ParachainHeadMerkleProofVerificationError: Into,
- IdentityCommitmentMerkleProofVerificationError: Into,
- DipProofVerificationError: Into,
- DidSignatureVerificationError: Into,
-{
- fn from(
- value: DipSiblingProviderStateProofVerifierError<
- ParachainHeadMerkleProofVerificationError,
- IdentityCommitmentMerkleProofVerificationError,
- DipProofVerificationError,
- DidSignatureVerificationError,
- >,
- ) -> Self {
- match value {
- DipSiblingProviderStateProofVerifierError::ParachainHeadMerkleProofVerificationError(error) => {
- error.into() as u16
- }
- DipSiblingProviderStateProofVerifierError::IdentityCommitmentMerkleProofVerificationError(error) => {
- u8::MAX as u16 + error.into() as u16
- }
- DipSiblingProviderStateProofVerifierError::DipProofVerificationError(error) => {
- u8::MAX as u16 * 2 + error.into() as u16
- }
- DipSiblingProviderStateProofVerifierError::DidSignatureVerificationError(error) => {
- u8::MAX as u16 * 3 + error.into() as u16
- }
- }
- }
-}
-
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
-pub struct DipSiblingProviderStateProofVerifier<
- RelayChainStateInfo,
- SiblingProviderParachainId,
- SiblingProviderStateInfo,
- TxSubmitter,
- ProviderDipMerkleHasher,
- ProviderDidKeyId,
- ProviderAccountId,
- ProviderWeb3Name,
- ProviderLinkedAccountId,
- const MAX_REVEALED_KEYS_COUNT: u32,
- const MAX_REVEALED_ACCOUNTS_COUNT: u32,
- LocalDidDetails,
- LocalContextProvider,
- LocalDidCallVerifier,
->(
- #[allow(clippy::type_complexity)]
- PhantomData<(
- RelayChainStateInfo,
- SiblingProviderParachainId,
- SiblingProviderStateInfo,
- TxSubmitter,
- ProviderDipMerkleHasher,
- ProviderDidKeyId,
- ProviderAccountId,
- ProviderWeb3Name,
- ProviderLinkedAccountId,
- LocalDidDetails,
- LocalContextProvider,
- LocalDidCallVerifier,
- )>,
-);
-
-impl<
- Call,
- Subject,
- RelayChainStateInfo,
- SiblingProviderParachainId,
- SiblingProviderStateInfo,
- TxSubmitter,
- ProviderDipMerkleHasher,
- ProviderDidKeyId,
- ProviderAccountId,
- ProviderWeb3Name,
- ProviderLinkedAccountId,
- const MAX_REVEALED_KEYS_COUNT: u32,
- const MAX_REVEALED_ACCOUNTS_COUNT: u32,
- LocalDidDetails,
- LocalContextProvider,
- LocalDidCallVerifier,
- > IdentityProofVerifier
- for DipSiblingProviderStateProofVerifier<
- RelayChainStateInfo,
- SiblingProviderParachainId,
- SiblingProviderStateInfo,
- TxSubmitter,
- ProviderDipMerkleHasher,
- ProviderDidKeyId,
- ProviderAccountId,
- ProviderWeb3Name,
- ProviderLinkedAccountId,
- MAX_REVEALED_KEYS_COUNT,
- MAX_REVEALED_ACCOUNTS_COUNT,
- LocalDidDetails,
- LocalContextProvider,
- LocalDidCallVerifier,
- > where
- Call: Encode,
- TxSubmitter: Encode,
-
- RelayChainStateInfo: traits::RelayChainStorageInfo + traits::RelayChainStateInfo,
- OutputOf: Ord,
- RelayChainStateInfo::BlockNumber: Copy + Into + TryFrom + HasCompact,
- RelayChainStateInfo::Key: AsRef<[u8]>,
-
- SiblingProviderParachainId: Get,
-
- SiblingProviderStateInfo:
- traits::ProviderParachainStateInfo,
- OutputOf: Ord + From>,
- SiblingProviderStateInfo::BlockNumber: Encode + Clone,
- SiblingProviderStateInfo::Commitment: Decode,
- SiblingProviderStateInfo::Key: AsRef<[u8]>,
-
- LocalContextProvider: DidSignatureVerifierContext,
- LocalContextProvider::BlockNumber: Encode + CheckedSub + From + PartialOrd,
- LocalContextProvider::Hash: Encode,
- LocalContextProvider::SignedExtra: Encode,
- LocalDidDetails: Bump + Default + Encode,
- LocalDidCallVerifier:
- DipCallOriginFilter, DidVerificationKeyRelationship)>,
-
- ProviderDipMerkleHasher: sp_core::Hasher,
- ProviderDidKeyId: Encode + Clone + Into,
- ProviderAccountId: Encode + Clone,
- ProviderLinkedAccountId: Encode + Clone,
- ProviderWeb3Name: Encode + Clone,
-{
- type Error = DipSiblingProviderStateProofVerifierError<
- ParachainHeadProofVerifierError,
- DipIdentityCommitmentProofVerifierError,
- DidMerkleProofVerifierError,
- RevealedDidKeysSignatureAndCallVerifierError,
- >;
- type IdentityDetails = LocalDidDetails;
- type Proof = SiblingParachainDipStateProof<
- RelayChainStateInfo::BlockNumber,
- Vec>,
- RevealedDidMerkleProofLeaf<
- ProviderDidKeyId,
- ProviderAccountId,
- SiblingProviderStateInfo::BlockNumber,
- ProviderWeb3Name,
- ProviderLinkedAccountId,
- >,
- LocalContextProvider::BlockNumber,
- >;
- type Submitter = TxSubmitter;
- type VerificationResult = RevealedDidMerkleProofLeaves<
- ProviderDidKeyId,
- ProviderAccountId,
- SiblingProviderStateInfo::BlockNumber,
- ProviderWeb3Name,
- ProviderLinkedAccountId,
- MAX_REVEALED_KEYS_COUNT,
- MAX_REVEALED_ACCOUNTS_COUNT,
- >;
-
- fn verify_proof_for_call_against_details(
- call: &Call,
- subject: &Subject,
- submitter: &Self::Submitter,
- identity_details: &mut Option,
- proof: Self::Proof,
- ) -> Result {
- // 1. Verify relay chain proof.
- let provider_parachain_header = ParachainHeadProofVerifier::::verify_proof_for_parachain(
- &SiblingProviderParachainId::get(),
- &proof.para_state_root.relay_block_height,
- proof.para_state_root.proof,
- )
- .map_err(DipSiblingProviderStateProofVerifierError::ParachainHeadMerkleProofVerificationError)?;
-
- // 2. 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(DipSiblingProviderStateProofVerifierError::IdentityCommitmentMerkleProofVerificationError)?;
-
- // 3. Verify DIP merkle proof.
- let proof_leaves = DidMerkleProofVerifier::<
- ProviderDipMerkleHasher,
- _,
- _,
- _,
- _,
- _,
- MAX_REVEALED_KEYS_COUNT,
- MAX_REVEALED_ACCOUNTS_COUNT,
- >::verify_dip_merkle_proof(&subject_identity_commitment, proof.did.leaves)
- .map_err(DipSiblingProviderStateProofVerifierError::DipProofVerificationError)?;
+mod export;
- // 4. Verify DID signature.
- RevealedDidKeysSignatureAndCallVerifier::<
- _,
- _,
- _,
- _,
- LocalContextProvider,
- _,
- _,
- _,
- LocalDidCallVerifier,
- >::verify_did_signature_for_call(
- call,
- submitter,
- identity_details,
- RevealedDidKeysAndSignature {
- merkle_leaves: proof_leaves.borrow(),
- did_signature: proof.did.signature,
- },
- ).map_err(DipSiblingProviderStateProofVerifierError::DidSignatureVerificationError)?;
-
- Ok(proof_leaves)
- }
-}
-
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
-pub struct ChildParachainDipStateProof<
- ParentBlockHeight: Copy + Into + TryFrom,
- ParentBlockHasher: Hash,
- DipMerkleProofBlindedValues,
- DipMerkleProofRevealedLeaf,
-> {
- para_state_root: ParachainRootStateProof,
- relay_header: Header,
- dip_identity_commitment: Vec>,
- did: DipMerkleProofAndDidSignature,
-}
-
-pub enum DipChildProviderStateProofVerifierError<
- ParachainHeadMerkleProofVerificationError,
- IdentityCommitmentMerkleProofVerificationError,
- DipProofVerificationError,
- DidSignatureVerificationError,
-> {
- InvalidBlockHeight,
- InvalidBlockHash,
- ParachainHeadMerkleProofVerificationError(ParachainHeadMerkleProofVerificationError),
- IdentityCommitmentMerkleProofVerificationError(IdentityCommitmentMerkleProofVerificationError),
- DipProofVerificationError(DipProofVerificationError),
- DidSignatureVerificationError(DidSignatureVerificationError),
-}
-
-impl<
- ParachainHeadMerkleProofVerificationError,
- IdentityCommitmentMerkleProofVerificationError,
- DipProofVerificationError,
- DidSignatureVerificationError,
- >
- From<
- DipChildProviderStateProofVerifierError<
- ParachainHeadMerkleProofVerificationError,
- IdentityCommitmentMerkleProofVerificationError,
- DipProofVerificationError,
- DidSignatureVerificationError,
- >,
- > for u16
-where
- ParachainHeadMerkleProofVerificationError: Into,
- IdentityCommitmentMerkleProofVerificationError: Into,
- DipProofVerificationError: Into,
- DidSignatureVerificationError: Into,
-{
- fn from(
- value: DipChildProviderStateProofVerifierError<
- ParachainHeadMerkleProofVerificationError,
- IdentityCommitmentMerkleProofVerificationError,
- DipProofVerificationError,
- DidSignatureVerificationError,
- >,
- ) -> Self {
- match value {
- DipChildProviderStateProofVerifierError::InvalidBlockHeight => 0,
- DipChildProviderStateProofVerifierError::InvalidBlockHash => 1,
- DipChildProviderStateProofVerifierError::ParachainHeadMerkleProofVerificationError(error) => {
- u8::MAX as u16 + error.into() as u16
- }
- DipChildProviderStateProofVerifierError::IdentityCommitmentMerkleProofVerificationError(error) => {
- u8::MAX as u16 * 2 + error.into() as u16
- }
- DipChildProviderStateProofVerifierError::DipProofVerificationError(error) => {
- u8::MAX as u16 * 3 + error.into() as u16
- }
- DipChildProviderStateProofVerifierError::DidSignatureVerificationError(error) => {
- u8::MAX as u16 * 4 + error.into() as u16
- }
- }
- }
-}
-
-pub struct DipChildProviderStateProofVerifier<
- RelayChainInfo,
- ChildProviderParachainId,
- ChildProviderStateInfo,
- TxSubmitter,
- ProviderDipMerkleHasher,
- ProviderDidKeyId,
- ProviderAccountId,
- ProviderWeb3Name,
- ProviderLinkedAccountId,
- const MAX_REVEALED_KEYS_COUNT: u32,
- const MAX_REVEALED_ACCOUNTS_COUNT: u32,
- LocalDidDetails,
- LocalContextProvider,
- LocalDidCallVerifier,
->(
- #[allow(clippy::type_complexity)]
- PhantomData<(
- RelayChainInfo,
- ChildProviderParachainId,
- ChildProviderStateInfo,
- TxSubmitter,
- ProviderDipMerkleHasher,
- ProviderDidKeyId,
- ProviderAccountId,
- ProviderWeb3Name,
- ProviderLinkedAccountId,
- LocalDidDetails,
- LocalContextProvider,
- LocalDidCallVerifier,
- )>,
-);
-
-impl<
- Call,
- Subject,
- RelayChainInfo,
- ChildProviderParachainId,
- ChildProviderStateInfo,
- TxSubmitter,
- ProviderDipMerkleHasher,
- ProviderDidKeyId,
- ProviderAccountId,
- ProviderWeb3Name,
- ProviderLinkedAccountId,
- const MAX_REVEALED_KEYS_COUNT: u32,
- const MAX_REVEALED_ACCOUNTS_COUNT: u32,
- LocalDidDetails,
- LocalContextProvider,
- LocalDidCallVerifier,
- > IdentityProofVerifier
- for DipChildProviderStateProofVerifier<
- RelayChainInfo,
- ChildProviderParachainId,
- ChildProviderStateInfo,
- TxSubmitter,
- ProviderDipMerkleHasher,
- ProviderDidKeyId,
- ProviderAccountId,
- ProviderWeb3Name,
- ProviderLinkedAccountId,
- MAX_REVEALED_KEYS_COUNT,
- MAX_REVEALED_ACCOUNTS_COUNT,
- LocalDidDetails,
- LocalContextProvider,
- LocalDidCallVerifier,
- > where
- Call: Encode,
- TxSubmitter: Encode,
-
- RelayChainInfo: RelayChainStorageInfo
- + HistoricalBlockRegistry<
- BlockNumber = ::BlockNumber,
- Hasher = ::Hasher,
- >,
- 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,
- RelayChainInfo::Key: AsRef<[u8]>,
-
- ChildProviderParachainId: Get,
-
- ChildProviderStateInfo: ProviderParachainStateInfo,
- OutputOf: Ord + From::Hasher>>,
- ChildProviderStateInfo::BlockNumber: Encode + Clone,
- ChildProviderStateInfo::Commitment: Decode,
- ChildProviderStateInfo::Key: AsRef<[u8]>,
-
- LocalContextProvider:
- DidSignatureVerifierContext::BlockNumber>,
- LocalContextProvider::BlockNumber: CheckedSub + From,
- LocalContextProvider::Hash: Encode,
- LocalContextProvider::SignedExtra: Encode,
- LocalDidDetails: Bump + Default + Encode,
- LocalDidCallVerifier:
- DipCallOriginFilter, DidVerificationKeyRelationship)>,
-
- ProviderDipMerkleHasher: sp_core::Hasher,
- ProviderDidKeyId: Encode + Clone + Into,
- ProviderAccountId: Encode + Clone,
- ProviderLinkedAccountId: Encode + Clone,
- ProviderWeb3Name: Encode + Clone,
-{
- type Error = DipChildProviderStateProofVerifierError<
- ParachainHeadProofVerifierError,
- DipIdentityCommitmentProofVerifierError,
- DidMerkleProofVerifierError,
- RevealedDidKeysSignatureAndCallVerifierError,
- >;
- type IdentityDetails = LocalDidDetails;
- type Proof = ChildParachainDipStateProof<
- ::BlockNumber,
- ::Hasher,
- Vec>,
- RevealedDidMerkleProofLeaf<
- ProviderDidKeyId,
- ProviderAccountId,
- ChildProviderStateInfo::BlockNumber,
- ProviderWeb3Name,
- ProviderLinkedAccountId,
- >,
- >;
- type Submitter = TxSubmitter;
- type VerificationResult = RevealedDidMerkleProofLeaves<
- ProviderDidKeyId,
- ProviderAccountId,
- ChildProviderStateInfo::BlockNumber,
- ProviderWeb3Name,
- ProviderLinkedAccountId,
- MAX_REVEALED_KEYS_COUNT,
- MAX_REVEALED_ACCOUNTS_COUNT,
- >;
-
- fn verify_proof_for_call_against_details(
- call: &Call,
- subject: &Subject,
- submitter: &Self::Submitter,
- identity_details: &mut Option,
- 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(DipChildProviderStateProofVerifierError::InvalidBlockHeight)?;
-
- // 1.1 Verify that the provided header hashes to the same block has retrieved
- if block_hash_at_height != proof.relay_header.hash() {
- return Err(DipChildProviderStateProofVerifierError::InvalidBlockHash);
- }
- // 1.2 If so, extract the state root from the header
- let state_root_at_height = proof.relay_header.state_root;
-
- // FIXME: Compilation error
- // 2. Verify relay chain proof
- let provider_parachain_header =
- ParachainHeadProofVerifier::::verify_proof_for_parachain_with_root(
- &ChildProviderParachainId::get(),
- &state_root_at_height,
- proof.para_state_root.proof,
- )
- .map_err(DipChildProviderStateProofVerifierError::ParachainHeadMerkleProofVerificationError)?;
-
- // 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(DipChildProviderStateProofVerifierError::IdentityCommitmentMerkleProofVerificationError)?;
-
- // 4. Verify DIP merkle proof.
- let proof_leaves = DidMerkleProofVerifier::<
- ProviderDipMerkleHasher,
- _,
- _,
- _,
- _,
- _,
- MAX_REVEALED_KEYS_COUNT,
- MAX_REVEALED_ACCOUNTS_COUNT,
- >::verify_dip_merkle_proof(&subject_identity_commitment, proof.did.leaves)
- .map_err(DipChildProviderStateProofVerifierError::DipProofVerificationError)?;
-
- // 5. Verify DID signature.
- RevealedDidKeysSignatureAndCallVerifier::<
- _,
- _,
- _,
- _,
- LocalContextProvider,
- _,
- _,
- _,
- LocalDidCallVerifier,
- >::verify_did_signature_for_call(
- call,
- submitter,
- identity_details,
- RevealedDidKeysAndSignature {
- merkle_leaves: proof_leaves.borrow(),
- did_signature: proof.did.signature,
- },
- ).map_err(DipChildProviderStateProofVerifierError::DidSignatureVerificationError)?;
- Ok(proof_leaves)
- }
-}
+pub use export::*;
+pub use state_proofs::relay_chain::RococoStateRootsViaRelayStorePallet;
diff --git a/crates/kilt-dip-support/src/state_proofs.rs b/crates/kilt-dip-support/src/state_proofs.rs
index 53099e6adb..1f4866ab85 100644
--- a/crates/kilt-dip-support/src/state_proofs.rs
+++ b/crates/kilt-dip-support/src/state_proofs.rs
@@ -302,7 +302,7 @@ pub(super) mod parachain {
state_root: OutputOf,
proof: impl IntoIterator- >,
) -> Result {
- let dip_commitment_storage_key = ParaInfo::dip_subject_storage_key(identifier);
+ 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,
@@ -328,6 +328,7 @@ pub(super) mod parachain {
use super::*;
use hex_literal::hex;
+ use pallet_dip_provider::IdentityCommitmentVersion;
use sp_core::H256;
use sp_runtime::traits::BlakeTwo256;
@@ -345,7 +346,10 @@ pub(super) mod parachain {
type Identifier = ();
type Key = StorageKey;
- fn dip_subject_storage_key(_identifier: &Self::Identifier) -> Self::Key {
+ 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)
diff --git a/crates/kilt-dip-support/src/traits.rs b/crates/kilt-dip-support/src/traits.rs
index e23174a542..d3c013b1b5 100644
--- a/crates/kilt-dip-support/src/traits.rs
+++ b/crates/kilt-dip-support/src/traits.rs
@@ -17,6 +17,7 @@
// 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::IdentityCommitmentVersion;
use sp_core::storage::StorageKey;
use sp_runtime::traits::{CheckedAdd, One, Zero};
use sp_std::marker::PhantomData;
@@ -76,7 +77,7 @@ pub trait ProviderParachainStateInfo {
type Hasher: sp_runtime::traits::Hash;
type Identifier;
- fn dip_subject_storage_key(identifier: &Self::Identifier) -> Self::Key;
+ fn dip_subject_storage_key(identifier: &Self::Identifier, version: IdentityCommitmentVersion) -> Self::Key;
}
pub struct ProviderParachainStateInfoViaProviderPallet(PhantomData);
@@ -91,9 +92,9 @@ where
type Identifier = T::Identifier;
type Key = StorageKey;
- fn dip_subject_storage_key(identifier: &Self::Identifier) -> Self::Key {
+ fn dip_subject_storage_key(identifier: &Self::Identifier, version: IdentityCommitmentVersion) -> Self::Key {
StorageKey(pallet_dip_provider::IdentityCommitments::::hashed_key_for(
- identifier,
+ identifier, version,
))
}
}
diff --git a/dip-template/runtimes/dip-consumer/src/dip.rs b/dip-template/runtimes/dip-consumer/src/dip.rs
index 40eb0bf100..91ca198c50 100644
--- a/dip-template/runtimes/dip-consumer/src/dip.rs
+++ b/dip-template/runtimes/dip-consumer/src/dip.rs
@@ -21,7 +21,7 @@ use dip_provider_runtime_template::{AccountId as ProviderAccountId, Runtime as P
use frame_support::traits::Contains;
use kilt_dip_support::{
traits::{DipCallOriginFilter, FrameSystemDidSignatureContext, ProviderParachainStateInfoViaProviderPallet},
- DipSiblingProviderStateProofVerifier, RococoStateRootsViaRelayStorePallet,
+ RococoStateRootsViaRelayStorePallet, VersionedDipSiblingProviderStateProofVerifier,
};
use pallet_did_lookup::linkable_account::LinkableAccountId;
use pallet_dip_consumer::traits::IdentityProofVerifier;
@@ -32,7 +32,7 @@ use crate::{AccountId, DidIdentifier, Runtime, RuntimeCall, RuntimeOrigin};
pub type MerkleProofVerifierOutputOf =
>::VerificationResult;
-pub type ProofVerifier = DipSiblingProviderStateProofVerifier<
+pub type ProofVerifier = VersionedDipSiblingProviderStateProofVerifier<
RococoStateRootsViaRelayStorePallet,
ConstU32<2_000>,
ProviderParachainStateInfoViaProviderPallet,
diff --git a/dip-template/runtimes/dip-provider/src/dip.rs b/dip-template/runtimes/dip-provider/src/dip.rs
index bd86831553..720304f30b 100644
--- a/dip-template/runtimes/dip-provider/src/dip.rs
+++ b/dip-template/runtimes/dip-provider/src/dip.rs
@@ -18,7 +18,7 @@
use did::{DidRawOrigin, EnsureDidOrigin, KeyIdOf};
use pallet_did_lookup::linkable_account::LinkableAccountId;
-use pallet_dip_provider::traits::IdentityProvider;
+use pallet_dip_provider::{traits::IdentityProvider, IdentityCommitmentVersion};
use parity_scale_codec::{Decode, Encode};
use runtime_common::dip::{
did::LinkedDidInfoProviderOf,
@@ -32,6 +32,7 @@ use crate::{AccountId, DidIdentifier, Hash, Runtime, RuntimeEvent};
#[derive(Encode, Decode, TypeInfo)]
pub struct RuntimeApiDipProofRequest {
pub(crate) identifier: DidIdentifier,
+ pub(crate) version: IdentityCommitmentVersion,
pub(crate) keys: Vec>,
pub(crate) accounts: Vec,
pub(crate) should_include_web3_name: bool,
diff --git a/dip-template/runtimes/dip-provider/src/lib.rs b/dip-template/runtimes/dip-provider/src/lib.rs
index 578fb1939b..cc8320d55e 100644
--- a/dip-template/runtimes/dip-provider/src/lib.rs
+++ b/dip-template/runtimes/dip-provider/src/lib.rs
@@ -568,7 +568,6 @@ impl_runtime_apis! {
}
}
- // TODO: Support generating different versions of the proof, based on the provided parameter
impl kilt_runtime_api_dip_provider::DipProvider>, RuntimeApiDipProofError> for Runtime {
fn generate_proof(request: RuntimeApiDipProofRequest) -> Result>, RuntimeApiDipProofError> {
let linked_did_info = match ::IdentityProvider::retrieve(&request.identifier) {
@@ -576,7 +575,7 @@ impl_runtime_apis! {
Ok(None) => Err(RuntimeApiDipProofError::IdentityNotFound),
Err(e) => Err(RuntimeApiDipProofError::IdentityProviderError(e))
}?;
- DidMerkleRootGenerator::::generate_proof(&linked_did_info, request.keys.iter(), request.should_include_web3_name, request.accounts.iter()).map_err(RuntimeApiDipProofError::MerkleProofError)
+ DidMerkleRootGenerator::::generate_proof(&linked_did_info, request.version, request.keys.iter(), request.should_include_web3_name, request.accounts.iter()).map_err(RuntimeApiDipProofError::MerkleProofError)
}
}
}
diff --git a/pallets/pallet-dip-provider/Cargo.toml b/pallets/pallet-dip-provider/Cargo.toml
index 5e22e357a1..8c078fbc52 100644
--- a/pallets/pallet-dip-provider/Cargo.toml
+++ b/pallets/pallet-dip-provider/Cargo.toml
@@ -19,6 +19,7 @@ frame-support.workspace = true
frame-system.workspace = true
parity-scale-codec = {workspace = true, features = ["derive"]}
scale-info = {workspace = true, features = ["derive"]}
+sp-io.workspace = true
sp-std.workspace = true
[features]
diff --git a/pallets/pallet-dip-provider/src/lib.rs b/pallets/pallet-dip-provider/src/lib.rs
index ad17b78e4e..826fd170ac 100644
--- a/pallets/pallet-dip-provider/src/lib.rs
+++ b/pallets/pallet-dip-provider/src/lib.rs
@@ -31,14 +31,23 @@ pub mod pallet {
use frame_support::{pallet_prelude::*, traits::EnsureOrigin};
use frame_system::pallet_prelude::*;
use parity_scale_codec::FullCodec;
+ use sp_io::MultiRemovalResults;
use sp_std::fmt::Debug;
use crate::traits::{IdentityCommitmentGenerator, IdentityProvider, SubmitterInfo};
pub type IdentityOf = <::IdentityProvider as IdentityProvider<::Identifier>>::Success;
+ pub type IdentityCommitmentVersion = u16;
+ pub const LATEST_COMMITMENT_VERSION: IdentityCommitmentVersion = 0;
const STORAGE_VERSION: StorageVersion = StorageVersion::new(0);
+ #[derive(Encode, Decode, RuntimeDebug, TypeInfo, Clone, PartialEq)]
+ pub enum VersionOrLimit {
+ Version(IdentityCommitmentVersion),
+ Limit(u32),
+ }
+
#[pallet::config]
pub trait Config: frame_system::Config {
type CommitOriginCheck: EnsureOrigin;
@@ -59,8 +68,14 @@ pub mod pallet {
#[pallet::storage]
#[pallet::getter(fn identity_commitments)]
- pub type IdentityCommitments =
- StorageMap<_, Twox64Concat, ::Identifier, ::IdentityCommitment>;
+ pub type IdentityCommitments = StorageDoubleMap<
+ _,
+ Twox64Concat,
+ ::Identifier,
+ Twox64Concat,
+ IdentityCommitmentVersion,
+ ::IdentityCommitment,
+ >;
#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
@@ -72,6 +87,11 @@ pub mod pallet {
IdentityCommitted {
identifier: T::Identifier,
commitment: T::IdentityCommitment,
+ version: IdentityCommitmentVersion,
+ },
+ VersionedIdentityDeleted {
+ identifier: T::Identifier,
+ version: IdentityCommitmentVersion,
},
IdentityDeleted {
identifier: T::Identifier,
@@ -80,6 +100,8 @@ pub mod pallet {
#[pallet::error]
pub enum Error {
+ IdentityNotFound,
+ LimitTooLow,
IdentityProvider(u16),
IdentityCommitmentGenerator(u16),
}
@@ -89,32 +111,70 @@ pub mod pallet {
#[pallet::call_index(0)]
// TODO: Update weight
#[pallet::weight(0)]
- pub fn commit_identity(origin: OriginFor, identifier: T::Identifier) -> DispatchResult {
+ pub fn commit_identity(
+ origin: OriginFor,
+ identifier: T::Identifier,
+ version: Option,
+ ) -> DispatchResult {
// TODO: use dispatcher to get deposit
let _dispatcher =
T::CommitOriginCheck::ensure_origin(origin).map(|e: ::CommitOrigin| e.submitter())?;
- let identity_commitment: Option = match T::IdentityProvider::retrieve(&identifier) {
- Ok(Some(identity)) => T::IdentityCommitmentGenerator::generate_commitment(&identifier, &identity)
- .map(Some)
- .map_err(|error| Error::::IdentityCommitmentGenerator(error.into())),
- Ok(None) => Ok(None),
+ let commitment_version = version.unwrap_or(LATEST_COMMITMENT_VERSION);
+ let commitment = match T::IdentityProvider::retrieve(&identifier) {
+ Ok(Some(identity)) => {
+ T::IdentityCommitmentGenerator::generate_commitment(&identifier, &identity, commitment_version)
+ .map_err(|error| Error::::IdentityCommitmentGenerator(error.into()))
+ }
+ Ok(None) => Err(Error::::IdentityNotFound),
Err(error) => Err(Error::::IdentityProvider(error.into())),
}?;
- if let Some(commitment) = identity_commitment {
- // TODO: Take deposit (once 0.9.42 PR is merged into develop)
- IdentityCommitments::::insert(&identifier, commitment.clone());
- Self::deposit_event(Event::::IdentityCommitted { identifier, commitment });
- } else {
- // TODO: Release deposit (once 0.9.42 PR is merged into develop)
- IdentityCommitments::::remove(&identifier);
- Self::deposit_event(Event::::IdentityDeleted { identifier });
- }
+ // TODO: Take deposit (once 0.9.42 PR is merged into develop)
+ IdentityCommitments::::insert(&identifier, commitment_version, commitment.clone());
+ Self::deposit_event(Event::::IdentityCommitted {
+ identifier,
+ commitment,
+ version: commitment_version,
+ });
+ Ok(())
+ }
+
+ #[pallet::call_index(1)]
+ // TODO: Update weight
+ #[pallet::weight(0)]
+ pub fn delete_identity_commitment(
+ origin: OriginFor,
+ identifier: T::Identifier,
+ version_or_limit: VersionOrLimit,
+ ) -> DispatchResult {
+ let _dispatcher =
+ T::CommitOriginCheck::ensure_origin(origin).map(|e: ::CommitOrigin| e.submitter())?;
+ match version_or_limit {
+ VersionOrLimit::Version(version) => {
+ let commitment = IdentityCommitments::::take(&identifier, version);
+ match commitment {
+ Some(_) => Err(Error::::IdentityNotFound),
+ None => {
+ Self::deposit_event(Event::::VersionedIdentityDeleted { identifier, version });
+ Ok(())
+ }
+ }
+ }
+ VersionOrLimit::Limit(limit) => {
+ let MultiRemovalResults { maybe_cursor, .. } =
+ IdentityCommitments::::clear_prefix(&identifier, limit, None);
+ match maybe_cursor {
+ Some(_) => Err(Error::::LimitTooLow),
+ None => {
+ Self::deposit_event(Event::::IdentityDeleted { identifier });
+ Ok(())
+ }
+ }
+ }
+ }?;
Ok(())
}
- // TODO: Add extrinsic to remove commitment without requiring the identity to be
- // deleted.
}
}
diff --git a/pallets/pallet-dip-provider/src/traits.rs b/pallets/pallet-dip-provider/src/traits.rs
index 5f0d137963..76b742e129 100644
--- a/pallets/pallet-dip-provider/src/traits.rs
+++ b/pallets/pallet-dip-provider/src/traits.rs
@@ -22,11 +22,17 @@ pub use identity_generation::*;
pub mod identity_generation {
use sp_std::marker::PhantomData;
+ use crate::IdentityCommitmentVersion;
+
pub trait IdentityCommitmentGenerator {
type Error;
type Output;
- fn generate_commitment(identifier: &Identifier, identity: &Identity) -> Result;
+ fn generate_commitment(
+ identifier: &Identifier,
+ identity: &Identity,
+ version: IdentityCommitmentVersion,
+ ) -> Result;
}
// Implement the `IdentityCommitmentGenerator` by returning the `Default` value
@@ -41,7 +47,11 @@ pub mod identity_generation {
type Error = ();
type Output = Output;
- fn generate_commitment(_identifier: &Identifier, _identity: &Identity) -> Result {
+ fn generate_commitment(
+ _identifier: &Identifier,
+ _identity: &Identity,
+ _version: IdentityCommitmentVersion,
+ ) -> Result {
Ok(Output::default())
}
}
diff --git a/runtimes/common/src/dip/merkle.rs b/runtimes/common/src/dip/merkle.rs
index 0059d267ae..d7af9c87b5 100644
--- a/runtimes/common/src/dip/merkle.rs
+++ b/runtimes/common/src/dip/merkle.rs
@@ -20,7 +20,7 @@ use frame_support::RuntimeDebug;
use frame_system::pallet_prelude::BlockNumberFor;
use kilt_dip_support::merkle::{DidKeyMerkleKey, DidKeyMerkleValue, DidMerkleProof};
use pallet_did_lookup::linkable_account::LinkableAccountId;
-use pallet_dip_provider::traits::IdentityCommitmentGenerator;
+use pallet_dip_provider::{traits::IdentityCommitmentGenerator, IdentityCommitmentVersion};
use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
use sp_std::{borrow::ToOwned, marker::PhantomData, vec::Vec};
@@ -50,6 +50,7 @@ pub struct CompleteMerkleProof {
#[derive(Clone, RuntimeDebug, Encode, Decode, TypeInfo, PartialEq)]
pub enum DidMerkleProofError {
+ UnsupportedVersion,
DidNotFound,
KeyNotFound,
LinkedAccountNotFound,
@@ -60,50 +61,40 @@ pub enum DidMerkleProofError {
impl From for u16 {
fn from(value: DidMerkleProofError) -> Self {
match value {
- DidMerkleProofError::DidNotFound => 0,
- DidMerkleProofError::KeyNotFound => 1,
- DidMerkleProofError::LinkedAccountNotFound => 2,
- DidMerkleProofError::Web3NameNotFound => 3,
+ DidMerkleProofError::UnsupportedVersion => 0,
+ DidMerkleProofError::DidNotFound => 1,
+ DidMerkleProofError::KeyNotFound => 2,
+ DidMerkleProofError::LinkedAccountNotFound => 3,
+ DidMerkleProofError::Web3NameNotFound => 4,
DidMerkleProofError::Internal => u16::MAX,
}
}
}
-pub struct DidMerkleRootGenerator(PhantomData);
+pub mod v0 {
+ use super::*;
-type ProofLeafOf = RevealedDidMerkleProofLeaf<
- KeyIdOf,
- ::AccountId,
- BlockNumberFor,
- ::Web3Name,
- LinkableAccountId,
->;
+ type ProofLeafOf = RevealedDidMerkleProofLeaf<
+ KeyIdOf,
+ ::AccountId,
+ BlockNumberFor,
+ ::Web3Name,
+ LinkableAccountId,
+ >;
-impl DidMerkleRootGenerator
-where
- T: did::Config + pallet_did_lookup::Config + pallet_web3_names::Config,
-{
- // Calls the function in the `sp_trie` crate to generate the merkle root given
- // the provided `DidDetails`.
- // Each key in the merkle tree is added in the following way:
- // - keys in the `public_keys` map are added by value in the merkle tree, with
- // the leaf key being the key ID and the value being the key details
- // - keys everywhere else in the DidDetails are added by reference, with the
- // leaf key being the encoding of the tuple (keyID, key relationship) and the
- // value being hte empty tuple
- // A valid proof will contain a leaf with the key details for each reference
- // leaf, with multiple reference leaves potentially referring to the same
- // details leaf, as we already do with out `DidDetails` type.
- fn calculate_root_with_db(
- identity: &LinkedDidInfoOf,
- db: &mut MemoryDB,
- ) -> Result {
+ 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,
+ {
// Fails if the DID details do not exist.
let (Some(did_details), web3_name, linked_accounts) = (&identity.a, &identity.b, &identity.c) else {
return Err(DidMerkleProofError::DidNotFound);
};
- let mut trie = TrieHash::>::default();
- let mut trie_builder = TrieDBMutBuilder::>::new(db, &mut trie).build();
+ let mut trie = TrieHash::>::default();
+ let mut trie_builder = TrieDBMutBuilder::>::new(db, &mut trie).build();
// Authentication key
let auth_key_details = did_details
@@ -113,7 +104,7 @@ where
log::error!("Authentication key should be part of the public keys.");
DidMerkleProofError::Internal
})?;
- let auth_leaf = ProofLeafOf::::DidKey(
+ let auth_leaf = ProofLeafOf::::DidKey(
DidKeyMerkleKey(
did_details.authentication_key,
DidVerificationKeyRelationship::Authentication.into(),
@@ -135,7 +126,7 @@ where
log::error!("Attestation key should be part of the public keys.");
DidMerkleProofError::Internal
})?;
- let att_leaf = ProofLeafOf::::DidKey(
+ let att_leaf = ProofLeafOf::::DidKey(
(att_key_id, DidVerificationKeyRelationship::AssertionMethod.into()).into(),
att_key_details.clone().into(),
);
@@ -155,7 +146,7 @@ where
log::error!("Delegation key should be part of the public keys.");
DidMerkleProofError::Internal
})?;
- let del_leaf = ProofLeafOf::::DidKey(
+ let del_leaf = ProofLeafOf::::DidKey(
(del_key_id, DidVerificationKeyRelationship::CapabilityDelegation.into()).into(),
del_key_details.clone().into(),
);
@@ -178,7 +169,7 @@ where
log::error!("Key agreement key should be part of the public keys.");
DidMerkleProofError::Internal
})?;
- let enc_leaf = ProofLeafOf::::DidKey(
+ let enc_leaf = ProofLeafOf::::DidKey(
(*id, DidKeyRelationship::Encryption).into(),
key_agreement_details.clone().into(),
);
@@ -199,7 +190,8 @@ where
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::::LinkedAccount(linked_account.clone().into(), ().into());
trie_builder
.insert(
linked_account_leaf.encoded_key().as_slice(),
@@ -218,7 +210,7 @@ where
// Web3name, if present
if let Some(web3name_details) = web3_name {
- let web3_name_leaf = ProofLeafOf::::Web3Name(
+ let web3_name_leaf = ProofLeafOf::::Web3Name(
web3name_details.web3_name.clone().into(),
web3name_details.claimed_at.into(),
);
@@ -240,19 +232,15 @@ where
Ok(trie_builder.root().to_owned())
}
- // Only used for testing and as part of the features exposed by the runtime API
- // of the provider. Given the provided `DidDetails` and a list of key IDs, it
- // generates a merkle proof which only reveals the details of the provided key
- // IDs.
- #[allow(clippy::result_unit_err)]
- pub fn generate_proof<'a, K, A>(
- identity: &LinkedDidInfoOf,
+ pub(super) fn generate_proof<'a, Runtime, K, A>(
+ identity: &LinkedDidInfoOf