Crates.io | merkle-tree-rs |
lib.rs | merkle-tree-rs |
version | 0.1.0 |
source | src |
created_at | 2022-11-17 16:39:47.406101 |
updated_at | 2022-11-17 16:39:47.406101 |
description | A Rust library to generate merkle trees and merkle proofs. |
homepage | |
repository | https://github.com/literallymarvellous/merkle-tree-rs |
max_upload_size | |
id | 717355 |
size | 41,750 |
merkle-tree-rs
A Rust library to generate merkle trees and merkle proofs.
Well suited for airdrops and similar mechanisms in combination with OpenZeppelin Contracts MerkleProof
utilities.
Add merkle-tree-rs to your repository, also serde and serde_json for json.
[dependencies]
merkle-tree-rs = "0.1.0"
serde = "1.0.147"
serde_json = "1.0"
use merkle_tree_rs::standard::StandardMerkleTree;
use std::fs;
let values = vec![
vec![
"0x1111111111111111111111111111111111111111".to_string(),
"5000000000000000000".to_string(),
],
vec![
"0x2222222222222222222222222222222222222222".to_string(),
"2500000000000000000".to_string(),
],
];
let tree = StandardMerkleTree::of(values, &["address".to_string(), "uint256".to_string()]);
let root = tree.root();
println!("Merkle root: {}", root);
let tree_json = serde_json::to_string(&tree.dump()).unwrap();
fs::write("tree.json", tree_json).unwrap();
Assume we're looking to generate a proof for the entry that corresponds to address 0x11...11
.
use merkle_tree_rs::standard::StandardMerkleTree;
use std::fs;
let tree_json = fs::read_to_string("tree.json").unwrap();
let tree_data: StandardMerkleTreeData = serde_json::from_str(&tree_json).unwrap();
let tree = StandardMerkleTree::load(tree_data);
for (i, v) in tree.clone().enumerate() {
if v[0] == "0x1111111111111111111111111111111111111111" {
let proof = tree.get_proof(LeafType::Number(i));
println!("Value : {:?}", v);
println!("Proof : {:?}", proof);
}
}
In practice this might be done in a frontend application prior to submitting the proof on-chain, with the address looked up being that of the connected wallet.
See MerkleProof
for documentation on how to validate the proof in Solidity.
This library works on "standard" merkle trees designed for Ethereum smart contracts. We have defined them with a few characteristics that make them secure and good for on-chain verification.
From the last three points we get that the hash of a leaf in the tree with value [addr, amount]
can be computed in Solidity as follows:
bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(addr, amount))));
This is an opinionated design that we believe will offer the best out of the box experience for most users. We may introduce options for customization in the future based on user requests.
StandardMerkleTree
use merkle_tree_rs::standard::StandardMerkleTree,
StandardMerkleTree.of
Types currently supported for encoding includes address, uint, uint256 and string.
let values = vec![
vec![
"0x1111111111111111111111111111111111111111".to_string(),
"5000000000000000000".to_string(),
],
vec![
"0x2222222222222222222222222222222222222222".to_string(),
"2500000000000000000".to_string(),
],
];
let encoding = ["address".to_string(), "uint256".to_string()];
let tree = StandardMerkleTree::of(values, &encoding);
Creates a standard merkle tree out of an array of the elements in the tree, along with their types for ABI encoding.
Note Consider reading the array of elements from a CSV file for easy interoperability with spreadsheets or other data processing pipelines.
tree.root
println!("{}", tree.root());
The root of the tree is a commitment on the values of the tree. It can be published (e.g., in a smart contract) to later prove that its values are part of the tree.
tree.dump
let tree_json = serde_json::to_string(&tree.dump()).unwrap();
fs::write("tree.json", tree_json).unwrap();
Returns a description of the merkle tree for distribution. It contains all the necessary information to reproduce the tree, find the relevant leaves, and generate proofs. You should distribute this to users in a web application or command line interface so they can generate proofs for their leaves of interest.
StandardMerkleTree.load
let tree_json = fs::read_to_string("tree.json").unwrap();
let tree_data: StandardMerkleTreeData = serde_json::from_str(&tree_json).unwrap();
let tree = StandardMerkleTree::load(tree_data);
Loads the tree from a description previously returned by dump
.
tree.getProof
let proof = tree.get_proof(LeafType::Number(i));
Returns a proof for the i
th value in the tree. Indices refer to the position of the values in the array from which the tree was constructed.
It is wrapped in a LeafType
enum of Number(usize)
for indices and LeafBytes(Vec<string>)
for values. Using value is less efficient cause it will fail if the value is not found in the tree.
let proof = tree.getProof(LeafType::LeafBytes([alice, "100"]));
tree.getMultiProof
let multi_proof = tree.getMultiProof([LeafType::Number(i0), LeafType::Number(i1), ...]);
Returns a multiproof strcut containing {proof, prooflags, leaves} for the values at indices i0, i1, ...
. Indices refer to the position of the values in the array from which the tree was constructed.
The multiproof returned contains an array with the leaves that are being proven. This array may be in a different order than that given by i0, i1, ...
! The order returned is significant, as it is that in which the leaves must be submitted for verification (e.g., in a smart contract).
Also accepts values instead of indices, but this will be less efficient. It will fail if any of the values is not found in the tree.
for (i, v) in tree.clone().enumerate {
console.log("value: {:?}", v);
console.log("proof: {:?}", tree.getProof(LeafType::Number(i)));
}
Lists the values in the tree along with their indices, which can be used to obtain proofs.
tree.render
println!("{:?}", tree.render());
Returns a visual representation of the tree that can be useful for debugging.
tree.leafHash
let leaf = tree.leafHash(["alice".to_string(), "100".to_string()]);
Returns the leaf hash of the value, as defined in Standard Merkle Trees.
Corresponds to the following expression in Solidity:
bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(alice, 100))));
Attributions