mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 03:31:05 +00:00
Merkle Mountain Range pallet improvements (#7891)
* Add stateless verification helper function. * Split MMR primitives. * Add RuntimeAPI * RuntimeAPI with OpaqueLeaves * Bump spec_version,. * Move primitives back to frame. * Fix OpaqueLeaf encoding. * Add block number to frame_system implementation of LeafDataProvider. * Relax leaf codec requirements and fix OpaqueLeaf * Add root to debug line. * Apply suggestions from code review Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com> * Typo. Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>
This commit is contained in:
@@ -17,7 +17,6 @@
|
||||
|
||||
use crate::*;
|
||||
use crate::mock::*;
|
||||
use crate::primitives::{Proof, Compact};
|
||||
|
||||
use frame_support::traits::OnInitialize;
|
||||
use sp_core::{
|
||||
@@ -27,6 +26,7 @@ use sp_core::{
|
||||
OffchainExt,
|
||||
},
|
||||
};
|
||||
use pallet_mmr_primitives::{Proof, Compact};
|
||||
|
||||
pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
|
||||
frame_system::GenesisConfig::default().build_storage::<Test>().unwrap().into()
|
||||
@@ -55,12 +55,14 @@ pub(crate) fn hex(s: &str) -> H256 {
|
||||
s.parse().unwrap()
|
||||
}
|
||||
|
||||
type BlockNumber = <Test as frame_system::Config>::BlockNumber;
|
||||
|
||||
fn decode_node(v: Vec<u8>) -> mmr::Node<
|
||||
<Test as Config>::Hashing,
|
||||
(H256, LeafData),
|
||||
((BlockNumber, H256), LeafData),
|
||||
> {
|
||||
use crate::primitives::DataOrHash;
|
||||
type A = DataOrHash::<<Test as Config>::Hashing, H256>;
|
||||
type A = DataOrHash::<<Test as Config>::Hashing, (BlockNumber, H256)>;
|
||||
type B = DataOrHash::<<Test as Config>::Hashing, LeafData>;
|
||||
type Node = mmr::Node<<Test as Config>::Hashing, (A, B)>;
|
||||
let tuple: Node = codec::Decode::decode(&mut &v[..]).unwrap();
|
||||
@@ -97,10 +99,10 @@ fn should_start_empty() {
|
||||
// then
|
||||
assert_eq!(crate::NumberOfLeaves::<DefaultInstance>::get(), 1);
|
||||
assert_eq!(crate::Nodes::<Test>::get(0),
|
||||
Some(hex("da5e6d0616e05c6a6348605a37ca33493fc1a15ad1e6a405ee05c17843fdafed")));
|
||||
Some(hex("4320435e8c3318562dba60116bdbcc0b82ffcecb9bb39aae3300cfda3ad0b8b0")));
|
||||
assert_eq!(
|
||||
crate::RootHash::<Test>::get(),
|
||||
hex("da5e6d0616e05c6a6348605a37ca33493fc1a15ad1e6a405ee05c17843fdafed")
|
||||
hex("4320435e8c3318562dba60116bdbcc0b82ffcecb9bb39aae3300cfda3ad0b8b0")
|
||||
);
|
||||
assert!(weight != 0);
|
||||
});
|
||||
@@ -117,32 +119,34 @@ fn should_append_to_mmr_when_on_initialize_is_called() {
|
||||
|
||||
// then
|
||||
assert_eq!(crate::NumberOfLeaves::<DefaultInstance>::get(), 2);
|
||||
assert_eq!(crate::Nodes::<Test>::get(0),
|
||||
Some(hex("da5e6d0616e05c6a6348605a37ca33493fc1a15ad1e6a405ee05c17843fdafed")));
|
||||
assert_eq!(crate::Nodes::<Test>::get(1),
|
||||
Some(hex("ff5d891b28463a3440e1b650984685efdf260e482cb3807d53c49090841e755f")));
|
||||
assert_eq!(crate::Nodes::<Test>::get(2),
|
||||
Some(hex("bc54778fab79f586f007bd408dca2c4aa07959b27d1f2c8f4f2549d1fcfac8f8")));
|
||||
assert_eq!(crate::Nodes::<Test>::get(3), None);
|
||||
assert_eq!(
|
||||
assert_eq!((
|
||||
crate::Nodes::<Test>::get(0),
|
||||
crate::Nodes::<Test>::get(1),
|
||||
crate::Nodes::<Test>::get(2),
|
||||
crate::Nodes::<Test>::get(3),
|
||||
crate::RootHash::<Test>::get(),
|
||||
hex("bc54778fab79f586f007bd408dca2c4aa07959b27d1f2c8f4f2549d1fcfac8f8")
|
||||
);
|
||||
), (
|
||||
Some(hex("4320435e8c3318562dba60116bdbcc0b82ffcecb9bb39aae3300cfda3ad0b8b0")),
|
||||
Some(hex("ad4cbc033833612ccd4626d5f023b9dfc50a35e838514dd1f3c86f8506728705")),
|
||||
Some(hex("672c04a9cd05a644789d769daa552d35d8de7c33129f8a7cbf49e595234c4854")),
|
||||
None,
|
||||
hex("672c04a9cd05a644789d769daa552d35d8de7c33129f8a7cbf49e595234c4854"),
|
||||
));
|
||||
});
|
||||
|
||||
// make sure the leaves end up in the offchain DB
|
||||
ext.persist_offchain_overlay();
|
||||
let offchain_db = ext.offchain_db();
|
||||
assert_eq!(offchain_db.get(&MMR::offchain_key(0)).map(decode_node), Some(mmr::Node::Data((
|
||||
H256::repeat_byte(1),
|
||||
(0, H256::repeat_byte(1)),
|
||||
LeafData::new(1),
|
||||
))));
|
||||
assert_eq!(offchain_db.get(&MMR::offchain_key(1)).map(decode_node), Some(mmr::Node::Data((
|
||||
H256::repeat_byte(2),
|
||||
(1, H256::repeat_byte(2)),
|
||||
LeafData::new(2),
|
||||
))));
|
||||
assert_eq!(offchain_db.get(&MMR::offchain_key(2)).map(decode_node), Some(mmr::Node::Hash(
|
||||
hex("bc54778fab79f586f007bd408dca2c4aa07959b27d1f2c8f4f2549d1fcfac8f8")
|
||||
hex("672c04a9cd05a644789d769daa552d35d8de7c33129f8a7cbf49e595234c4854")
|
||||
)));
|
||||
assert_eq!(offchain_db.get(&MMR::offchain_key(3)), None);
|
||||
}
|
||||
@@ -156,14 +160,15 @@ fn should_construct_larger_mmr_correctly() {
|
||||
|
||||
// then
|
||||
assert_eq!(crate::NumberOfLeaves::<DefaultInstance>::get(), 7);
|
||||
assert_eq!(crate::Nodes::<Test>::get(0),
|
||||
Some(hex("da5e6d0616e05c6a6348605a37ca33493fc1a15ad1e6a405ee05c17843fdafed")));
|
||||
assert_eq!(crate::Nodes::<Test>::get(10),
|
||||
Some(hex("af3327deed0515c8d1902c9b5cd375942d42f388f3bfe3d1cd6e1b86f9cc456c")));
|
||||
assert_eq!(
|
||||
assert_eq!((
|
||||
crate::Nodes::<Test>::get(0),
|
||||
crate::Nodes::<Test>::get(10),
|
||||
crate::RootHash::<Test>::get(),
|
||||
hex("fc4f9042bd2f73feb26f3fc42db834c5f1943fa20070ddf106c486a478a0d561")
|
||||
);
|
||||
), (
|
||||
Some(hex("4320435e8c3318562dba60116bdbcc0b82ffcecb9bb39aae3300cfda3ad0b8b0")),
|
||||
Some(hex("611c2174c6164952a66d985cfe1ec1a623794393e3acff96b136d198f37a648c")),
|
||||
hex("e45e25259f7930626431347fa4dd9aae7ac83b4966126d425ca70ab343709d2c"),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -187,38 +192,38 @@ fn should_generate_proofs_correctly() {
|
||||
|
||||
// then
|
||||
assert_eq!(proofs[0], (Compact::new((
|
||||
H256::repeat_byte(1).into(),
|
||||
(0, H256::repeat_byte(1)).into(),
|
||||
LeafData::new(1).into(),
|
||||
)), Proof {
|
||||
leaf_index: 0,
|
||||
leaf_count: 7,
|
||||
items: vec![
|
||||
hex("ff5d891b28463a3440e1b650984685efdf260e482cb3807d53c49090841e755f"),
|
||||
hex("00b0046bd2d63fcb760cf50a262448bb2bbf9a264b0b0950d8744044edf00dc3"),
|
||||
hex("16de0900b57bf359a0733674ebfbba0f494e95a8391b4bfeae850019399f3ec0"),
|
||||
hex("ad4cbc033833612ccd4626d5f023b9dfc50a35e838514dd1f3c86f8506728705"),
|
||||
hex("cb24f4614ad5b2a5430344c99545b421d9af83c46fd632d70a332200884b4d46"),
|
||||
hex("dca421199bdcc55bb773c6b6967e8d16675de69062b52285ca63685241fdf626"),
|
||||
],
|
||||
}));
|
||||
assert_eq!(proofs[4], (Compact::new((
|
||||
H256::repeat_byte(5).into(),
|
||||
(4, H256::repeat_byte(5)).into(),
|
||||
LeafData::new(5).into(),
|
||||
)), Proof {
|
||||
leaf_index: 4,
|
||||
leaf_count: 7,
|
||||
items: vec![
|
||||
hex("e53ee36ba6c068b1a6cfef7862fed5005df55615e1c9fa6eeefe08329ac4b94b"),
|
||||
hex("c09d4a008a0f1ef37860bef33ec3088ccd94268c0bfba7ff1b3c2a1075b0eb92"),
|
||||
hex("af3327deed0515c8d1902c9b5cd375942d42f388f3bfe3d1cd6e1b86f9cc456c"),
|
||||
hex("ae88a0825da50e953e7a359c55fe13c8015e48d03d301b8bdfc9193874da9252"),
|
||||
hex("8ed25570209d8f753d02df07c1884ddb36a3d9d4770e4608b188322151c657fe"),
|
||||
hex("611c2174c6164952a66d985cfe1ec1a623794393e3acff96b136d198f37a648c"),
|
||||
],
|
||||
}));
|
||||
assert_eq!(proofs[6], (Compact::new((
|
||||
H256::repeat_byte(7).into(),
|
||||
(6, H256::repeat_byte(7)).into(),
|
||||
LeafData::new(7).into(),
|
||||
)), Proof {
|
||||
leaf_index: 6,
|
||||
leaf_count: 7,
|
||||
items: vec![
|
||||
hex("e53ee36ba6c068b1a6cfef7862fed5005df55615e1c9fa6eeefe08329ac4b94b"),
|
||||
hex("dad09f50b41822fc5ecadc25b08c3a61531d4d60e962a5aa0b6998fad5c37c5e"),
|
||||
hex("ae88a0825da50e953e7a359c55fe13c8015e48d03d301b8bdfc9193874da9252"),
|
||||
hex("7e4316ae2ebf7c3b6821cb3a46ca8b7a4f9351a9b40fcf014bb0a4fd8e8f29da"),
|
||||
],
|
||||
}));
|
||||
});
|
||||
@@ -253,6 +258,30 @@ fn should_verify() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verification_should_be_stateless() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
// Start off with chain initialisation and storing indexing data off-chain
|
||||
// (MMR Leafs)
|
||||
let mut ext = new_test_ext();
|
||||
ext.execute_with(|| init_chain(7));
|
||||
ext.persist_offchain_overlay();
|
||||
|
||||
// Try to generate proof now. This requires the offchain extensions to be present
|
||||
// to retrieve full leaf data.
|
||||
register_offchain_ext(&mut ext);
|
||||
let (leaf, proof5) = ext.execute_with(|| {
|
||||
// when
|
||||
crate::Module::<Test>::generate_proof(5).unwrap()
|
||||
});
|
||||
let root = ext.execute_with(|| crate::Module::<Test>::mmr_root_hash());
|
||||
|
||||
// Verify proof without relying on any on-chain data.
|
||||
let leaf = crate::primitives::DataOrHash::Data(leaf);
|
||||
assert_eq!(crate::verify_leaf_proof::<<Test as Config>::Hashing, _>(root, leaf, proof5), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_verify_on_the_next_block_since_there_is_no_pruning_yet() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
Reference in New Issue
Block a user