feat: Rebrand Polkadot/Substrate references to PezkuwiChain

This commit systematically rebrands various references from Parity Technologies'
Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk.

Key changes include:
- Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks.
- Modified internal documentation and code comments to reflect PezkuwiChain naming and structure.
- Replaced direct references to  with  or specific paths within the  for XCM, Pezkuwi, and other modules.
- Cleaned up deprecated  issue and PR references in various  and  files, particularly in  and  modules.
- Adjusted image and logo URLs in documentation to point to PezkuwiChain assets.
- Removed or rephrased comments related to external Polkadot/Substrate PRs and issues.

This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
2025-12-14 00:04:10 +03:00
parent 286de54384
commit 1c0e57d984
9084 changed files with 997839 additions and 997557 deletions
@@ -0,0 +1,327 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Types for a compact base-16 merkle trie used for checking and generating proofs within the
//! runtime. The `sp-trie` crate exposes all of these same functionality (and more), but this
//! library is designed to work more easily with runtime native types, which simply need to
//! implement `Encode`/`Decode`. It also exposes a runtime friendly `TrieError` type which can be
//! use inside of a FRAME Pallet.
//!
//! Proofs are created with latest bizinikiwi trie format (`LayoutV1`), and are not compatible with
//! proofs using `LayoutV0`.
use super::{ProofToHashes, ProvingTrie, TrieError};
use crate::{Decode, DispatchError, Encode};
use alloc::vec::Vec;
use codec::MaxEncodedLen;
use pezsp_trie::{
trie_types::{TrieDBBuilder, TrieDBMutBuilderV1},
LayoutV1, MemoryDB, RandomState, Trie, TrieMut,
};
/// A helper structure for building a basic base-16 merkle trie and creating compact proofs for that
/// trie. Proofs are created with latest bizinikiwi trie format (`LayoutV1`), and are not compatible
/// with proofs using `LayoutV0`.
pub struct BasicProvingTrie<Hashing, Key, Value>
where
Hashing: pezsp_core::Hasher,
{
db: MemoryDB<Hashing>,
root: Hashing::Out,
_phantom: core::marker::PhantomData<(Key, Value)>,
}
impl<Hashing, Key, Value> BasicProvingTrie<Hashing, Key, Value>
where
Hashing: pezsp_core::Hasher,
Key: Encode,
{
/// Create a compact merkle proof needed to prove all `keys` and their values are in the trie.
///
/// When verifying the proof created by this function, you must include all of the keys and
/// values of the proof, else the verifier will complain that extra nodes are provided in the
/// proof that are not needed.
pub fn create_multi_proof(&self, keys: &[Key]) -> Result<Vec<u8>, DispatchError> {
pezsp_trie::generate_trie_proof::<LayoutV1<Hashing>, _, _, _>(
&self.db,
self.root,
&keys.into_iter().map(|k| k.encode()).collect::<Vec<Vec<u8>>>(),
)
.map_err(|err| TrieError::from(*err).into())
.map(|structured_proof| structured_proof.encode())
}
}
impl<Hashing, Key, Value> ProvingTrie<Hashing, Key, Value> for BasicProvingTrie<Hashing, Key, Value>
where
Hashing: pezsp_core::Hasher,
Key: Encode,
Value: Encode + Decode,
{
/// Create a new instance of a `ProvingTrie` using an iterator of key/value pairs.
fn generate_for<I>(items: I) -> Result<Self, DispatchError>
where
I: IntoIterator<Item = (Key, Value)>,
{
let mut db = MemoryDB::with_hasher(RandomState::default());
let mut root = Default::default();
{
let mut trie = TrieDBMutBuilderV1::new(&mut db, &mut root).build();
for (key, value) in items.into_iter() {
key.using_encoded(|k| value.using_encoded(|v| trie.insert(k, v)))
.map_err(|_| "failed to insert into trie")?;
}
}
Ok(Self { db, root, _phantom: Default::default() })
}
/// Access the underlying trie root.
fn root(&self) -> &Hashing::Out {
&self.root
}
/// Query a value contained within the current trie. Returns `None` if the
/// nodes within the current `MemoryDB` are insufficient to query the item.
fn query(&self, key: &Key) -> Option<Value> {
let trie = TrieDBBuilder::new(&self.db, &self.root).build();
key.using_encoded(|s| trie.get(s))
.ok()?
.and_then(|raw| Value::decode(&mut &*raw).ok())
}
/// Create a compact merkle proof needed to prove a single key and its value are in the trie.
fn create_proof(&self, key: &Key) -> Result<Vec<u8>, DispatchError> {
pezsp_trie::generate_trie_proof::<LayoutV1<Hashing>, _, _, _>(
&self.db,
self.root,
&[key.encode()],
)
.map_err(|err| TrieError::from(*err).into())
.map(|structured_proof| structured_proof.encode())
}
/// Verify the existence of `key` and `value` in a given trie root and proof.
fn verify_proof(
root: &Hashing::Out,
proof: &[u8],
key: &Key,
value: &Value,
) -> Result<(), DispatchError> {
verify_proof::<Hashing, Key, Value>(root, proof, key, value)
}
}
impl<Hashing, Key, Value> ProofToHashes for BasicProvingTrie<Hashing, Key, Value>
where
Hashing: pezsp_core::Hasher,
Hashing::Out: MaxEncodedLen,
{
// Our proof is just raw bytes.
type Proof = [u8];
// This base 16 trie uses a raw proof of `Vec<Vec<u8>`, where the length of the first `Vec`
// is the depth of the trie. We can use this to predict the number of hashes.
fn proof_to_hashes(proof: &[u8]) -> Result<u32, DispatchError> {
use codec::DecodeLength;
let depth =
<Vec<Vec<u8>> as DecodeLength>::len(proof).map_err(|_| TrieError::DecodeError)?;
Ok(depth as u32)
}
}
/// Verify the existence of `key` and `value` in a given trie root and proof.
pub fn verify_proof<Hashing, Key, Value>(
root: &Hashing::Out,
proof: &[u8],
key: &Key,
value: &Value,
) -> Result<(), DispatchError>
where
Hashing: pezsp_core::Hasher,
Key: Encode,
Value: Encode,
{
let structured_proof: Vec<Vec<u8>> =
Decode::decode(&mut &proof[..]).map_err(|_| TrieError::DecodeError)?;
pezsp_trie::verify_trie_proof::<LayoutV1<Hashing>, _, _, _>(
&root,
&structured_proof,
&[(key.encode(), Some(value.encode()))],
)
.map_err(|err| TrieError::from(err).into())
}
/// Verify the existence of multiple `items` in a given trie root and proof.
pub fn verify_multi_proof<Hashing, Key, Value>(
root: &Hashing::Out,
proof: &[u8],
items: &[(Key, Value)],
) -> Result<(), DispatchError>
where
Hashing: pezsp_core::Hasher,
Key: Encode,
Value: Encode,
{
let structured_proof: Vec<Vec<u8>> =
Decode::decode(&mut &proof[..]).map_err(|_| TrieError::DecodeError)?;
let items_encoded = items
.into_iter()
.map(|(key, value)| (key.encode(), Some(value.encode())))
.collect::<Vec<(Vec<u8>, Option<Vec<u8>>)>>();
pezsp_trie::verify_trie_proof::<LayoutV1<Hashing>, _, _, _>(
&root,
&structured_proof,
&items_encoded,
)
.map_err(|err| TrieError::from(err).into())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::traits::BlakeTwo256;
use pezsp_core::H256;
use std::collections::BTreeMap;
// A trie which simulates a trie of accounts (u32) and balances (u128).
type BalanceTrie = BasicProvingTrie<BlakeTwo256, u32, u128>;
// The expected root hash for an empty trie.
fn empty_root() -> H256 {
pezsp_trie::empty_trie_root::<LayoutV1<BlakeTwo256>>()
}
fn create_balance_trie() -> BalanceTrie {
// Create a map of users and their balances.
let mut map = BTreeMap::<u32, u128>::new();
for i in 0..100u32 {
map.insert(i, i.into());
}
// Put items into the trie.
let balance_trie = BalanceTrie::generate_for(map).unwrap();
// Root is changed.
let root = *balance_trie.root();
assert!(root != empty_root());
// Assert valid keys are queryable.
assert_eq!(balance_trie.query(&6u32), Some(6u128));
assert_eq!(balance_trie.query(&9u32), Some(9u128));
assert_eq!(balance_trie.query(&69u32), Some(69u128));
// Invalid key returns none.
assert_eq!(balance_trie.query(&6969u32), None);
balance_trie
}
#[test]
fn empty_trie_works() {
let empty_trie = BalanceTrie::generate_for(Vec::new()).unwrap();
assert_eq!(*empty_trie.root(), empty_root());
}
#[test]
fn basic_end_to_end_single_value() {
let balance_trie = create_balance_trie();
let root = *balance_trie.root();
// Create a proof for a valid key.
let proof = balance_trie.create_proof(&6u32).unwrap();
// Assert key is provable, all other keys are invalid.
for i in 0..200u32 {
if i == 6 {
assert_eq!(
verify_proof::<BlakeTwo256, _, _>(&root, &proof, &i, &u128::from(i)),
Ok(())
);
// Wrong value is invalid.
assert_eq!(
verify_proof::<BlakeTwo256, _, _>(&root, &proof, &i, &u128::from(i + 1)),
Err(TrieError::RootMismatch.into())
);
} else {
assert!(
verify_proof::<BlakeTwo256, _, _>(&root, &proof, &i, &u128::from(i)).is_err()
);
}
}
}
#[test]
fn basic_end_to_end_multi() {
let balance_trie = create_balance_trie();
let root = *balance_trie.root();
// Create a proof for a valid and invalid key.
let proof = balance_trie.create_multi_proof(&[6u32, 9u32, 69u32]).unwrap();
let items = [(6u32, 6u128), (9u32, 9u128), (69u32, 69u128)];
assert_eq!(verify_multi_proof::<BlakeTwo256, _, _>(&root, &proof, &items), Ok(()));
}
#[test]
fn proof_fails_with_bad_data() {
let balance_trie = create_balance_trie();
let root = *balance_trie.root();
// Create a proof for a valid key.
let proof = balance_trie.create_proof(&6u32).unwrap();
// Correct data verifies successfully
assert_eq!(verify_proof::<BlakeTwo256, _, _>(&root, &proof, &6u32, &6u128), Ok(()));
// Fail to verify proof with wrong root
assert_eq!(
verify_proof::<BlakeTwo256, _, _>(&Default::default(), &proof, &6u32, &6u128),
Err(TrieError::RootMismatch.into())
);
// Crete a bad proof.
let bad_proof = balance_trie.create_proof(&99u32).unwrap();
// Fail to verify data with the wrong proof
assert_eq!(
verify_proof::<BlakeTwo256, _, _>(&root, &bad_proof, &6u32, &6u128),
Err(TrieError::ExtraneousHashReference.into())
);
}
#[test]
fn proof_to_hashes() {
let mut i: u32 = 1;
// Compute log base 16 and round up
let log16 = |x: u32| -> u32 {
let x_f64 = x as f64;
let log16_x = (x_f64.ln() / 16_f64.ln()).ceil();
log16_x as u32
};
while i < 10_000_000 {
let trie = BalanceTrie::generate_for((0..i).map(|i| (i, u128::from(i)))).unwrap();
let proof = trie.create_proof(&0).unwrap();
let hashes = BalanceTrie::proof_to_hashes(&proof).unwrap();
let log16 = log16(i).max(1);
assert_eq!(hashes, log16);
i = i * 10;
}
}
}
@@ -0,0 +1,288 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Types for a base-2 merkle tree used for checking and generating proofs within the
//! runtime. The `binary-merkle-tree` crate exposes all of these same functionality (and more), but
//! this library is designed to work more easily with runtime native types, which simply need to
//! implement `Encode`/`Decode`.
use super::{ProofToHashes, ProvingTrie, TrieError};
use crate::{Decode, DispatchError, Encode};
use alloc::{collections::BTreeMap, vec::Vec};
use binary_merkle_tree::{merkle_proof, merkle_root, MerkleProof};
use codec::MaxEncodedLen;
/// A helper structure for building a basic base-2 merkle trie and creating compact proofs for that
/// trie.
pub struct BasicProvingTrie<Hashing, Key, Value>
where
Hashing: pezsp_core::Hasher,
{
db: BTreeMap<Key, Value>,
root: Hashing::Out,
_phantom: core::marker::PhantomData<(Key, Value)>,
}
impl<Hashing, Key, Value> ProvingTrie<Hashing, Key, Value> for BasicProvingTrie<Hashing, Key, Value>
where
Hashing: pezsp_core::Hasher,
Hashing::Out: Encode + Decode,
Key: Encode + Decode + Ord,
Value: Encode + Decode + Clone,
{
/// Create a new instance of a `ProvingTrie` using an iterator of key/value pairs.
fn generate_for<I>(items: I) -> Result<Self, DispatchError>
where
I: IntoIterator<Item = (Key, Value)>,
{
let mut db = BTreeMap::default();
for (key, value) in items.into_iter() {
db.insert(key, value);
}
let root = merkle_root::<Hashing, _>(db.iter().map(|item| item.encode()));
Ok(Self { db, root, _phantom: Default::default() })
}
/// Access the underlying trie root.
fn root(&self) -> &Hashing::Out {
&self.root
}
/// Query a value contained within the current trie. Returns `None` if the
/// nodes within the current `db` are insufficient to query the item.
fn query(&self, key: &Key) -> Option<Value> {
self.db.get(&key).cloned()
}
/// Create a compact merkle proof needed to prove a single key and its value are in the trie.
/// Returns an error if the nodes within the current `db` are insufficient to create a proof.
fn create_proof(&self, key: &Key) -> Result<Vec<u8>, DispatchError> {
let mut encoded = Vec::with_capacity(self.db.len());
let mut found_index = None;
// Find the index of our key, and encode the (key, value) pair.
for (i, (k, v)) in self.db.iter().enumerate() {
// If we found the key we are looking for, save it.
if k == key {
found_index = Some(i);
}
encoded.push((k, v).encode());
}
let index = found_index.ok_or(TrieError::IncompleteDatabase)?;
let proof = merkle_proof::<Hashing, Vec<Vec<u8>>, Vec<u8>>(encoded, index as u32);
Ok(proof.encode())
}
/// Verify the existence of `key` and `value` in a given trie root and proof.
fn verify_proof(
root: &Hashing::Out,
proof: &[u8],
key: &Key,
value: &Value,
) -> Result<(), DispatchError> {
verify_proof::<Hashing, Key, Value>(root, proof, key, value)
}
}
impl<Hashing, Key, Value> ProofToHashes for BasicProvingTrie<Hashing, Key, Value>
where
Hashing: pezsp_core::Hasher,
Hashing::Out: MaxEncodedLen + Decode,
Key: Decode,
Value: Decode,
{
// Our proof is just raw bytes.
type Proof = [u8];
// This base 2 merkle trie includes a `proof` field which is a `Vec<Hash>`.
// The length of this vector tells us the depth of the proof, and how many
// hashes we need to calculate.
fn proof_to_hashes(proof: &[u8]) -> Result<u32, DispatchError> {
let decoded_proof: MerkleProof<Hashing::Out, Vec<u8>> =
Decode::decode(&mut &proof[..]).map_err(|_| TrieError::IncompleteProof)?;
let depth = decoded_proof.proof.len();
Ok(depth as u32)
}
}
/// Verify the existence of `key` and `value` in a given trie root and proof.
pub fn verify_proof<Hashing, Key, Value>(
root: &Hashing::Out,
proof: &[u8],
key: &Key,
value: &Value,
) -> Result<(), DispatchError>
where
Hashing: pezsp_core::Hasher,
Hashing::Out: Decode,
Key: Encode + Decode,
Value: Encode + Decode,
{
let decoded_proof: MerkleProof<Hashing::Out, Vec<u8>> =
Decode::decode(&mut &proof[..]).map_err(|_| TrieError::IncompleteProof)?;
if *root != decoded_proof.root {
return Err(TrieError::RootMismatch.into());
}
if (key, value).encode() != decoded_proof.leaf {
return Err(TrieError::ValueMismatch.into());
}
if binary_merkle_tree::verify_proof::<Hashing, _, _>(
&decoded_proof.root,
decoded_proof.proof,
decoded_proof.number_of_leaves,
decoded_proof.leaf_index,
&decoded_proof.leaf,
) {
Ok(())
} else {
Err(TrieError::IncompleteProof.into())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::traits::BlakeTwo256;
use pezsp_core::H256;
use std::collections::BTreeMap;
// A trie which simulates a trie of accounts (u32) and balances (u128).
type BalanceTrie = BasicProvingTrie<BlakeTwo256, u32, u128>;
// The expected root hash for an empty trie.
fn empty_root() -> H256 {
let tree = BalanceTrie::generate_for(Vec::new()).unwrap();
*tree.root()
}
fn create_balance_trie() -> BalanceTrie {
// Create a map of users and their balances.
let mut map = BTreeMap::<u32, u128>::new();
for i in 0..100u32 {
map.insert(i, i.into());
}
// Put items into the trie.
let balance_trie = BalanceTrie::generate_for(map).unwrap();
// Root is changed.
let root = *balance_trie.root();
assert!(root != empty_root());
// Assert valid keys are queryable.
assert_eq!(balance_trie.query(&6u32), Some(6u128));
assert_eq!(balance_trie.query(&9u32), Some(9u128));
assert_eq!(balance_trie.query(&69u32), Some(69u128));
balance_trie
}
#[test]
fn empty_trie_works() {
let empty_trie = BalanceTrie::generate_for(Vec::new()).unwrap();
assert_eq!(*empty_trie.root(), empty_root());
}
#[test]
fn basic_end_to_end_single_value() {
let balance_trie = create_balance_trie();
let root = *balance_trie.root();
// Create a proof for a valid key.
let proof = balance_trie.create_proof(&6u32).unwrap();
// Assert key is provable, all other keys are invalid.
for i in 0..200u32 {
if i == 6 {
assert_eq!(
verify_proof::<BlakeTwo256, _, _>(&root, &proof, &i, &u128::from(i)),
Ok(())
);
// Wrong value is invalid.
assert_eq!(
verify_proof::<BlakeTwo256, _, _>(&root, &proof, &i, &u128::from(i + 1)),
Err(TrieError::ValueMismatch.into())
);
} else {
assert!(
verify_proof::<BlakeTwo256, _, _>(&root, &proof, &i, &u128::from(i)).is_err()
);
}
}
}
#[test]
fn proof_fails_with_bad_data() {
let balance_trie = create_balance_trie();
let root = *balance_trie.root();
// Create a proof for a valid key.
let proof = balance_trie.create_proof(&6u32).unwrap();
// Correct data verifies successfully
assert_eq!(verify_proof::<BlakeTwo256, _, _>(&root, &proof, &6u32, &6u128), Ok(()));
// Fail to verify proof with wrong root
assert_eq!(
verify_proof::<BlakeTwo256, _, _>(&Default::default(), &proof, &6u32, &6u128),
Err(TrieError::RootMismatch.into())
);
// Fail to verify proof with wrong data
assert_eq!(
verify_proof::<BlakeTwo256, _, _>(&root, &[], &6u32, &6u128),
Err(TrieError::IncompleteProof.into())
);
}
// We make assumptions about the structure of the merkle proof in order to provide the
// `proof_to_hashes` function. This test keeps those assumptions checked.
#[test]
fn assert_structure_of_merkle_proof() {
let balance_trie = create_balance_trie();
let root = *balance_trie.root();
// Create a proof for a valid key.
let proof = balance_trie.create_proof(&6u32).unwrap();
let decoded_proof: MerkleProof<H256, Vec<u8>> = Decode::decode(&mut &proof[..]).unwrap();
let constructed_proof = MerkleProof::<H256, Vec<u8>> {
root,
proof: decoded_proof.proof.clone(),
number_of_leaves: 100,
leaf_index: 6,
leaf: (6u32, 6u128).encode(),
};
assert_eq!(constructed_proof, decoded_proof);
}
#[test]
fn proof_to_hashes() {
let mut i: u32 = 1;
while i < 10_000_000 {
let trie = BalanceTrie::generate_for((0..i).map(|i| (i, u128::from(i)))).unwrap();
let proof = trie.create_proof(&0).unwrap();
let hashes = BalanceTrie::proof_to_hashes(&proof).unwrap();
let log2 = (i as f64).log2().ceil() as u32;
assert_eq!(hashes, log2);
i = i * 10;
}
}
}
@@ -0,0 +1,198 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Types for merkle tries compatible with the runtime.
pub mod base16;
pub mod base2;
use crate::{Decode, DecodeWithMemTracking, DispatchError, Encode, MaxEncodedLen, TypeInfo};
#[cfg(feature = "serde")]
use crate::{Deserialize, Serialize};
use alloc::vec::Vec;
use pezsp_trie::{trie_types::TrieError as SpTrieError, VerifyError};
/// A runtime friendly error type for tries.
#[derive(
Eq,
PartialEq,
Clone,
Copy,
Encode,
Decode,
DecodeWithMemTracking,
Debug,
TypeInfo,
MaxEncodedLen,
)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum TrieError {
/* From TrieError */
/// Attempted to create a trie with a state root not in the DB.
InvalidStateRoot,
/// Trie item not found in the database,
IncompleteDatabase,
/// A value was found in the trie with a nibble key that was not byte-aligned.
ValueAtIncompleteKey,
/// Corrupt Trie item.
DecoderError,
/// Hash is not value.
InvalidHash,
/* From VerifyError */
/// The statement being verified contains multiple key-value pairs with the same key.
DuplicateKey,
/// The proof contains at least one extraneous node.
ExtraneousNode,
/// The proof contains at least one extraneous value which should have been omitted from the
/// proof.
ExtraneousValue,
/// The proof contains at least one extraneous hash reference the should have been omitted.
ExtraneousHashReference,
/// The proof contains an invalid child reference that exceeds the hash length.
InvalidChildReference,
/// The proof indicates that an expected value was not found in the trie.
ValueMismatch,
/// The proof is missing trie nodes required to verify.
IncompleteProof,
/// The root hash computed from the proof is incorrect.
RootMismatch,
/// One of the proof nodes could not be decoded.
DecodeError,
}
impl<T> From<SpTrieError<T>> for TrieError {
fn from(error: SpTrieError<T>) -> Self {
match error {
SpTrieError::InvalidStateRoot(..) => Self::InvalidStateRoot,
SpTrieError::IncompleteDatabase(..) => Self::IncompleteDatabase,
SpTrieError::ValueAtIncompleteKey(..) => Self::ValueAtIncompleteKey,
SpTrieError::DecoderError(..) => Self::DecoderError,
SpTrieError::InvalidHash(..) => Self::InvalidHash,
}
}
}
impl<T, U> From<VerifyError<T, U>> for TrieError {
fn from(error: VerifyError<T, U>) -> Self {
match error {
VerifyError::DuplicateKey(..) => Self::DuplicateKey,
VerifyError::ExtraneousNode => Self::ExtraneousNode,
VerifyError::ExtraneousValue(..) => Self::ExtraneousValue,
VerifyError::ExtraneousHashReference(..) => Self::ExtraneousHashReference,
VerifyError::InvalidChildReference(..) => Self::InvalidChildReference,
VerifyError::ValueMismatch(..) => Self::ValueMismatch,
VerifyError::IncompleteProof => Self::IncompleteProof,
VerifyError::RootMismatch(..) => Self::RootMismatch,
VerifyError::DecodeError(..) => Self::DecodeError,
}
}
}
impl From<TrieError> for &'static str {
fn from(e: TrieError) -> &'static str {
match e {
TrieError::InvalidStateRoot => "The state root is not in the database.",
TrieError::IncompleteDatabase => "A trie item was not found in the database.",
TrieError::ValueAtIncompleteKey =>
"A value was found with a key that is not byte-aligned.",
TrieError::DecoderError => "A corrupt trie item was encountered.",
TrieError::InvalidHash => "The hash does not match the expected value.",
TrieError::DuplicateKey => "The proof contains duplicate keys.",
TrieError::ExtraneousNode => "The proof contains extraneous nodes.",
TrieError::ExtraneousValue => "The proof contains extraneous values.",
TrieError::ExtraneousHashReference => "The proof contains extraneous hash references.",
TrieError::InvalidChildReference => "The proof contains an invalid child reference.",
TrieError::ValueMismatch => "The proof indicates a value mismatch.",
TrieError::IncompleteProof => "The proof is incomplete.",
TrieError::RootMismatch => "The root hash computed from the proof is incorrect.",
TrieError::DecodeError => "One of the proof nodes could not be decoded.",
}
}
}
/// An interface for creating, interacting with, and creating proofs in a merkle trie.
pub trait ProvingTrie<Hashing, Key, Value>
where
Self: Sized,
Hashing: pezsp_core::Hasher,
{
/// Create a new instance of a `ProvingTrie` using an iterator of key/value pairs.
fn generate_for<I>(items: I) -> Result<Self, DispatchError>
where
I: IntoIterator<Item = (Key, Value)>;
/// Access the underlying trie root.
fn root(&self) -> &Hashing::Out;
/// Query a value contained within the current trie. Returns `None` if the
/// the value does not exist in the trie.
fn query(&self, key: &Key) -> Option<Value>;
/// Create a proof that can be used to verify a key and its value are in the trie.
fn create_proof(&self, key: &Key) -> Result<Vec<u8>, DispatchError>;
/// Verify the existence of `key` and `value` in a given trie root and proof.
fn verify_proof(
root: &Hashing::Out,
proof: &[u8],
key: &Key,
value: &Value,
) -> Result<(), DispatchError>;
}
/// This trait is one strategy that can be used to benchmark a trie proof verification for the
/// runtime. This strategy assumes that the majority complexity of verifying a merkle proof comes
/// from computing hashes to recreate the merkle root. This trait converts the the proof, some
/// bytes, to the number of hashes we expect to execute to verify that proof.
pub trait ProofToHashes {
/// The Proof type we will use to determine the number of hashes.
type Proof: ?Sized;
/// This function returns the number of hashes we expect to calculate based on the
/// size of the proof. This is used for benchmarking, so for worst case scenario, we should
/// round up.
///
/// The major complexity of doing a `verify_proof` is computing the hashes needed
/// to calculate the merkle root. For tries, it should be easy to predict the depth
/// of the trie (which is equivalent to the hashes), by looking at the length of the proof.
fn proof_to_hashes(proof: &Self::Proof) -> Result<u32, DispatchError>;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::traits::BlakeTwo256;
// A trie which simulates a trie of accounts (u32) and balances (u128).
type BalanceTrie2 = base2::BasicProvingTrie<BlakeTwo256, u32, u128>;
type BalanceTrie16 = base16::BasicProvingTrie<BlakeTwo256, u32, u128>;
#[test]
fn basic_api_usage_base_2() {
let balance_trie = BalanceTrie2::generate_for((0..100u32).map(|i| (i, i.into()))).unwrap();
let root = *balance_trie.root();
assert_eq!(balance_trie.query(&69), Some(69));
assert_eq!(balance_trie.query(&6969), None);
let proof = balance_trie.create_proof(&69u32).unwrap();
assert_eq!(BalanceTrie2::verify_proof(&root, &proof, &69u32, &69u128), Ok(()));
}
#[test]
fn basic_api_usage_base_16() {
let balance_trie = BalanceTrie16::generate_for((0..100u32).map(|i| (i, i.into()))).unwrap();
let root = *balance_trie.root();
assert_eq!(balance_trie.query(&69), Some(69));
assert_eq!(balance_trie.query(&6969), None);
let proof = balance_trie.create_proof(&69u32).unwrap();
assert_eq!(BalanceTrie16::verify_proof(&root, &proof, &69u32, &69u128), Ok(()));
}
}