Skip to content

Commit

Permalink
Bump Merkle Library to use fuel-merkle v0.49 (#243)
Browse files Browse the repository at this point in the history
## Type of change

<!--Delete points that do not apply-->

- Improvement (refactoring, restructuring repository, cleaning tech
debt, ...)

## Changes

The following changes have been made:

- Updates the Merkle Library to use the `fuel-merkle` crate v0.49
- Updates the Merkle Library examples to use the `fuel-merkle` crate
v0.49

## Notes

- `leaf_sum` is not exposed in the `fuel-merkle` crate so it needed to
be copied

## Related Issues

<!--Delete everything after the "#" symbol and replace it with a number.
No spaces between hash and number-->

Closes #186
  • Loading branch information
bitzoic authored May 9, 2024
1 parent 0cd6185 commit 8045a19
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 31 deletions.
2 changes: 1 addition & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
license = "Apache-2.0"

[dependencies]
fuel-merkle = { version = "0.33.0" }
fuel-merkle = { version = "0.49.0" }
sha2 = { version = "0.10" }
fuels = { version = "0.58.0", features = ["fuel-core-lib"] }
tokio = { version = "1.12", features = ["rt", "macros"] }
Expand Down
41 changes: 32 additions & 9 deletions examples/merkle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use fuel_merkle::{binary::in_memory::MerkleTree, common::Bytes32};
use fuels::{prelude::*, types::Bits256};
use sha2::{Digest, Sha256};

pub const LEAF: u8 = 0x00;

// Load abi from json
abigen!(Contract(
name = "MerkleExample",
Expand Down Expand Up @@ -44,32 +46,44 @@ async fn rust_setup_example() {
let (contract_instance, _id) = get_contract_instance().await;

// ANCHOR: generating_a_tree
// Create a new Merkle Tree and define leaves
let mut tree = MerkleTree::new();
let leaves = ["A".as_bytes(), "B".as_bytes(), "C".as_bytes()].to_vec();

// Hash the leaves and then push to the merkle tree
for datum in leaves.iter() {
let mut hasher = Sha256::new();
hasher.update(&datum);
let hash: Bytes32 = hasher.finalize().try_into().unwrap();
let hash = hasher.finalize();
tree.push(&hash);
}
// ANCHOR_END: generating_a_tree

let key = 0;
let num_leaves = 3;

// ANCHOR: generating_proof
let proof = tree.prove(key).unwrap();
// Define the key or index of the leaf you want to prove and the number of leaves
let key: u64 = 0;

// Get the merkle root and proof set
let (merkle_root, proof_set) = tree.prove(key).unwrap();

// Convert the proof set from Vec<Bytes32> to Vec<Bits256>
let mut bits256_proof: Vec<Bits256> = Vec::new();
for itterator in &proof.1 {
for itterator in proof_set {
bits256_proof.push(Bits256(itterator.clone()));
}
// ANCHOR_END: generating_proof

// ANCHOR: verify_proof
let merkle_root = proof.0;
let merkle_leaf = proof.1[key as usize];
bits256_proof.remove(key as usize);
// Create the merkle leaf
let mut leaf_hasher = Sha256::new();
leaf_hasher.update(&leaves[key as usize]);
let hashed_leaf_data = leaf_hasher.finalize();
let merkle_leaf = leaf_sum(&hashed_leaf_data);

// Get the number of leaves or data points
let num_leaves: u64 = leaves.len() as u64;

// Call the Sway contract to verify the generated merkle proof
let result: bool = contract_instance
.methods()
.verify(
Expand All @@ -86,3 +100,12 @@ async fn rust_setup_example() {
assert!(result);
// ANCHOR_END: verify_proof
}

pub fn leaf_sum(data: &[u8]) -> [u8; 32] {
let mut hash = Sha256::new();

hash.update(&[LEAF]);
hash.update(data);

hash.finalize().into()
}
2 changes: 1 addition & 1 deletion tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
license = "Apache-2.0"

[dependencies]
fuel-merkle = { version = "0.33.0" }
fuel-merkle = { version = "0.49.0" }
fuels = { version = "0.58.0", features = ["fuel-core-lib"] }
sha2 = { version = "0.10" }
tokio = { version = "1.12", features = ["rt", "macros"] }
Expand Down
50 changes: 30 additions & 20 deletions tests/src/merkle_proof/tests/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use fuel_merkle::{
binary::in_memory::MerkleTree,
common::{empty_sum_sha256, Bytes32},
};
use fuel_merkle::binary::in_memory::MerkleTree;
use fuel_tx::Bytes32;
use fuels::{
prelude::{
abigen, launch_provider_and_get_wallet, Contract, LoadConfiguration, TxPolicies,
Expand Down Expand Up @@ -96,9 +94,9 @@ pub mod test_helpers {
}

impl Node {
pub fn new(hash: Bytes32) -> Self {
pub fn new(hash: [u8; 32]) -> Self {
Node {
hash,
hash: hash.into(),
left: None,
right: None,
}
Expand All @@ -121,23 +119,26 @@ pub mod test_helpers {
) -> (MerkleTree, Bits256, Bits256, Vec<Bits256>) {
let mut tree = MerkleTree::new();
let num_leaves = leaves.len();
let mut leaf_hash = [0u8; 32];

for n in 0..num_leaves {
let mut hasher = Sha256::new();
hasher.update(&leaves[n]);
let hash: Bytes32 = hasher.finalize().try_into().unwrap();
let hash = hasher.finalize();

if n == key as usize {
leaf_hash = hash.into();
}

let _ = tree.push(&hash);
}

let merkle_root = tree.root();
let mut proof = tree.prove(key).unwrap();
let merkle_leaf = proof.1[0];
proof.1.remove(0);
let (merkle_root, proof) = tree.prove(key).unwrap();
let merkle_leaf = leaf_sum(&leaf_hash);

let mut final_proof: Vec<Bits256> = Vec::new();

for itterator in proof.1 {
for itterator in proof {
final_proof.push(Bits256(itterator.clone()));
}

Expand All @@ -156,7 +157,7 @@ pub mod test_helpers {
) -> (Bits256, Vec<Bits256>, Bits256) {
let num_leaves = leaves.len();
let mut nodes: Vec<Node> = Vec::new();
let mut leaf_hash: Bytes32 = *empty_sum_sha256();
let mut leaf_hash = [0u8; 32];
let mut proof: Vec<Bits256> = Vec::new();

assert!(key <= num_leaves);
Expand All @@ -166,12 +167,12 @@ pub mod test_helpers {
let mut hasher = Sha256::new();
hasher.update(&[LEAF]);
hasher.update(&leaves[n]);
let hash: Bytes32 = hasher.finalize().try_into().unwrap();
let hash = hasher.finalize();

let new_node = Node::new(hash);
let new_node = Node::new(hash.into());
nodes.push(new_node);
if n == key {
leaf_hash = hash.clone();
leaf_hash = hash.into();
}
}

Expand All @@ -186,7 +187,7 @@ pub mod test_helpers {
hasher.update(&[NODE]);
hasher.update(&nodes[itterator].hash);
hasher.update(&nodes[itterator + 1].hash);
let hash: Bytes32 = hasher.finalize().try_into().unwrap();
let hash = hasher.finalize().into();

let new_node = Node::new(hash).left(itterator).right(itterator + 1);
nodes.push(new_node);
Expand All @@ -210,12 +211,12 @@ pub mod test_helpers {
// Go left
index = node.left.unwrap();
let proof_node = node.right.unwrap();
proof.push(Bits256(nodes[proof_node].hash));
proof.push(Bits256(*nodes[proof_node].hash));
} else {
// Go right
index = node.right.unwrap();
let proof_node = node.left.unwrap();
proof.push(Bits256(nodes[proof_node].hash));
proof.push(Bits256(*nodes[proof_node].hash));

key = key - number_subtree_elements;
}
Expand All @@ -226,7 +227,7 @@ pub mod test_helpers {
(
Bits256(leaf_hash),
proof,
Bits256(nodes.last().unwrap().hash),
Bits256(*nodes.last().unwrap().hash),
)
}

Expand Down Expand Up @@ -258,4 +259,13 @@ pub mod test_helpers {

instance
}

pub fn leaf_sum(data: &[u8]) -> [u8; 32] {
let mut hash = Sha256::new();

hash.update(&[LEAF]);
hash.update(data);

hash.finalize().into()
}
}

0 comments on commit 8045a19

Please sign in to comment.