pezsp_runtime/proving_trie/
mod.rs1pub mod base16;
21pub mod base2;
22
23use crate::{Decode, DecodeWithMemTracking, DispatchError, Encode, MaxEncodedLen, TypeInfo};
24#[cfg(feature = "serde")]
25use crate::{Deserialize, Serialize};
26use alloc::vec::Vec;
27use pezsp_trie::{trie_types::TrieError as SpTrieError, VerifyError};
28
29#[derive(
31 Eq,
32 PartialEq,
33 Clone,
34 Copy,
35 Encode,
36 Decode,
37 DecodeWithMemTracking,
38 Debug,
39 TypeInfo,
40 MaxEncodedLen,
41)]
42#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
43pub enum TrieError {
44 InvalidStateRoot,
47 IncompleteDatabase,
49 ValueAtIncompleteKey,
51 DecoderError,
53 InvalidHash,
55 DuplicateKey,
58 ExtraneousNode,
60 ExtraneousValue,
63 ExtraneousHashReference,
65 InvalidChildReference,
67 ValueMismatch,
69 IncompleteProof,
71 RootMismatch,
73 DecodeError,
75}
76
77impl<T> From<SpTrieError<T>> for TrieError {
78 fn from(error: SpTrieError<T>) -> Self {
79 match error {
80 SpTrieError::InvalidStateRoot(..) => Self::InvalidStateRoot,
81 SpTrieError::IncompleteDatabase(..) => Self::IncompleteDatabase,
82 SpTrieError::ValueAtIncompleteKey(..) => Self::ValueAtIncompleteKey,
83 SpTrieError::DecoderError(..) => Self::DecoderError,
84 SpTrieError::InvalidHash(..) => Self::InvalidHash,
85 }
86 }
87}
88
89impl<T, U> From<VerifyError<T, U>> for TrieError {
90 fn from(error: VerifyError<T, U>) -> Self {
91 match error {
92 VerifyError::DuplicateKey(..) => Self::DuplicateKey,
93 VerifyError::ExtraneousNode => Self::ExtraneousNode,
94 VerifyError::ExtraneousValue(..) => Self::ExtraneousValue,
95 VerifyError::ExtraneousHashReference(..) => Self::ExtraneousHashReference,
96 VerifyError::InvalidChildReference(..) => Self::InvalidChildReference,
97 VerifyError::ValueMismatch(..) => Self::ValueMismatch,
98 VerifyError::IncompleteProof => Self::IncompleteProof,
99 VerifyError::RootMismatch(..) => Self::RootMismatch,
100 VerifyError::DecodeError(..) => Self::DecodeError,
101 }
102 }
103}
104
105impl From<TrieError> for &'static str {
106 fn from(e: TrieError) -> &'static str {
107 match e {
108 TrieError::InvalidStateRoot => "The state root is not in the database.",
109 TrieError::IncompleteDatabase => "A trie item was not found in the database.",
110 TrieError::ValueAtIncompleteKey => {
111 "A value was found with a key that is not byte-aligned."
112 },
113 TrieError::DecoderError => "A corrupt trie item was encountered.",
114 TrieError::InvalidHash => "The hash does not match the expected value.",
115 TrieError::DuplicateKey => "The proof contains duplicate keys.",
116 TrieError::ExtraneousNode => "The proof contains extraneous nodes.",
117 TrieError::ExtraneousValue => "The proof contains extraneous values.",
118 TrieError::ExtraneousHashReference => "The proof contains extraneous hash references.",
119 TrieError::InvalidChildReference => "The proof contains an invalid child reference.",
120 TrieError::ValueMismatch => "The proof indicates a value mismatch.",
121 TrieError::IncompleteProof => "The proof is incomplete.",
122 TrieError::RootMismatch => "The root hash computed from the proof is incorrect.",
123 TrieError::DecodeError => "One of the proof nodes could not be decoded.",
124 }
125 }
126}
127
128pub trait ProvingTrie<Hashing, Key, Value>
130where
131 Self: Sized,
132 Hashing: pezsp_core::Hasher,
133{
134 fn generate_for<I>(items: I) -> Result<Self, DispatchError>
136 where
137 I: IntoIterator<Item = (Key, Value)>;
138 fn root(&self) -> &Hashing::Out;
140 fn query(&self, key: &Key) -> Option<Value>;
143 fn create_proof(&self, key: &Key) -> Result<Vec<u8>, DispatchError>;
145 fn verify_proof(
147 root: &Hashing::Out,
148 proof: &[u8],
149 key: &Key,
150 value: &Value,
151 ) -> Result<(), DispatchError>;
152}
153
154pub trait ProofToHashes {
159 type Proof: ?Sized;
161 fn proof_to_hashes(proof: &Self::Proof) -> Result<u32, DispatchError>;
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174 use crate::traits::BlakeTwo256;
175
176 type BalanceTrie2 = base2::BasicProvingTrie<BlakeTwo256, u32, u128>;
178 type BalanceTrie16 = base16::BasicProvingTrie<BlakeTwo256, u32, u128>;
179
180 #[test]
181 fn basic_api_usage_base_2() {
182 let balance_trie = BalanceTrie2::generate_for((0..100u32).map(|i| (i, i.into()))).unwrap();
183 let root = *balance_trie.root();
184 assert_eq!(balance_trie.query(&69), Some(69));
185 assert_eq!(balance_trie.query(&6969), None);
186 let proof = balance_trie.create_proof(&69u32).unwrap();
187 assert_eq!(BalanceTrie2::verify_proof(&root, &proof, &69u32, &69u128), Ok(()));
188 }
189
190 #[test]
191 fn basic_api_usage_base_16() {
192 let balance_trie = BalanceTrie16::generate_for((0..100u32).map(|i| (i, i.into()))).unwrap();
193 let root = *balance_trie.root();
194 assert_eq!(balance_trie.query(&69), Some(69));
195 assert_eq!(balance_trie.query(&6969), None);
196 let proof = balance_trie.create_proof(&69u32).unwrap();
197 assert_eq!(BalanceTrie16::verify_proof(&root, &proof, &69u32, &69u128), Ok(()));
198 }
199}