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

[TASK] Add rpc api for is_known_root method #325

Closed
salman01zp opened this issue May 4, 2023 · 1 comment · Fixed by #327
Closed

[TASK] Add rpc api for is_known_root method #325

salman01zp opened this issue May 4, 2023 · 1 comment · Fixed by #327

Comments

@salman01zp
Copy link
Contributor

salman01zp commented May 4, 2023

Summary

Add RPC api to validate if the given root is a known root, this will be used by the relayer to validate leaves before caching.

https://github.com/webb-tools/protocol-substrate/blob/main/pallets/mt/src/lib.rs#L492-#L509

#[method(name = "mt_isKnownRoot")]
fn is_known_root(
	&self,
	tree_id: u32,
	target_root: Element,
	at: Option<BlockHash>,
) -> RpcResult<bool>;

@shekohex
Copy link
Collaborator

shekohex commented May 4, 2023

This Like a two part operation here.

Runtime API:
So for you to do this, you need to declare it for the runtime API first like here:

sp_api::decl_runtime_apis! {
pub trait MerkleTreeApi<E: ElementTrait> {
/// Get the leaf of tree id at a given index.
fn get_leaf(tree_id: u32, index: u32) -> Option<E>;
}
}

And then you will need to implement that Runtime API in the */runtime/lib.rs like so:

impl pallet_mt_rpc_runtime_api::MerkleTreeApi<Block, Element> for Runtime {
fn get_leaf(tree_id: u32, index: u32) -> Option<Element> {
let v = MerkleTreeBn254::leaves(tree_id, index);
if v == Element::default() {
None
} else {
Some(v)
}
}
}

RPC:
And here for the RPC

/// Merkle RPC methods.
#[rpc(client, server)]
pub trait MerkleTreeRpcApi<BlockHash, Element> {
/// Get The MerkleTree leaves.
///
/// This method calls into a runtime with `Merkle` pallet included and
/// attempts to get the merkletree leaves.
/// Optionally, a block hash at which the runtime should be queried can be
/// specified.
///
/// Returns the (full) a Vec<[u8; 32]> of the leaves.
#[method(name = "mt_getLeaves")]
fn get_leaves(
&self,
tree_id: u32,
from: usize,
to: usize,
at: Option<BlockHash>,
) -> RpcResult<Vec<Element>>;
}

Then you just implement it inside the RPC

This an example implementation of the get_leaves

fn get_leaves(
&self,
tree_id: u32,
from: usize,
to: usize,
at: Option<<Block as BlockT>::Hash>,
) -> RpcResult<Vec<Element>> {
self.deny_unsafe.check_if_safe()?;
let api = self.client.runtime_api();
let at = at.unwrap_or_else(|| self.client.info().best_hash);
if to - from >= 512 {
return Err(error::Error::TooManyLeavesRequested.into())
}
let leaves = (from..to)
.into_iter()
.flat_map(|i| api.get_leaf(at, tree_id, i as u32)) // Result<Option<Element>>
.flatten() // Element
.collect();
Ok(leaves)

And that's it actually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants