frame_support/traits/
proving.rs1use alloc::vec::Vec;
21use codec::{Decode, Encode};
22use sp_core::Hasher;
23use sp_runtime::DispatchError;
24
25pub use sp_runtime::proving_trie::*;
27
28pub trait VerifyExistenceProof {
30 type Proof;
32 type Hash;
34
35 fn verify_proof(proof: Self::Proof, root: &Self::Hash) -> Result<Vec<u8>, DispatchError>;
39}
40
41pub struct BinaryMerkleTreeProver<H>(core::marker::PhantomData<H>);
43
44impl<H: Hasher> VerifyExistenceProof for BinaryMerkleTreeProver<H>
45where
46 H::Out: Decode + Encode,
47{
48 type Proof = binary_merkle_tree::MerkleProof<H::Out, Vec<u8>>;
49 type Hash = H::Out;
50
51 fn verify_proof(proof: Self::Proof, root: &Self::Hash) -> Result<Vec<u8>, DispatchError> {
52 if proof.root != *root {
53 return Err(TrieError::RootMismatch.into());
54 }
55
56 if binary_merkle_tree::verify_proof::<H, _, _>(
57 &proof.root,
58 proof.proof,
59 proof.number_of_leaves,
60 proof.leaf_index,
61 &proof.leaf,
62 ) {
63 Ok(proof.leaf)
64 } else {
65 Err(TrieError::IncompleteProof.into())
66 }
67 }
68}
69
70impl<H: Hasher> ProofToHashes for BinaryMerkleTreeProver<H> {
71 type Proof = binary_merkle_tree::MerkleProof<H::Out, Vec<u8>>;
72
73 fn proof_to_hashes(proof: &Self::Proof) -> Result<u32, DispatchError> {
77 let depth = proof.proof.len();
78 Ok(depth as u32)
79 }
80}
81
82#[derive(Encode, Decode, Clone)]
84pub struct SixteenPatriciaMerkleTreeExistenceProof {
85 pub key: Vec<u8>,
87 pub value: Vec<u8>,
89 pub proof: Vec<Vec<u8>>,
91}
92
93pub struct SixteenPatriciaMerkleTreeProver<H>(core::marker::PhantomData<H>);
95
96impl<H: Hasher> VerifyExistenceProof for SixteenPatriciaMerkleTreeProver<H> {
97 type Proof = SixteenPatriciaMerkleTreeExistenceProof;
98 type Hash = H::Out;
99
100 fn verify_proof(proof: Self::Proof, root: &Self::Hash) -> Result<Vec<u8>, DispatchError> {
101 sp_trie::verify_trie_proof::<sp_trie::LayoutV1<H>, _, _, _>(
102 &root,
103 &proof.proof,
104 [&(&proof.key, Some(&proof.value))],
105 )
106 .map_err(|err| TrieError::from(err).into())
107 .map(|_| proof.value)
108 }
109}
110
111impl<H: Hasher> ProofToHashes for SixteenPatriciaMerkleTreeProver<H> {
112 type Proof = SixteenPatriciaMerkleTreeExistenceProof;
113
114 fn proof_to_hashes(proof: &Self::Proof) -> Result<u32, DispatchError> {
117 let depth = proof.proof.len();
118 Ok(depth as u32)
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125 use sp_runtime::{
126 proving_trie::{base16::BasicProvingTrie, ProvingTrie},
127 traits::BlakeTwo256,
128 };
129
130 #[test]
131 fn verify_binary_merkle_tree_prover_works() {
132 let proof = binary_merkle_tree::merkle_proof::<BlakeTwo256, _, _>(
133 vec![b"hey".encode(), b"yes".encode()],
134 1,
135 );
136 let root = proof.root;
137
138 assert_eq!(
139 BinaryMerkleTreeProver::<BlakeTwo256>::verify_proof(proof, &root).unwrap(),
140 b"yes".encode()
141 );
142 }
143
144 #[test]
145 fn verify_sixteen_patricia_merkle_tree_prover_works() {
146 let trie = BasicProvingTrie::<BlakeTwo256, u32, _>::generate_for(vec![
147 (0u32, String::from("hey")),
148 (1u32, String::from("yes")),
149 ])
150 .unwrap();
151 let proof = trie.create_proof(&1u32).unwrap();
152 let structured_proof: Vec<Vec<u8>> = Decode::decode(&mut &proof[..]).unwrap();
153 let root = *trie.root();
154
155 let proof = SixteenPatriciaMerkleTreeExistenceProof {
156 key: 1u32.encode(),
157 value: String::from("yes").encode(),
158 proof: structured_proof,
159 };
160
161 assert_eq!(
162 SixteenPatriciaMerkleTreeProver::<BlakeTwo256>::verify_proof(proof, &root).unwrap(),
163 String::from("yes").encode()
164 );
165 }
166
167 #[test]
168 fn proof_to_hashes_sixteen() {
169 let mut i: u32 = 1;
170
171 let log16 = |x: u32| -> u32 {
173 let x_f64 = x as f64;
174 let log16_x = (x_f64.ln() / 16_f64.ln()).ceil();
175 log16_x as u32
176 };
177
178 while i < 10_000_000 {
179 let trie = BasicProvingTrie::<BlakeTwo256, u32, _>::generate_for(
180 (0..i).map(|i| (i, u128::from(i))),
181 )
182 .unwrap();
183 let proof = trie.create_proof(&0).unwrap();
184 let structured_proof: Vec<Vec<u8>> = Decode::decode(&mut &proof[..]).unwrap();
185 let root = *trie.root();
186
187 let proof = SixteenPatriciaMerkleTreeExistenceProof {
188 key: 0u32.encode(),
189 value: 0u128.encode(),
190 proof: structured_proof,
191 };
192 let hashes =
193 SixteenPatriciaMerkleTreeProver::<BlakeTwo256>::proof_to_hashes(&proof).unwrap();
194 let log16 = log16(i).max(1);
195 assert_eq!(hashes, log16);
196
197 assert_eq!(
198 SixteenPatriciaMerkleTreeProver::<BlakeTwo256>::verify_proof(proof.clone(), &root)
199 .unwrap(),
200 proof.value
201 );
202
203 i = i * 10;
204 }
205 }
206
207 #[test]
208 fn proof_to_hashes_binary() {
209 let mut i: u32 = 1;
210 while i < 10_000_000 {
211 let proof = binary_merkle_tree::merkle_proof::<BlakeTwo256, _, _>(
212 (0..i).map(|i| u128::from(i).encode()),
213 0,
214 );
215 let root = proof.root;
216
217 let hashes = BinaryMerkleTreeProver::<BlakeTwo256>::proof_to_hashes(&proof).unwrap();
218 let log2 = (i as f64).log2().ceil() as u32;
219 assert_eq!(hashes, log2);
220
221 assert_eq!(
222 BinaryMerkleTreeProver::<BlakeTwo256>::verify_proof(proof, &root).unwrap(),
223 0u128.encode()
224 );
225
226 i = i * 10;
227 }
228 }
229}