pallet-mmr: fix offchain db for sync from zero (#12498)

* pallet-mmr: cosmetic improvements

* pallet-mmr: fix offchain storage for initial sync

* address review comments

* pallet-mmr: change offchain fork-resistant key to `(prefix, pos, parent_hash)`

Do this so that both canon and fork-resitant keys have the same
`(prefix, pos).encode()` prefix. Might be useful in the future if we'd
be able to to "get" offchain db entries using key prefixes as well.

Signed-off-by: acatangiu <adrian@parity.io>

Signed-off-by: acatangiu <adrian@parity.io>
This commit is contained in:
Adrian Catangiu
2022-10-17 12:09:47 +03:00
committed by GitHub
parent 37538f0429
commit 4ae0d9a8e3
4 changed files with 163 additions and 108 deletions
@@ -169,25 +169,22 @@ fn should_append_to_mmr_when_on_initialize_is_called() {
ext.persist_offchain_overlay();
let offchain_db = ext.offchain_db();
assert_eq!(
offchain_db.get(&MMR::node_offchain_key(parent_b1, 0)).map(decode_node),
Some(mmr::Node::Data(((0, H256::repeat_byte(1)), LeafData::new(1),)))
);
assert_eq!(
offchain_db.get(&MMR::node_offchain_key(parent_b2, 1)).map(decode_node),
Some(mmr::Node::Data(((1, H256::repeat_byte(2)), LeafData::new(2),)))
);
assert_eq!(
offchain_db.get(&MMR::node_offchain_key(parent_b2, 2)).map(decode_node),
Some(mmr::Node::Hash(hex(
"672c04a9cd05a644789d769daa552d35d8de7c33129f8a7cbf49e595234c4854"
)))
);
assert_eq!(offchain_db.get(&MMR::node_offchain_key(parent_b2, 3)), None);
assert_eq!(offchain_db.get(&MMR::node_canon_offchain_key(0)), None);
assert_eq!(offchain_db.get(&MMR::node_canon_offchain_key(1)), None);
assert_eq!(offchain_db.get(&MMR::node_canon_offchain_key(2)), None);
let expected = Some(mmr::Node::Data(((0, H256::repeat_byte(1)), LeafData::new(1))));
assert_eq!(offchain_db.get(&MMR::node_offchain_key(0, parent_b1)).map(decode_node), expected);
assert_eq!(offchain_db.get(&MMR::node_canon_offchain_key(0)).map(decode_node), expected);
let expected = Some(mmr::Node::Data(((1, H256::repeat_byte(2)), LeafData::new(2))));
assert_eq!(offchain_db.get(&MMR::node_offchain_key(1, parent_b2)).map(decode_node), expected);
assert_eq!(offchain_db.get(&MMR::node_canon_offchain_key(1)).map(decode_node), expected);
let expected = Some(mmr::Node::Hash(hex(
"672c04a9cd05a644789d769daa552d35d8de7c33129f8a7cbf49e595234c4854",
)));
assert_eq!(offchain_db.get(&MMR::node_offchain_key(2, parent_b2)).map(decode_node), expected);
assert_eq!(offchain_db.get(&MMR::node_canon_offchain_key(2)).map(decode_node), expected);
assert_eq!(offchain_db.get(&MMR::node_offchain_key(3, parent_b2)), None);
assert_eq!(offchain_db.get(&MMR::node_canon_offchain_key(3)), None);
}
@@ -815,16 +812,20 @@ fn should_canonicalize_offchain() {
let parent_num: BlockNumber = (block_num - 1).into();
let leaf_index = u64::from(block_num - 1);
let pos = helper::leaf_index_to_pos(leaf_index.into());
// not canon,
assert_eq!(offchain_db.get(&MMR::node_canon_offchain_key(pos)), None);
let parent_hash = <frame_system::Pallet<Test>>::block_hash(parent_num);
// but available in fork-proof storage.
// Available in offchain db under both fork-proof key and canon key.
// We'll later check it is pruned from fork-proof key.
let expected = Some(mmr::Node::Data((
(leaf_index, H256::repeat_byte(u8::try_from(block_num).unwrap())),
LeafData::new(block_num.into()),
)));
assert_eq!(
offchain_db.get(&MMR::node_offchain_key(parent_hash, pos)).map(decode_node),
Some(mmr::Node::Data((
(leaf_index, H256::repeat_byte(u8::try_from(block_num).unwrap())),
LeafData::new(block_num.into()),
)))
offchain_db.get(&MMR::node_canon_offchain_key(pos)).map(decode_node),
expected
);
assert_eq!(
offchain_db.get(&MMR::node_offchain_key(pos, parent_hash)).map(decode_node),
expected
);
}
@@ -835,12 +836,16 @@ fn should_canonicalize_offchain() {
let verify = |pos: NodeIndex, leaf_index: LeafIndex, expected: H256| {
let parent_num: BlockNumber = leaf_index.try_into().unwrap();
let parent_hash = <frame_system::Pallet<Test>>::block_hash(parent_num);
// not canon,
assert_eq!(offchain_db.get(&MMR::node_canon_offchain_key(pos)), None);
// but available in fork-proof storage.
// Available in offchain db under both fork-proof key and canon key.
// We'll later check it is pruned from fork-proof key.
let expected = Some(mmr::Node::Hash(expected));
assert_eq!(
offchain_db.get(&MMR::node_offchain_key(parent_hash, pos)).map(decode_node),
Some(mmr::Node::Hash(expected))
offchain_db.get(&MMR::node_canon_offchain_key(pos)).map(decode_node),
expected
);
assert_eq!(
offchain_db.get(&MMR::node_offchain_key(pos, parent_hash)).map(decode_node),
expected
);
};
verify(2, 1, hex("672c04a9cd05a644789d769daa552d35d8de7c33129f8a7cbf49e595234c4854"));
@@ -867,7 +872,7 @@ fn should_canonicalize_offchain() {
let parent_num: BlockNumber = (block_num - 1).into();
let parent_hash = <frame_system::Pallet<Test>>::block_hash(parent_num);
// no longer available in fork-proof storage (was pruned),
assert_eq!(offchain_db.get(&MMR::node_offchain_key(parent_hash, pos)), None);
assert_eq!(offchain_db.get(&MMR::node_offchain_key(pos, parent_hash)), None);
// but available using canon key.
assert_eq!(
offchain_db.get(&MMR::node_canon_offchain_key(pos)).map(decode_node),
@@ -886,7 +891,7 @@ fn should_canonicalize_offchain() {
let parent_num: BlockNumber = leaf_index.try_into().unwrap();
let parent_hash = <frame_system::Pallet<Test>>::block_hash(parent_num);
// no longer available in fork-proof storage (was pruned),
assert_eq!(offchain_db.get(&MMR::node_offchain_key(parent_hash, pos)), None);
assert_eq!(offchain_db.get(&MMR::node_offchain_key(pos, parent_hash)), None);
// but available using canon key.
assert_eq!(
offchain_db.get(&MMR::node_canon_offchain_key(pos)).map(decode_node),