Skip to content

Commit f4b73bd

Browse files
authored
Add generate and verify logic for AncestryProof (#4430)
Extracting the logic for generating and verifying ancestry proofs from this PR: #1903 with small adjustments @Lederstrumpf I added you as a co-author to each commit. Please let me know if you want me to also associate an e-mail address with your name
1 parent 805d54d commit f4b73bd

File tree

15 files changed

+251
-105
lines changed

15 files changed

+251
-105
lines changed

Cargo.lock

Lines changed: 11 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bridges/primitives/beefy/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
pub use binary_merkle_tree::merkle_root;
2323
pub use pallet_beefy_mmr::BeefyEcdsaToEthereum;
2424
pub use pallet_mmr::{
25-
primitives::{DataOrHash as MmrDataOrHash, Proof as MmrProof},
25+
primitives::{DataOrHash as MmrDataOrHash, LeafProof as MmrProof},
2626
verify_leaves_proof as verify_mmr_leaves_proof,
2727
};
2828
pub use sp_consensus_beefy::{

polkadot/node/service/src/fake_runtime_api.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,11 +272,11 @@ sp_api::impl_runtime_apis! {
272272
fn generate_proof(
273273
_: Vec<BlockNumber>,
274274
_: Option<BlockNumber>,
275-
) -> Result<(Vec<sp_mmr_primitives::EncodableOpaqueLeaf>, sp_mmr_primitives::Proof<Hash>), sp_mmr_primitives::Error> {
275+
) -> Result<(Vec<sp_mmr_primitives::EncodableOpaqueLeaf>, sp_mmr_primitives::LeafProof<Hash>), sp_mmr_primitives::Error> {
276276
unimplemented!()
277277
}
278278

279-
fn verify_proof(_: Vec<sp_mmr_primitives::EncodableOpaqueLeaf>, _: sp_mmr_primitives::Proof<Hash>)
279+
fn verify_proof(_: Vec<sp_mmr_primitives::EncodableOpaqueLeaf>, _: sp_mmr_primitives::LeafProof<Hash>)
280280
-> Result<(), sp_mmr_primitives::Error>
281281
{
282282
unimplemented!()
@@ -285,7 +285,7 @@ sp_api::impl_runtime_apis! {
285285
fn verify_proof_stateless(
286286
_: Hash,
287287
_: Vec<sp_mmr_primitives::EncodableOpaqueLeaf>,
288-
_: sp_mmr_primitives::Proof<Hash>
288+
_: sp_mmr_primitives::LeafProof<Hash>
289289
) -> Result<(), sp_mmr_primitives::Error> {
290290
unimplemented!()
291291
}

polkadot/runtime/rococo/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2134,7 +2134,7 @@ sp_api::impl_runtime_apis! {
21342134
fn generate_proof(
21352135
block_numbers: Vec<BlockNumber>,
21362136
best_known_block_number: Option<BlockNumber>,
2137-
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::Proof<mmr::Hash>), mmr::Error> {
2137+
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<mmr::Hash>), mmr::Error> {
21382138
Mmr::generate_proof(block_numbers, best_known_block_number).map(
21392139
|(leaves, proof)| {
21402140
(
@@ -2148,7 +2148,7 @@ sp_api::impl_runtime_apis! {
21482148
)
21492149
}
21502150

2151-
fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::Proof<mmr::Hash>)
2151+
fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::LeafProof<mmr::Hash>)
21522152
-> Result<(), mmr::Error>
21532153
{
21542154
let leaves = leaves.into_iter().map(|leaf|
@@ -2161,7 +2161,7 @@ sp_api::impl_runtime_apis! {
21612161
fn verify_proof_stateless(
21622162
root: mmr::Hash,
21632163
leaves: Vec<mmr::EncodableOpaqueLeaf>,
2164-
proof: mmr::Proof<mmr::Hash>
2164+
proof: mmr::LeafProof<mmr::Hash>
21652165
) -> Result<(), mmr::Error> {
21662166
let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect();
21672167
pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(root, nodes, proof)

polkadot/runtime/test-runtime/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,11 +1044,11 @@ sp_api::impl_runtime_apis! {
10441044
fn generate_proof(
10451045
_block_numbers: Vec<BlockNumber>,
10461046
_best_known_block_number: Option<BlockNumber>,
1047-
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::Proof<Hash>), mmr::Error> {
1047+
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<Hash>), mmr::Error> {
10481048
Err(mmr::Error::PalletNotIncluded)
10491049
}
10501050

1051-
fn verify_proof(_leaves: Vec<mmr::EncodableOpaqueLeaf>, _proof: mmr::Proof<Hash>)
1051+
fn verify_proof(_leaves: Vec<mmr::EncodableOpaqueLeaf>, _proof: mmr::LeafProof<Hash>)
10521052
-> Result<(), mmr::Error>
10531053
{
10541054
Err(mmr::Error::PalletNotIncluded)
@@ -1057,7 +1057,7 @@ sp_api::impl_runtime_apis! {
10571057
fn verify_proof_stateless(
10581058
_root: Hash,
10591059
_leaves: Vec<mmr::EncodableOpaqueLeaf>,
1060-
_proof: mmr::Proof<Hash>
1060+
_proof: mmr::LeafProof<Hash>
10611061
) -> Result<(), mmr::Error> {
10621062
Err(mmr::Error::PalletNotIncluded)
10631063
}

polkadot/runtime/westend/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,7 +2013,7 @@ sp_api::impl_runtime_apis! {
20132013
fn generate_proof(
20142014
block_numbers: Vec<BlockNumber>,
20152015
best_known_block_number: Option<BlockNumber>,
2016-
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::Proof<mmr::Hash>), mmr::Error> {
2016+
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<mmr::Hash>), mmr::Error> {
20172017
Mmr::generate_proof(block_numbers, best_known_block_number).map(
20182018
|(leaves, proof)| {
20192019
(
@@ -2027,7 +2027,7 @@ sp_api::impl_runtime_apis! {
20272027
)
20282028
}
20292029

2030-
fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::Proof<mmr::Hash>)
2030+
fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::LeafProof<mmr::Hash>)
20312031
-> Result<(), mmr::Error>
20322032
{
20332033
let leaves = leaves.into_iter().map(|leaf|
@@ -2040,7 +2040,7 @@ sp_api::impl_runtime_apis! {
20402040
fn verify_proof_stateless(
20412041
root: mmr::Hash,
20422042
leaves: Vec<mmr::EncodableOpaqueLeaf>,
2043-
proof: mmr::Proof<mmr::Hash>
2043+
proof: mmr::LeafProof<mmr::Hash>
20442044
) -> Result<(), mmr::Error> {
20452045
let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect();
20462046
pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(root, nodes, proof)

substrate/bin/node/runtime/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3094,7 +3094,7 @@ impl_runtime_apis! {
30943094
fn generate_proof(
30953095
block_numbers: Vec<BlockNumber>,
30963096
best_known_block_number: Option<BlockNumber>,
3097-
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::Proof<mmr::Hash>), mmr::Error> {
3097+
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<mmr::Hash>), mmr::Error> {
30983098
Mmr::generate_proof(block_numbers, best_known_block_number).map(
30993099
|(leaves, proof)| {
31003100
(
@@ -3108,7 +3108,7 @@ impl_runtime_apis! {
31083108
)
31093109
}
31103110

3111-
fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::Proof<mmr::Hash>)
3111+
fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::LeafProof<mmr::Hash>)
31123112
-> Result<(), mmr::Error>
31133113
{
31143114
let leaves = leaves.into_iter().map(|leaf|
@@ -3121,7 +3121,7 @@ impl_runtime_apis! {
31213121
fn verify_proof_stateless(
31223122
root: mmr::Hash,
31233123
leaves: Vec<mmr::EncodableOpaqueLeaf>,
3124-
proof: mmr::Proof<mmr::Hash>
3124+
proof: mmr::LeafProof<mmr::Hash>
31253125
) -> Result<(), mmr::Error> {
31263126
let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect();
31273127
pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(root, nodes, proof)

substrate/client/merkle-mountain-range/rpc/src/lib.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use sp_core::{
3636
offchain::{storage::OffchainDb, OffchainDbExt, OffchainStorage},
3737
Bytes,
3838
};
39-
use sp_mmr_primitives::{Error as MmrError, Proof};
39+
use sp_mmr_primitives::{Error as MmrError, LeafProof};
4040
use sp_runtime::traits::{Block as BlockT, NumberFor};
4141

4242
pub use sp_mmr_primitives::MmrApi as MmrRuntimeApi;
@@ -52,17 +52,17 @@ pub struct LeavesProof<BlockHash> {
5252
pub block_hash: BlockHash,
5353
/// SCALE-encoded vector of `LeafData`.
5454
pub leaves: Bytes,
55-
/// SCALE-encoded proof data. See [sp_mmr_primitives::Proof].
55+
/// SCALE-encoded proof data. See [sp_mmr_primitives::LeafProof].
5656
pub proof: Bytes,
5757
}
5858

5959
impl<BlockHash> LeavesProof<BlockHash> {
6060
/// Create new `LeavesProof` from a given vector of `Leaf` and a
61-
/// [sp_mmr_primitives::Proof].
61+
/// [sp_mmr_primitives::LeafProof].
6262
pub fn new<Leaf, MmrHash>(
6363
block_hash: BlockHash,
6464
leaves: Vec<Leaf>,
65-
proof: Proof<MmrHash>,
65+
proof: LeafProof<MmrHash>,
6666
) -> Self
6767
where
6868
Leaf: Encode,
@@ -258,7 +258,7 @@ mod tests {
258258
fn should_serialize_leaf_proof() {
259259
// given
260260
let leaf = vec![1_u8, 2, 3, 4];
261-
let proof = Proof {
261+
let proof = LeafProof {
262262
leaf_indices: vec![1],
263263
leaf_count: 9,
264264
items: vec![H256::repeat_byte(1), H256::repeat_byte(2)],
@@ -281,7 +281,7 @@ mod tests {
281281
// given
282282
let leaf_a = vec![1_u8, 2, 3, 4];
283283
let leaf_b = vec![2_u8, 2, 3, 4];
284-
let proof = Proof {
284+
let proof = LeafProof {
285285
leaf_indices: vec![1, 2],
286286
leaf_count: 9,
287287
items: vec![H256::repeat_byte(1), H256::repeat_byte(2)],
@@ -306,7 +306,7 @@ mod tests {
306306
block_hash: H256::repeat_byte(0),
307307
leaves: Bytes(vec![vec![1_u8, 2, 3, 4]].encode()),
308308
proof: Bytes(
309-
Proof {
309+
LeafProof {
310310
leaf_indices: vec![1],
311311
leaf_count: 9,
312312
items: vec![H256::repeat_byte(1), H256::repeat_byte(2)],
@@ -333,7 +333,7 @@ mod tests {
333333
block_hash: H256::repeat_byte(0),
334334
leaves: Bytes(vec![vec![1_u8, 2, 3, 4], vec![2_u8, 2, 3, 4]].encode()),
335335
proof: Bytes(
336-
Proof {
336+
LeafProof {
337337
leaf_indices: vec![1, 2],
338338
leaf_count: 9,
339339
items: vec![H256::repeat_byte(1), H256::repeat_byte(2)],

substrate/client/merkle-mountain-range/src/test_utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,11 @@ sp_api::mock_impl_runtime_apis! {
309309
&self,
310310
_block_numbers: Vec<u64>,
311311
_best_known_block_number: Option<u64>,
312-
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::Proof<MmrHash>), mmr::Error> {
312+
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<MmrHash>), mmr::Error> {
313313
Err(mmr::Error::PalletNotIncluded)
314314
}
315315

316-
fn verify_proof(_leaves: Vec<mmr::EncodableOpaqueLeaf>, _proof: mmr::Proof<MmrHash>)
316+
fn verify_proof(_leaves: Vec<mmr::EncodableOpaqueLeaf>, _proof: mmr::LeafProof<MmrHash>)
317317
-> Result<(), mmr::Error>
318318
{
319319
Err(mmr::Error::PalletNotIncluded)
@@ -322,7 +322,7 @@ sp_api::mock_impl_runtime_apis! {
322322
fn verify_proof_stateless(
323323
_root: MmrHash,
324324
_leaves: Vec<mmr::EncodableOpaqueLeaf>,
325-
_proof: mmr::Proof<MmrHash>
325+
_proof: mmr::LeafProof<MmrHash>
326326
) -> Result<(), mmr::Error> {
327327
Err(mmr::Error::PalletNotIncluded)
328328
}

substrate/frame/merkle-mountain-range/src/lib.rs

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -260,15 +260,15 @@ pub mod pallet {
260260

261261
/// Stateless MMR proof verification for batch of leaves.
262262
///
263-
/// This function can be used to verify received MMR [primitives::Proof] (`proof`)
263+
/// This function can be used to verify received MMR [primitives::LeafProof] (`proof`)
264264
/// for given leaves set (`leaves`) against a known MMR root hash (`root`).
265265
/// Note, the leaves should be sorted such that corresponding leaves and leaf indices have the
266266
/// same position in both the `leaves` vector and the `leaf_indices` vector contained in the
267-
/// [primitives::Proof].
267+
/// [primitives::LeafProof].
268268
pub fn verify_leaves_proof<H, L>(
269269
root: H::Output,
270270
leaves: Vec<mmr::Node<H, L>>,
271-
proof: primitives::Proof<H::Output>,
271+
proof: primitives::LeafProof<H::Output>,
272272
) -> Result<(), primitives::Error>
273273
where
274274
H: traits::Hash,
@@ -342,7 +342,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
342342
pub fn generate_proof(
343343
block_numbers: Vec<BlockNumberFor<T>>,
344344
best_known_block_number: Option<BlockNumberFor<T>>,
345-
) -> Result<(Vec<LeafOf<T, I>>, primitives::Proof<HashOf<T, I>>), primitives::Error> {
345+
) -> Result<(Vec<LeafOf<T, I>>, primitives::LeafProof<HashOf<T, I>>), primitives::Error> {
346346
// check whether best_known_block_number provided, else use current best block
347347
let best_known_block_number =
348348
best_known_block_number.unwrap_or_else(|| <frame_system::Pallet<T>>::block_number());
@@ -362,11 +362,6 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
362362
mmr.generate_proof(leaf_indices)
363363
}
364364

365-
/// Return the on-chain MMR root hash.
366-
pub fn mmr_root() -> HashOf<T, I> {
367-
RootHash::<T, I>::get()
368-
}
369-
370365
/// Verify MMR proof for given `leaves`.
371366
///
372367
/// This method is safe to use within the runtime code.
@@ -375,7 +370,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
375370
/// or the proof is invalid.
376371
pub fn verify_leaves(
377372
leaves: Vec<LeafOf<T, I>>,
378-
proof: primitives::Proof<HashOf<T, I>>,
373+
proof: primitives::LeafProof<HashOf<T, I>>,
379374
) -> Result<(), primitives::Error> {
380375
if proof.leaf_count > NumberOfLeaves::<T, I>::get() ||
381376
proof.leaf_count == 0 ||
@@ -393,4 +388,37 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
393388
Err(primitives::Error::Verify.log_debug("The proof is incorrect."))
394389
}
395390
}
391+
392+
pub fn generate_ancestry_proof(
393+
prev_block_number: BlockNumberFor<T>,
394+
best_known_block_number: Option<BlockNumberFor<T>>,
395+
) -> Result<primitives::AncestryProof<HashOf<T, I>>, Error> {
396+
// check whether best_known_block_number provided, else use current best block
397+
let best_known_block_number =
398+
best_known_block_number.unwrap_or_else(|| <frame_system::Pallet<T>>::block_number());
399+
400+
let leaf_count = Self::block_num_to_leaf_index(best_known_block_number)?.saturating_add(1);
401+
let prev_leaf_count = Self::block_num_to_leaf_index(prev_block_number)?.saturating_add(1);
402+
403+
let mmr: ModuleMmr<mmr::storage::OffchainStorage, T, I> = mmr::Mmr::new(leaf_count);
404+
mmr.generate_ancestry_proof(prev_leaf_count)
405+
}
406+
407+
pub fn verify_ancestry_proof(
408+
ancestry_proof: primitives::AncestryProof<HashOf<T, I>>,
409+
) -> Result<(), Error> {
410+
let mmr: ModuleMmr<mmr::storage::OffchainStorage, T, I> =
411+
mmr::Mmr::new(ancestry_proof.leaf_count);
412+
let is_valid = mmr.verify_ancestry_proof(ancestry_proof)?;
413+
if is_valid {
414+
Ok(())
415+
} else {
416+
Err(Error::Verify.log_debug("The ancestry proof is incorrect."))
417+
}
418+
}
419+
420+
/// Return the on-chain MMR root hash.
421+
pub fn mmr_root() -> HashOf<T, I> {
422+
RootHash::<T, I>::get()
423+
}
396424
}

0 commit comments

Comments
 (0)