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