1pub mod base16;
21pub mod base2;
22
23use crate::{Decode, DispatchError, Encode, MaxEncodedLen, TypeInfo};
24#[cfg(feature = "serde")]
25use crate::{Deserialize, Serialize};
26use sp_std::vec::Vec;
27use sp_trie::{trie_types::TrieError as SpTrieError, VerifyError};
28
29#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
31#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
32pub enum TrieError {
33 InvalidStateRoot,
36 IncompleteDatabase,
38 ValueAtIncompleteKey,
40 DecoderError,
42 InvalidHash,
44 DuplicateKey,
47 ExtraneousNode,
49 ExtraneousValue,
52 ExtraneousHashReference,
54 InvalidChildReference,
56 ValueMismatch,
58 IncompleteProof,
60 RootMismatch,
62 DecodeError,
64}
65
66impl<T> From<SpTrieError<T>> for TrieError {
67 fn from(error: SpTrieError<T>) -> Self {
68 match error {
69 SpTrieError::InvalidStateRoot(..) => Self::InvalidStateRoot,
70 SpTrieError::IncompleteDatabase(..) => Self::IncompleteDatabase,
71 SpTrieError::ValueAtIncompleteKey(..) => Self::ValueAtIncompleteKey,
72 SpTrieError::DecoderError(..) => Self::DecoderError,
73 SpTrieError::InvalidHash(..) => Self::InvalidHash,
74 }
75 }
76}
77
78impl<T, U> From<VerifyError<T, U>> for TrieError {
79 fn from(error: VerifyError<T, U>) -> Self {
80 match error {
81 VerifyError::DuplicateKey(..) => Self::DuplicateKey,
82 VerifyError::ExtraneousNode => Self::ExtraneousNode,
83 VerifyError::ExtraneousValue(..) => Self::ExtraneousValue,
84 VerifyError::ExtraneousHashReference(..) => Self::ExtraneousHashReference,
85 VerifyError::InvalidChildReference(..) => Self::InvalidChildReference,
86 VerifyError::ValueMismatch(..) => Self::ValueMismatch,
87 VerifyError::IncompleteProof => Self::IncompleteProof,
88 VerifyError::RootMismatch(..) => Self::RootMismatch,
89 VerifyError::DecodeError(..) => Self::DecodeError,
90 }
91 }
92}
93
94impl From<TrieError> for &'static str {
95 fn from(e: TrieError) -> &'static str {
96 match e {
97 TrieError::InvalidStateRoot => "The state root is not in the database.",
98 TrieError::IncompleteDatabase => "A trie item was not found in the database.",
99 TrieError::ValueAtIncompleteKey =>
100 "A value was found with a key that is not byte-aligned.",
101 TrieError::DecoderError => "A corrupt trie item was encountered.",
102 TrieError::InvalidHash => "The hash does not match the expected value.",
103 TrieError::DuplicateKey => "The proof contains duplicate keys.",
104 TrieError::ExtraneousNode => "The proof contains extraneous nodes.",
105 TrieError::ExtraneousValue => "The proof contains extraneous values.",
106 TrieError::ExtraneousHashReference => "The proof contains extraneous hash references.",
107 TrieError::InvalidChildReference => "The proof contains an invalid child reference.",
108 TrieError::ValueMismatch => "The proof indicates a value mismatch.",
109 TrieError::IncompleteProof => "The proof is incomplete.",
110 TrieError::RootMismatch => "The root hash computed from the proof is incorrect.",
111 TrieError::DecodeError => "One of the proof nodes could not be decoded.",
112 }
113 }
114}
115
116pub trait ProvingTrie<Hashing, Key, Value>
118where
119 Self: Sized,
120 Hashing: sp_core::Hasher,
121{
122 fn generate_for<I>(items: I) -> Result<Self, DispatchError>
124 where
125 I: IntoIterator<Item = (Key, Value)>;
126 fn root(&self) -> &Hashing::Out;
128 fn query(&self, key: &Key) -> Option<Value>;
131 fn create_proof(&self, key: &Key) -> Result<Vec<u8>, DispatchError>;
133 fn verify_proof(
135 root: &Hashing::Out,
136 proof: &[u8],
137 key: &Key,
138 value: &Value,
139 ) -> Result<(), DispatchError>;
140}
141
142pub trait ProofToHashes {
147 type Proof: ?Sized;
149 fn proof_to_hashes(proof: &Self::Proof) -> Result<u32, DispatchError>;
157}
158
159#[cfg(test)]
160mod tests {
161 use super::*;
162 use crate::traits::BlakeTwo256;
163
164 type BalanceTrie2 = base2::BasicProvingTrie<BlakeTwo256, u32, u128>;
166 type BalanceTrie16 = base16::BasicProvingTrie<BlakeTwo256, u32, u128>;
167
168 #[test]
169 fn basic_api_usage_base_2() {
170 let balance_trie = BalanceTrie2::generate_for((0..100u32).map(|i| (i, i.into()))).unwrap();
171 let root = *balance_trie.root();
172 assert_eq!(balance_trie.query(&69), Some(69));
173 assert_eq!(balance_trie.query(&6969), None);
174 let proof = balance_trie.create_proof(&69u32).unwrap();
175 assert_eq!(BalanceTrie2::verify_proof(&root, &proof, &69u32, &69u128), Ok(()));
176 }
177
178 #[test]
179 fn basic_api_usage_base_16() {
180 let balance_trie = BalanceTrie16::generate_for((0..100u32).map(|i| (i, i.into()))).unwrap();
181 let root = *balance_trie.root();
182 assert_eq!(balance_trie.query(&69), Some(69));
183 assert_eq!(balance_trie.query(&6969), None);
184 let proof = balance_trie.create_proof(&69u32).unwrap();
185 assert_eq!(BalanceTrie16::verify_proof(&root, &proof, &69u32, &69u128), Ok(()));
186 }
187}