mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-15 17:21:08 +00:00
Expose proof generation and verifying api. (#4646)
* Expose proof generation and verifying api. * tabs to spaces * bring back license comment * Revert "tabs to spaces" This reverts commit 4c3f72f9ef76b6a9f8988ed15b1bab17a9e51d2f. * Formatting and docs nits * Bump deps versions * Upadte Cargo.lock * into -> in
This commit is contained in:
committed by
Bastian Köcher
parent
d5ecec3775
commit
ad60af5f13
@@ -27,6 +27,8 @@ use sp_std::boxed::Box;
|
||||
use sp_std::marker::PhantomData;
|
||||
use sp_std::vec::Vec;
|
||||
use hash_db::{Hasher, Prefix};
|
||||
use trie_db::proof::{generate_proof, verify_proof};
|
||||
pub use trie_db::proof::VerifyError;
|
||||
/// Our `NodeCodec`-specific error.
|
||||
pub use error::Error;
|
||||
/// The Substrate format implementation of `TrieStream`.
|
||||
@@ -119,6 +121,47 @@ pub mod trie_types {
|
||||
pub type TrieError<H> = trie_db::TrieError<H, super::Error>;
|
||||
}
|
||||
|
||||
/// Create a proof for a subset of keys in a trie.
|
||||
///
|
||||
/// The `keys` may contain any set of keys regardless of each one of them is included
|
||||
/// in the `db`.
|
||||
///
|
||||
/// For a key `K` that is included in the `db` a proof of inclusion is generated.
|
||||
/// For a key `K` that is not included in the `db` a proof of non-inclusion is generated.
|
||||
/// These can be later checked in `verify_trie_proof`.
|
||||
pub fn generate_trie_proof<'a, L: TrieConfiguration, I, K, DB>(
|
||||
db: &DB,
|
||||
root: TrieHash<L>,
|
||||
keys: I,
|
||||
) -> Result<Vec<Vec<u8>>, Box<TrieError<L>>> where
|
||||
I: IntoIterator<Item=&'a K>,
|
||||
K: 'a + AsRef<[u8]>,
|
||||
DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
|
||||
{
|
||||
let trie = TrieDB::<L>::new(db, &root)?;
|
||||
generate_proof(&trie, keys)
|
||||
}
|
||||
|
||||
/// Verify a set of key-value pairs against a trie root and a proof.
|
||||
///
|
||||
/// Checks a set of keys with optional values for inclusion in the proof that was generated by
|
||||
/// `generate_trie_proof`.
|
||||
/// If the value in the pair is supplied (`(key, Some(value))`), this key-value pair will be
|
||||
/// checked for inclusion in the proof.
|
||||
/// If the value is omitted (`(key, None)`), this key will be checked for non-inclusion in the
|
||||
/// proof.
|
||||
pub fn verify_trie_proof<'a, L: TrieConfiguration, I, K, V>(
|
||||
root: &TrieHash<L>,
|
||||
proof: &[Vec<u8>],
|
||||
items: I,
|
||||
) -> Result<(), VerifyError<TrieHash<L>, error::Error>> where
|
||||
I: IntoIterator<Item=&'a (K, Option<V>)>,
|
||||
K: 'a + AsRef<[u8]>,
|
||||
V: 'a + AsRef<[u8]>,
|
||||
{
|
||||
verify_proof::<Layout<L::Hash>, _, _, _>(root, proof, items)
|
||||
}
|
||||
|
||||
/// Determine a trie root given a hash DB and delta values.
|
||||
pub fn delta_trie_root<L: TrieConfiguration, I, A, B, DB>(
|
||||
db: &mut DB,
|
||||
@@ -727,4 +770,89 @@ mod tests {
|
||||
|
||||
assert_eq!(pairs, iter_pairs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn proof_non_inclusion_works() {
|
||||
let pairs = vec![
|
||||
(hex!("0102").to_vec(), hex!("01").to_vec()),
|
||||
(hex!("0203").to_vec(), hex!("0405").to_vec()),
|
||||
];
|
||||
|
||||
let mut memdb = MemoryDB::default();
|
||||
let mut root = Default::default();
|
||||
populate_trie::<Layout>(&mut memdb, &mut root, &pairs);
|
||||
|
||||
let non_included_key: Vec<u8> = hex!("0909").to_vec();
|
||||
let proof = generate_trie_proof::<Layout, _, _, _>(
|
||||
&memdb,
|
||||
root,
|
||||
&[non_included_key.clone()]
|
||||
).unwrap();
|
||||
|
||||
// Verifying that the K was not included into the trie should work.
|
||||
assert!(verify_trie_proof::<Layout, _, _, Vec<u8>>(
|
||||
&root,
|
||||
&proof,
|
||||
&[(non_included_key.clone(), None)],
|
||||
).is_ok()
|
||||
);
|
||||
|
||||
// Verifying that the K was included into the trie should fail.
|
||||
assert!(verify_trie_proof::<Layout, _, _, Vec<u8>>(
|
||||
&root,
|
||||
&proof,
|
||||
&[(non_included_key, Some(hex!("1010").to_vec()))],
|
||||
).is_err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn proof_inclusion_works() {
|
||||
let pairs = vec![
|
||||
(hex!("0102").to_vec(), hex!("01").to_vec()),
|
||||
(hex!("0203").to_vec(), hex!("0405").to_vec()),
|
||||
];
|
||||
|
||||
let mut memdb = MemoryDB::default();
|
||||
let mut root = Default::default();
|
||||
populate_trie::<Layout>(&mut memdb, &mut root, &pairs);
|
||||
|
||||
let proof = generate_trie_proof::<Layout, _, _, _>(
|
||||
&memdb,
|
||||
root,
|
||||
&[pairs[0].0.clone()]
|
||||
).unwrap();
|
||||
|
||||
// Check that a K, V included into the proof are verified.
|
||||
assert!(verify_trie_proof::<Layout, _, _, _>(
|
||||
&root,
|
||||
&proof,
|
||||
&[(pairs[0].0.clone(), Some(pairs[0].1.clone()))]
|
||||
).is_ok()
|
||||
);
|
||||
|
||||
// Absence of the V is not verified with the proof that has K, V included.
|
||||
assert!(verify_trie_proof::<Layout, _, _, Vec<u8>>(
|
||||
&root,
|
||||
&proof,
|
||||
&[(pairs[0].0.clone(), None)]
|
||||
).is_err()
|
||||
);
|
||||
|
||||
// K not included into the trie is not verified.
|
||||
assert!(verify_trie_proof::<Layout, _, _, _>(
|
||||
&root,
|
||||
&proof,
|
||||
&[(hex!("4242").to_vec(), Some(pairs[0].1.clone()))]
|
||||
).is_err()
|
||||
);
|
||||
|
||||
// K included into the trie but not included into the proof is not verified.
|
||||
assert!(verify_trie_proof::<Layout, _, _, _>(
|
||||
&root,
|
||||
&proof,
|
||||
&[(pairs[1].0.clone(), Some(pairs[1].1.clone()))]
|
||||
).is_err()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user