Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 5 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
39 changes: 30 additions & 9 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2010,10 +2010,7 @@ impl_runtime_apis! {
}
}

impl pallet_mmr::primitives::MmrApi<
Block,
mmr::Hash,
> for Runtime {
impl pallet_mmr::primitives::MmrApi<Block, mmr::Hash> for Runtime {
fn generate_proof(leaf_index: pallet_mmr::primitives::LeafIndex)
-> Result<(mmr::EncodableOpaqueLeaf, mmr::Proof<mmr::Hash>), mmr::Error>
{
Expand Down Expand Up @@ -2048,11 +2045,35 @@ impl_runtime_apis! {
Ok(Mmr::mmr_root())
}

fn generate_batch_proof(leaf_indices: Vec<pallet_mmr::primitives::LeafIndex>)
-> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::BatchProof<mmr::Hash>), mmr::Error>
{
Mmr::generate_batch_proof(leaf_indices)
.map(|(leaves, proof)| (leaves.into_iter().map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)).collect(), proof))
fn generate_batch_proof(
leaf_indices: Vec<pallet_mmr::primitives::LeafIndex>,
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::BatchProof<mmr::Hash>), mmr::Error> {
Mmr::generate_batch_proof(leaf_indices).map(|(leaves, proof)| {
(
leaves
.into_iter()
.map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf))
.collect(),
proof,
)
})
}

fn generate_historical_batch_proof(
leaf_indices: Vec<pallet_mmr::primitives::LeafIndex>,
leaves_count: pallet_mmr::primitives::LeafIndex,
) -> Result<(Vec<mmr::EncodableOpaqueLeaf>, mmr::BatchProof<mmr::Hash>), mmr::Error> {
Mmr::generate_historical_batch_proof(leaf_indices, leaves_count).map(
|(leaves, proof)| {
(
leaves
.into_iter()
.map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf))
.collect(),
proof,
)
},
)
}

fn verify_batch_proof(leaves: Vec<mmr::EncodableOpaqueLeaf>, proof: mmr::BatchProof<mmr::Hash>)
Expand Down
7 changes: 7 additions & 0 deletions client/beefy/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@ macro_rules! create_test_api {
unimplemented!()
}

fn generate_historical_batch_proof(
_leaf_indices: Vec<LeafIndex>,
_leaves_count: LeafIndex
) -> Result<(Vec<EncodableOpaqueLeaf>, BatchProof<MmrRootHash>), MmrError> {
unimplemented!()
}

fn verify_batch_proof(_leaves: Vec<EncodableOpaqueLeaf>, _proof: BatchProof<MmrRootHash>) -> Result<(), MmrError> {
unimplemented!()
}
Expand Down
49 changes: 49 additions & 0 deletions frame/merkle-mountain-range/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,31 @@ pub trait MmrApi<BlockHash> {
leaf_indices: Vec<LeafIndex>,
at: Option<BlockHash>,
) -> RpcResult<LeafBatchProof<BlockHash>>;

/// Generate a MMR proof for the given `leaf_indices` of the MMR that had `leaves_count` leaves.
///
/// This method calls into a runtime with MMR pallet included and attempts to generate
/// a MMR proof for the set of leaves at the given `leaf_indices` with MMR fixed to the state
/// with exactly `leaves_count` leaves. `leaves_count` must be larger than all `leaf_indices`
/// for the function to succeed.
///
/// Optionally, a block hash at which the runtime should be queried can be specified.
/// Note that specifying the block hash isn't super-useful here, unless you're generating
/// proof using non-finalized blocks where there are several competing forks. That's because
/// MMR state will be fixed to the state with `leaves_count`, which already points to some
/// historical block.
///
/// Returns the leaves and a proof for these leaves (compact encoding, i.e. hash of
/// the leaves). Both parameters are SCALE-encoded.
/// The order of entries in the `leaves` field of the returned struct
/// is the same as the order of the entries in `leaf_indices` supplied
#[method(name = "mmr_generateHistoricalBatchProof")]
fn generate_historical_batch_proof(
&self,
leaf_indices: Vec<LeafIndex>,
leaves_count: LeafIndex,
at: Option<BlockHash>,
) -> RpcResult<LeafBatchProof<BlockHash>>;
}

/// MMR RPC methods.
Expand Down Expand Up @@ -192,6 +217,30 @@ where

Ok(LeafBatchProof::new(block_hash, leaves, proof))
}

fn generate_historical_batch_proof(
&self,
leaf_indices: Vec<LeafIndex>,
leaves_count: LeafIndex,
at: Option<<Block as BlockT>::Hash>,
) -> RpcResult<LeafBatchProof<<Block as BlockT>::Hash>> {
let api = self.client.runtime_api();
let block_hash = at.unwrap_or_else(||
// If the block hash is not supplied assume the best block.
self.client.info().best_hash);

let (leaves, proof) = api
.generate_historical_batch_proof_with_context(
&BlockId::hash(block_hash),
sp_core::ExecutionContext::OffchainCall(None),
leaf_indices,
leaves_count,
)
.map_err(runtime_error_into_rpc_error)?
.map_err(mmr_error_into_rpc_error)?;

Ok(LeafBatchProof::new(block_hash, leaves, proof))
}
}

/// Converts a mmr-specific error into a [`CallError`].
Expand Down
22 changes: 21 additions & 1 deletion frame/merkle-mountain-range/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,27 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
(Vec<LeafOf<T, I>>, primitives::BatchProof<<T as Config<I>>::Hash>),
primitives::Error,
> {
let mmr: ModuleMmr<mmr::storage::OffchainStorage, T, I> = mmr::Mmr::new(Self::mmr_leaves());
Self::generate_historical_batch_proof(leaf_indices, Self::mmr_leaves())
}

/// Generate a MMR proof for the given `leaf_indices` for the MMR of `leaves_count` size.
///
/// Note this method can only be used from an off-chain context
/// (Offchain Worker or Runtime API call), since it requires
/// all the leaves to be present.
/// It may return an error or panic if used incorrectly.
pub fn generate_historical_batch_proof(
leaf_indices: Vec<LeafIndex>,
leaves_count: LeafIndex,
) -> Result<
(Vec<LeafOf<T, I>>, primitives::BatchProof<<T as Config<I>>::Hash>),
primitives::Error,
> {
if leaves_count > Self::mmr_leaves() {
return Err(Error::InvalidLeavesCount)
}

let mmr: ModuleMmr<mmr::storage::OffchainStorage, T, I> = mmr::Mmr::new(leaves_count);
mmr.generate_batch_proof(leaf_indices)
}

Expand Down
Loading