Skip to content
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ version = "1.12.0-dev"
members = [
"crates/*",
"dip-template/nodes/*",
"dip-template/pallets/*",
"dip-template/runtimes/*",
"nodes/*",
"pallets/*",
Expand Down Expand Up @@ -42,7 +43,7 @@ jsonrpsee = "0.16.2"
libsecp256k1 = {version = "0.7", default-features = false}
log = "0.4.17"
parity-scale-codec = {version = "3.1.5", default-features = false}
scale-info = {version = "2.1.1", default-features = false}
scale-info = {version = "2.7.0", default-features = false}
serde = "1.0.144"
serde_json = "1.0.85"
sha3 = {version = "0.10.0", default-features = false}
Expand Down Expand Up @@ -72,6 +73,7 @@ runtime-common = {path = "runtimes/common", default-features = false}
# Templates
dip-consumer-runtime-template = {path = "dip-template/runtimes/dip-consumer", default-features = false}
dip-provider-runtime-template = {path = "dip-template/runtimes/dip-provider", default-features = false}
pallet-postit = {path = "dip-template/pallets/pallet-postit", default-features = false}

# Internal runtime API (with default disabled)
kilt-runtime-api-did = {path = "runtime-api/did", default-features = false}
Expand Down
250 changes: 232 additions & 18 deletions crates/kilt-dip-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@

#![cfg_attr(not(feature = "std"), no_std)]

use parity_scale_codec::{Decode, Encode, HasCompact};
use parity_scale_codec::{Codec, Decode, Encode, HasCompact};
use scale_info::TypeInfo;
use sp_core::{Get, RuntimeDebug, U256};
use sp_runtime::traits::CheckedSub;
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};
Expand All @@ -32,8 +35,11 @@ use pallet_dip_consumer::traits::IdentityProofVerifier;
use crate::{
did::{RevealedDidKeysAndSignature, RevealedDidKeysSignatureAndCallVerifier, TimeBoundDidSignature},
merkle::{DidMerkleProof, DidMerkleProofVerifier, RevealedDidMerkleProofLeaf, RevealedDidMerkleProofLeaves},
state_proofs::{parachain::DipIdentityCommitmentProofVerifier, relay_chain::SiblingParachainHeadProofVerifier},
traits::{Bump, DidSignatureVerifierContext, DipCallOriginFilter},
state_proofs::{parachain::DipIdentityCommitmentProofVerifier, relay_chain::ParachainHeadProofVerifier},
traits::{
Bump, DidSignatureVerifierContext, DipCallOriginFilter, HistoricalBlockRegistry, ProviderParachainStateInfo,
RelayChainStorageInfo,
},
utils::OutputOf,
};

Expand All @@ -43,20 +49,22 @@ 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,
DipProviderBlockNumber,
> {
para_state_root: SiblingParachainRootStateProof<RelayBlockHeight>,
para_state_root: ParachainRootStateProof<RelayBlockHeight>,
dip_identity_commitment: Vec<Vec<u8>>,
did: DipMerkleProofAndDidSignature<DipMerkleProofBlindedValues, DipMerkleProofRevealedLeaf, DipProviderBlockNumber>,
}

#[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, Clone)]
pub struct SiblingParachainRootStateProof<RelayBlockHeight> {
pub struct ParachainRootStateProof<RelayBlockHeight> {
relay_block_height: RelayBlockHeight,
proof: Vec<Vec<u8>>,
}
Expand All @@ -67,6 +75,7 @@ pub struct DipMerkleProofAndDidSignature<BlindedValues, Leaf, BlockNumber> {
signature: TimeBoundDidSignature<BlockNumber>,
}

#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub struct DipSiblingProviderStateProofVerifier<
RelayChainStateInfo,
SiblingProviderParachainId,
Expand Down Expand Up @@ -133,8 +142,7 @@ impl<
Call: Encode,
TxSubmitter: Encode,

RelayChainStateInfo: traits::RelayChainStateInfo,
RelayChainStateInfo::Hasher: 'static,
RelayChainStateInfo: traits::RelayChainStorageInfo + traits::RelayChainStateInfo,
OutputOf<RelayChainStateInfo::Hasher>: Ord,
RelayChainStateInfo::BlockNumber: Copy + Into<U256> + TryFrom<U256> + HasCompact,
RelayChainStateInfo::Key: AsRef<[u8]>,
Expand All @@ -143,7 +151,6 @@ impl<

SiblingProviderStateInfo:
traits::ProviderParachainStateInfo<Identifier = Subject, Commitment = ProviderDipMerkleHasher::Out>,
SiblingProviderStateInfo::Hasher: 'static,
OutputOf<SiblingProviderStateInfo::Hasher>: Ord + From<OutputOf<RelayChainStateInfo::Hasher>>,
SiblingProviderStateInfo::BlockNumber: Encode + Clone,
SiblingProviderStateInfo::Commitment: Decode,
Expand Down Expand Up @@ -192,12 +199,11 @@ impl<
proof: Self::Proof,
) -> Result<Self::VerificationResult, Self::Error> {
// 1. Verify relay chain proof.
let provider_parachain_header =
SiblingParachainHeadProofVerifier::<RelayChainStateInfo>::verify_proof_for_parachain(
&SiblingProviderParachainId::get(),
&proof.para_state_root.relay_block_height,
proof.para_state_root.proof,
)?;
let provider_parachain_header = ParachainHeadProofVerifier::<RelayChainStateInfo>::verify_proof_for_parachain(
&SiblingProviderParachainId::get(),
&proof.para_state_root.relay_block_height,
proof.para_state_root.proof,
)?;

// 2. Verify parachain state proof.
let subject_identity_commitment =
Expand Down Expand Up @@ -242,6 +248,214 @@ impl<
}
}

pub use state_proofs::{
parachain::KiltDipCommitmentsForDipProviderPallet, relay_chain::RococoStateRootsViaRelayStorePallet,
};
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub struct ChildParachainDipStateProof<
RelayBlockHeight: Copy + Into<U256> + TryFrom<U256>,
RelayBlockHasher: Hash,
DipMerkleProofBlindedValues,
DipMerkleProofRevealedLeaf,
DipProviderBlockNumber,
> {
para_state_root: ParachainRootStateProof<RelayBlockHeight>,
relay_header: Header<RelayBlockHeight, RelayBlockHasher>,
dip_identity_commitment: Vec<Vec<u8>>,
did: DipMerkleProofAndDidSignature<DipMerkleProofBlindedValues, DipMerkleProofRevealedLeaf, DipProviderBlockNumber>,
}

pub struct DipChildProviderStateProofVerifier<
RelayChainInfo,
SiblingProviderParachainId,
SiblingProviderStateInfo,
TxSubmitter,
ProviderDipMerkleHasher,
ProviderDidKeyId,
ProviderWeb3Name,
ProviderLinkedAccountId,
const MAX_REVEALED_KEYS_COUNT: u32,
const MAX_REVEALED_ACCOUNTS_COUNT: u32,
LocalDidDetails,
LocalContextProvider,
LocalDidCallVerifier,
>(
#[allow(clippy::type_complexity)]
PhantomData<(
RelayChainInfo,
SiblingProviderParachainId,
SiblingProviderStateInfo,
TxSubmitter,
ProviderDipMerkleHasher,
ProviderDidKeyId,
ProviderWeb3Name,
ProviderLinkedAccountId,
LocalDidDetails,
LocalContextProvider,
LocalDidCallVerifier,
)>,
);

impl<
Call,
Subject,
RelayChainInfo,
SiblingProviderParachainId,
SiblingProviderStateInfo,
TxSubmitter,
ProviderDipMerkleHasher,
ProviderDidKeyId,
ProviderWeb3Name,
ProviderLinkedAccountId,
const MAX_REVEALED_KEYS_COUNT: u32,
const MAX_REVEALED_ACCOUNTS_COUNT: u32,
LocalDidDetails,
LocalContextProvider,
LocalDidCallVerifier,
> IdentityProofVerifier<Call, Subject>
for DipChildProviderStateProofVerifier<
RelayChainInfo,
SiblingProviderParachainId,
SiblingProviderStateInfo,
TxSubmitter,
ProviderDipMerkleHasher,
ProviderDidKeyId,
ProviderWeb3Name,
ProviderLinkedAccountId,
MAX_REVEALED_KEYS_COUNT,
MAX_REVEALED_ACCOUNTS_COUNT,
LocalDidDetails,
LocalContextProvider,
LocalDidCallVerifier,
> where
Call: Encode,
TxSubmitter: Encode,

RelayChainInfo: RelayChainStorageInfo
+ HistoricalBlockRegistry<
BlockNumber = <RelayChainInfo as RelayChainStorageInfo>::BlockNumber,
Hasher = <RelayChainInfo as RelayChainStorageInfo>::Hasher,
>,
OutputOf<<RelayChainInfo as RelayChainStorageInfo>::Hasher>:
Ord + Default + sp_std::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec,
<RelayChainInfo as RelayChainStorageInfo>::BlockNumber: Copy
+ Into<U256>
+ TryFrom<U256>
+ HasCompact
+ Member
+ sp_std::hash::Hash
+ MaybeDisplay
+ AtLeast32BitUnsigned
+ Codec,
RelayChainInfo::Key: AsRef<[u8]>,

SiblingProviderParachainId: Get<RelayChainInfo::ParaId>,

SiblingProviderStateInfo:
ProviderParachainStateInfo<Identifier = Subject, Commitment = ProviderDipMerkleHasher::Out>,
OutputOf<SiblingProviderStateInfo::Hasher>: Ord + From<OutputOf<<RelayChainInfo as RelayChainStorageInfo>::Hasher>>,
SiblingProviderStateInfo::BlockNumber: Encode + Clone,
SiblingProviderStateInfo::Commitment: Decode,
SiblingProviderStateInfo::Key: AsRef<[u8]>,

LocalContextProvider: DidSignatureVerifierContext,
LocalContextProvider::BlockNumber: Encode + CheckedSub + From<u16> + 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<ProviderDipMerkleHasher::Out>,
ProviderLinkedAccountId: Encode + Clone,
ProviderWeb3Name: Encode + Clone,
{
type Error = ();
type IdentityDetails = LocalDidDetails;
type Proof = ChildParachainDipStateProof<
<RelayChainInfo as RelayChainStorageInfo>::BlockNumber,
<RelayChainInfo as RelayChainStorageInfo>::Hasher,
Vec<Vec<u8>>,
RevealedDidMerkleProofLeaf<
ProviderDidKeyId,
SiblingProviderStateInfo::BlockNumber,
ProviderWeb3Name,
ProviderLinkedAccountId,
>,
LocalContextProvider::BlockNumber,
>;
type Submitter = TxSubmitter;
type VerificationResult = RevealedDidMerkleProofLeaves<
ProviderDidKeyId,
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<Self::IdentityDetails>,
proof: Self::Proof,
) -> Result<Self::VerificationResult, Self::Error> {
// 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(())?;

// 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(());
}
// 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::<RelayChainInfo>::verify_proof_for_parachain_with_root(
&SiblingProviderParachainId::get(),
&state_root_at_height,
proof.para_state_root.proof,
)?;

// 3. Verify parachain state proof.
let subject_identity_commitment =
DipIdentityCommitmentProofVerifier::<SiblingProviderStateInfo>::verify_proof_for_identifier(
subject,
provider_parachain_header.state_root.into(),
proof.dip_identity_commitment,
)?;

// 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)?;

// 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,
},
)?;
Ok(proof_leaves)
}
}
Loading