1pub 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 sp_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 TrieError::DecoderError => "A corrupt trie item was encountered.",
113 TrieError::InvalidHash => "The hash does not match the expected value.",
114 TrieError::DuplicateKey => "The proof contains duplicate keys.",
115 TrieError::ExtraneousNode => "The proof contains extraneous nodes.",
116 TrieError::ExtraneousValue => "The proof contains extraneous values.",
117 TrieError::ExtraneousHashReference => "The proof contains extraneous hash references.",
118 TrieError::InvalidChildReference => "The proof contains an invalid child reference.",
119 TrieError::ValueMismatch => "The proof indicates a value mismatch.",
120 TrieError::IncompleteProof => "The proof is incomplete.",
121 TrieError::RootMismatch => "The root hash computed from the proof is incorrect.",
122 TrieError::DecodeError => "One of the proof nodes could not be decoded.",
123 }
124 }
125}
126
127pub trait ProvingTrie<Hashing, Key, Value>
129where
130 Self: Sized,
131 Hashing: sp_core::Hasher,
132{
133 fn generate_for<I>(items: I) -> Result<Self, DispatchError>
135 where
136 I: IntoIterator<Item = (Key, Value)>;
137 fn root(&self) -> &Hashing::Out;
139 fn query(&self, key: &Key) -> Option<Value>;
142 fn create_proof(&self, key: &Key) -> Result<Vec<u8>, DispatchError>;
144 fn verify_proof(
146 root: &Hashing::Out,
147 proof: &[u8],
148 key: &Key,
149 value: &Value,
150 ) -> Result<(), DispatchError>;
151}
152
153pub trait ProofToHashes {
158 type Proof: ?Sized;
160 fn proof_to_hashes(proof: &Self::Proof) -> Result<u32, DispatchError>;
168}
169
170#[cfg(test)]
171mod tests {
172 use super::*;
173 use crate::traits::BlakeTwo256;
174
175 type BalanceTrie2 = base2::BasicProvingTrie<BlakeTwo256, u32, u128>;
177 type BalanceTrie16 = base16::BasicProvingTrie<BlakeTwo256, u32, u128>;
178
179 #[test]
180 fn basic_api_usage_base_2() {
181 let balance_trie = BalanceTrie2::generate_for((0..100u32).map(|i| (i, i.into()))).unwrap();
182 let root = *balance_trie.root();
183 assert_eq!(balance_trie.query(&69), Some(69));
184 assert_eq!(balance_trie.query(&6969), None);
185 let proof = balance_trie.create_proof(&69u32).unwrap();
186 assert_eq!(BalanceTrie2::verify_proof(&root, &proof, &69u32, &69u128), Ok(()));
187 }
188
189 #[test]
190 fn basic_api_usage_base_16() {
191 let balance_trie = BalanceTrie16::generate_for((0..100u32).map(|i| (i, i.into()))).unwrap();
192 let root = *balance_trie.root();
193 assert_eq!(balance_trie.query(&69), Some(69));
194 assert_eq!(balance_trie.query(&6969), None);
195 let proof = balance_trie.create_proof(&69u32).unwrap();
196 assert_eq!(BalanceTrie16::verify_proof(&root, &proof, &69u32, &69u128), Ok(()));
197 }
198}