Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generate and verify logic for AncestryProof #4430

Merged
merged 3 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bridges/primitives/beefy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
pub use binary_merkle_tree::merkle_root;
pub use pallet_beefy_mmr::BeefyEcdsaToEthereum;
pub use pallet_mmr::{
primitives::{DataOrHash as MmrDataOrHash, Proof as MmrProof},
primitives::{DataOrHash as MmrDataOrHash, LeafProof as MmrProof},
verify_leaves_proof as verify_mmr_leaves_proof,
};
pub use sp_consensus_beefy::{
Expand Down
6 changes: 3 additions & 3 deletions polkadot/node/service/src/fake_runtime_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,11 @@ sp_api::impl_runtime_apis! {
fn generate_proof(
_: Vec<BlockNumber>,
_: Option<BlockNumber>,
) -> Result<(Vec<sp_mmr_primitives::EncodableOpaqueLeaf>, sp_mmr_primitives::Proof<Hash>), sp_mmr_primitives::Error> {
) -> Result<(Vec<sp_mmr_primitives::EncodableOpaqueLeaf>, sp_mmr_primitives::LeafProof<Hash>), sp_mmr_primitives::Error> {
unimplemented!()
}

fn verify_proof(_: Vec<sp_mmr_primitives::EncodableOpaqueLeaf>, _: sp_mmr_primitives::Proof<Hash>)
fn verify_proof(_: Vec<sp_mmr_primitives::EncodableOpaqueLeaf>, _: sp_mmr_primitives::LeafProof<Hash>)
-> Result<(), sp_mmr_primitives::Error>
{
unimplemented!()
Expand All @@ -285,7 +285,7 @@ sp_api::impl_runtime_apis! {
fn verify_proof_stateless(
_: Hash,
_: Vec<sp_mmr_primitives::EncodableOpaqueLeaf>,
_: sp_mmr_primitives::Proof<Hash>
_: sp_mmr_primitives::LeafProof<Hash>
) -> Result<(), sp_mmr_primitives::Error> {
unimplemented!()
}
Expand Down
6 changes: 3 additions & 3 deletions polkadot/runtime/rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2134,7 +2134,7 @@ sp_api::impl_runtime_apis! {
fn generate_proof(
block_numbers: Vec<BlockNumber>,
best_known_block_number: Option<BlockNumber>,
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::Proof<mmr::Hash>), mmr::Error> {
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<mmr::Hash>), mmr::Error> {
Mmr::generate_proof(block_numbers, best_known_block_number).map(
|(leaves, proof)| {
(
Expand All @@ -2148,7 +2148,7 @@ sp_api::impl_runtime_apis! {
)
}

fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::Proof<mmr::Hash>)
fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::LeafProof<mmr::Hash>)
-> Result<(), mmr::Error>
{
let leaves = leaves.into_iter().map(|leaf|
Expand All @@ -2161,7 +2161,7 @@ sp_api::impl_runtime_apis! {
fn verify_proof_stateless(
root: mmr::Hash,
leaves: Vec<mmr::EncodableOpaqueLeaf>,
proof: mmr::Proof<mmr::Hash>
proof: mmr::LeafProof<mmr::Hash>
) -> Result<(), mmr::Error> {
let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect();
pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(root, nodes, proof)
Expand Down
6 changes: 3 additions & 3 deletions polkadot/runtime/test-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1044,11 +1044,11 @@ sp_api::impl_runtime_apis! {
fn generate_proof(
_block_numbers: Vec<BlockNumber>,
_best_known_block_number: Option<BlockNumber>,
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::Proof<Hash>), mmr::Error> {
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<Hash>), mmr::Error> {
Err(mmr::Error::PalletNotIncluded)
}

fn verify_proof(_leaves: Vec<mmr::EncodableOpaqueLeaf>, _proof: mmr::Proof<Hash>)
fn verify_proof(_leaves: Vec<mmr::EncodableOpaqueLeaf>, _proof: mmr::LeafProof<Hash>)
-> Result<(), mmr::Error>
{
Err(mmr::Error::PalletNotIncluded)
Expand All @@ -1057,7 +1057,7 @@ sp_api::impl_runtime_apis! {
fn verify_proof_stateless(
_root: Hash,
_leaves: Vec<mmr::EncodableOpaqueLeaf>,
_proof: mmr::Proof<Hash>
_proof: mmr::LeafProof<Hash>
) -> Result<(), mmr::Error> {
Err(mmr::Error::PalletNotIncluded)
}
Expand Down
6 changes: 3 additions & 3 deletions polkadot/runtime/westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2013,7 +2013,7 @@ sp_api::impl_runtime_apis! {
fn generate_proof(
block_numbers: Vec<BlockNumber>,
best_known_block_number: Option<BlockNumber>,
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::Proof<mmr::Hash>), mmr::Error> {
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<mmr::Hash>), mmr::Error> {
Mmr::generate_proof(block_numbers, best_known_block_number).map(
|(leaves, proof)| {
(
Expand All @@ -2027,7 +2027,7 @@ sp_api::impl_runtime_apis! {
)
}

fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::Proof<mmr::Hash>)
fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::LeafProof<mmr::Hash>)
-> Result<(), mmr::Error>
{
let leaves = leaves.into_iter().map(|leaf|
Expand All @@ -2040,7 +2040,7 @@ sp_api::impl_runtime_apis! {
fn verify_proof_stateless(
root: mmr::Hash,
leaves: Vec<mmr::EncodableOpaqueLeaf>,
proof: mmr::Proof<mmr::Hash>
proof: mmr::LeafProof<mmr::Hash>
) -> Result<(), mmr::Error> {
let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect();
pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(root, nodes, proof)
Expand Down
6 changes: 3 additions & 3 deletions substrate/bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3094,7 +3094,7 @@ impl_runtime_apis! {
fn generate_proof(
block_numbers: Vec<BlockNumber>,
best_known_block_number: Option<BlockNumber>,
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::Proof<mmr::Hash>), mmr::Error> {
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<mmr::Hash>), mmr::Error> {
Mmr::generate_proof(block_numbers, best_known_block_number).map(
|(leaves, proof)| {
(
Expand All @@ -3108,7 +3108,7 @@ impl_runtime_apis! {
)
}

fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::Proof<mmr::Hash>)
fn verify_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::LeafProof<mmr::Hash>)
-> Result<(), mmr::Error>
{
let leaves = leaves.into_iter().map(|leaf|
Expand All @@ -3121,7 +3121,7 @@ impl_runtime_apis! {
fn verify_proof_stateless(
root: mmr::Hash,
leaves: Vec<mmr::EncodableOpaqueLeaf>,
proof: mmr::Proof<mmr::Hash>
proof: mmr::LeafProof<mmr::Hash>
) -> Result<(), mmr::Error> {
let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect();
pallet_mmr::verify_leaves_proof::<mmr::Hashing, _>(root, nodes, proof)
Expand Down
16 changes: 8 additions & 8 deletions substrate/client/merkle-mountain-range/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use sp_core::{
offchain::{storage::OffchainDb, OffchainDbExt, OffchainStorage},
Bytes,
};
use sp_mmr_primitives::{Error as MmrError, Proof};
use sp_mmr_primitives::{Error as MmrError, LeafProof};
use sp_runtime::traits::{Block as BlockT, NumberFor};

pub use sp_mmr_primitives::MmrApi as MmrRuntimeApi;
Expand All @@ -52,17 +52,17 @@ pub struct LeavesProof<BlockHash> {
pub block_hash: BlockHash,
/// SCALE-encoded vector of `LeafData`.
pub leaves: Bytes,
/// SCALE-encoded proof data. See [sp_mmr_primitives::Proof].
/// SCALE-encoded proof data. See [sp_mmr_primitives::LeafProof].
pub proof: Bytes,
}

impl<BlockHash> LeavesProof<BlockHash> {
/// Create new `LeavesProof` from a given vector of `Leaf` and a
/// [sp_mmr_primitives::Proof].
/// [sp_mmr_primitives::LeafProof].
pub fn new<Leaf, MmrHash>(
block_hash: BlockHash,
leaves: Vec<Leaf>,
proof: Proof<MmrHash>,
proof: LeafProof<MmrHash>,
) -> Self
where
Leaf: Encode,
Expand Down Expand Up @@ -258,7 +258,7 @@ mod tests {
fn should_serialize_leaf_proof() {
// given
let leaf = vec![1_u8, 2, 3, 4];
let proof = Proof {
let proof = LeafProof {
leaf_indices: vec![1],
leaf_count: 9,
items: vec![H256::repeat_byte(1), H256::repeat_byte(2)],
Expand All @@ -281,7 +281,7 @@ mod tests {
// given
let leaf_a = vec![1_u8, 2, 3, 4];
let leaf_b = vec![2_u8, 2, 3, 4];
let proof = Proof {
let proof = LeafProof {
leaf_indices: vec![1, 2],
leaf_count: 9,
items: vec![H256::repeat_byte(1), H256::repeat_byte(2)],
Expand All @@ -306,7 +306,7 @@ mod tests {
block_hash: H256::repeat_byte(0),
leaves: Bytes(vec![vec![1_u8, 2, 3, 4]].encode()),
proof: Bytes(
Proof {
LeafProof {
leaf_indices: vec![1],
leaf_count: 9,
items: vec![H256::repeat_byte(1), H256::repeat_byte(2)],
Expand All @@ -333,7 +333,7 @@ mod tests {
block_hash: H256::repeat_byte(0),
leaves: Bytes(vec![vec![1_u8, 2, 3, 4], vec![2_u8, 2, 3, 4]].encode()),
proof: Bytes(
Proof {
LeafProof {
leaf_indices: vec![1, 2],
leaf_count: 9,
items: vec![H256::repeat_byte(1), H256::repeat_byte(2)],
Expand Down
6 changes: 3 additions & 3 deletions substrate/client/merkle-mountain-range/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,11 @@ sp_api::mock_impl_runtime_apis! {
&self,
_block_numbers: Vec<u64>,
_best_known_block_number: Option<u64>,
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::Proof<MmrHash>), mmr::Error> {
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::LeafProof<MmrHash>), mmr::Error> {
Err(mmr::Error::PalletNotIncluded)
}

fn verify_proof(_leaves: Vec<mmr::EncodableOpaqueLeaf>, _proof: mmr::Proof<MmrHash>)
fn verify_proof(_leaves: Vec<mmr::EncodableOpaqueLeaf>, _proof: mmr::LeafProof<MmrHash>)
-> Result<(), mmr::Error>
{
Err(mmr::Error::PalletNotIncluded)
Expand All @@ -322,7 +322,7 @@ sp_api::mock_impl_runtime_apis! {
fn verify_proof_stateless(
_root: MmrHash,
_leaves: Vec<mmr::EncodableOpaqueLeaf>,
_proof: mmr::Proof<MmrHash>
_proof: mmr::LeafProof<MmrHash>
) -> Result<(), mmr::Error> {
Err(mmr::Error::PalletNotIncluded)
}
Expand Down
48 changes: 38 additions & 10 deletions substrate/frame/merkle-mountain-range/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,15 +260,15 @@ pub mod pallet {

/// Stateless MMR proof verification for batch of leaves.
///
/// This function can be used to verify received MMR [primitives::Proof] (`proof`)
/// This function can be used to verify received MMR [primitives::LeafProof] (`proof`)
/// for given leaves set (`leaves`) against a known MMR root hash (`root`).
/// Note, the leaves should be sorted such that corresponding leaves and leaf indices have the
/// same position in both the `leaves` vector and the `leaf_indices` vector contained in the
/// [primitives::Proof].
/// [primitives::LeafProof].
pub fn verify_leaves_proof<H, L>(
root: H::Output,
leaves: Vec<mmr::Node<H, L>>,
proof: primitives::Proof<H::Output>,
proof: primitives::LeafProof<H::Output>,
) -> Result<(), primitives::Error>
where
H: traits::Hash,
Expand Down Expand Up @@ -342,7 +342,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
pub fn generate_proof(
block_numbers: Vec<BlockNumberFor<T>>,
best_known_block_number: Option<BlockNumberFor<T>>,
) -> Result<(Vec<LeafOf<T, I>>, primitives::Proof<HashOf<T, I>>), primitives::Error> {
) -> Result<(Vec<LeafOf<T, I>>, primitives::LeafProof<HashOf<T, I>>), primitives::Error> {
// check whether best_known_block_number provided, else use current best block
let best_known_block_number =
best_known_block_number.unwrap_or_else(|| <frame_system::Pallet<T>>::block_number());
Expand All @@ -362,11 +362,6 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
mmr.generate_proof(leaf_indices)
}

/// Return the on-chain MMR root hash.
pub fn mmr_root() -> HashOf<T, I> {
RootHash::<T, I>::get()
}

/// Verify MMR proof for given `leaves`.
///
/// This method is safe to use within the runtime code.
Expand All @@ -375,7 +370,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// or the proof is invalid.
pub fn verify_leaves(
leaves: Vec<LeafOf<T, I>>,
proof: primitives::Proof<HashOf<T, I>>,
proof: primitives::LeafProof<HashOf<T, I>>,
) -> Result<(), primitives::Error> {
if proof.leaf_count > NumberOfLeaves::<T, I>::get() ||
proof.leaf_count == 0 ||
Expand All @@ -393,4 +388,37 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
Err(primitives::Error::Verify.log_debug("The proof is incorrect."))
}
}

pub fn generate_ancestry_proof(
prev_block_number: BlockNumberFor<T>,
best_known_block_number: Option<BlockNumberFor<T>>,
) -> Result<primitives::AncestryProof<HashOf<T, I>>, Error> {
// check whether best_known_block_number provided, else use current best block
let best_known_block_number =
best_known_block_number.unwrap_or_else(|| <frame_system::Pallet<T>>::block_number());

let leaf_count = Self::block_num_to_leaf_index(best_known_block_number)?.saturating_add(1);
let prev_leaf_count = Self::block_num_to_leaf_index(prev_block_number)?.saturating_add(1);

let mmr: ModuleMmr<mmr::storage::OffchainStorage, T, I> = mmr::Mmr::new(leaf_count);
mmr.generate_ancestry_proof(prev_leaf_count)
}

pub fn verify_ancestry_proof(
ancestry_proof: primitives::AncestryProof<HashOf<T, I>>,
) -> Result<(), Error> {
let mmr: ModuleMmr<mmr::storage::OffchainStorage, T, I> =
mmr::Mmr::new(ancestry_proof.leaf_count);
let is_valid = mmr.verify_ancestry_proof(ancestry_proof)?;
if is_valid {
Ok(())
} else {
Err(Error::Verify.log_debug("The ancestry proof is incorrect."))
}
}

/// Return the on-chain MMR root hash.
pub fn mmr_root() -> HashOf<T, I> {
RootHash::<T, I>::get()
}
}
Loading
Loading