#merkle-tree #proofs #generate #tree-root #merkle-root #standard

merkle-tree-rs

一个用于生成梅克尔树和梅克尔证明的 Rust 库

1 个不稳定版本

0.1.0 2022年11月17日

#13#merkle-root

MIT 许可证

40KB
809

merkle-tree-rs

一个用于生成梅克尔树和梅克尔证明的 Rust 库。

非常适合与 OpenZeppelin 合约 MerkleProof 工具结合使用的空投和类似机制。

快速入门

将 merkle-tree-rs 添加到您的仓库中,还需要 serde 和 serde_json 以支持 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();
  1. 获取要包含在树中的值。(注意:考虑从文件中读取它们。)
  2. 构建梅克尔树。设置编码以匹配值。
  3. 打印梅克尔根。您可能需要在智能合约中发布此值。
  4. 编写一个描述树的文件。您将向用户分发此文件,以便他们可以为树中的值生成证明。

获取证明

假设我们正在寻找与地址 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);
      }
    }
  1. 从之前生成的描述中加载树。
  2. 遍历条目以找到您感兴趣的条目。
  3. 使用条目的索引生成证明。

在实际操作中,这可能在提交证明到链之前在客户端应用程序中完成,查找的地址是连接的钱包地址。

请参阅 MerkleProof 了解如何在 Solidity 中验证证明的文档。

标准梅克尔树

此库适用于为以太坊智能合约设计的“标准”梅克尔树。我们根据使其安全且适用于链上验证的一些特性对其进行了定义。

  • 该树呈 完全二叉树 形状。
  • 叶子排序。
  • 叶子是编码一系列值的 ABI 编码的结果。
  • 使用的哈希是 Keccak256。
  • 叶子经过双重哈希以防止 第二次预映像攻击

从最后三点我们可以得到,树中具有值 [addr, amount] 的叶子的哈希可以通过以下方式在 Solidity 中计算

bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(addr, amount))));

这是一个具有偏见的设 计,我们相信它将为大多数用户提供最佳的开箱即用体验。根据用户请求,我们可能会在未来引入自定义选项。

API & 示例

StandardMerkleTree

use merkle_tree_rs::standard::StandardMerkleTree,

StandardMerkleTree.

目前支持编码的类型包括地址、uint、uint256和字符串。

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);

从树中元素的数组创建一个标准默克尔树,包括它们的类型用于ABI编码。

注意 考虑从CSV文件读取元素数组,以便与电子表格或其他数据处理管道轻松互操作。

.

println!("{}", tree.root());

树的根是对树中值的承诺。它可以被发布(例如,在智能合约中)以证明其值是树的组成部分。

.转储

let tree_json = serde_json::to_string(&tree.dump()).unwrap();

fs::write("tree.json", tree_json).unwrap();

返回默克尔树的描述,以便分发。它包含所有必要的信 息来重建树、找到相关的叶子节点并生成证明。您应该在Web应用程序或命令行界面中将此信息分发给用户,以便他们可以为他们的兴趣叶子节点生成证明。

StandardMerkleTree.加载

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);

从先前由 dump 返回的描述中加载树。

.getProof

let proof = tree.get_proof(LeafType::Number(i));

返回树的第 i 个值的证明。索引指的是构建树时数组中值的位 置。

它被包装在 LeafType 枚举中,其中 Number 表示索引(usize),LeafBytes 表示值(Vec<string>)。使用值效率较低,因为如果值不在树中,它将失败。

let proof = tree.getProof(LeafType::LeafBytes([alice, "100"]));

.getMultiProof

let multi_proof = tree.getMultiProof([LeafType::Number(i0), LeafType::Number(i1), ...]);

返回一个多证明结构,包含 i0i1,... 索引处的值的证明、prooflags和leaves。索引指的是构建树时数组中值的位 置。

返回的多证明包含一个包含正在证明的叶子的数组。这个数组可能不同于 i0i1,... 给出的顺序!返回的顺序很重要,因为叶子必须按此顺序提交进行验证(例如,在智能合约中)。

也接受值而不是索引,但这将效率较低。如果任何值不在树中,它将失败。

遍历树

for (i, v) in tree.clone().enumerate {
  console.log("value: {:?}", v);
  console.log("proof: {:?}", tree.getProof(LeafType::Number(i)));
}

列出树中的值及其索引,可用于获取证明。

.render

println!("{:?}", tree.render());

返回一个可视化的树表示,可用于调试。

.leafHash

let leaf = tree.leafHash(["alice".to_string(), "100".to_string()]);

返回值的叶子哈希,如标准默克尔树中定义。

对应于Solidity中的以下表达式

bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(alice, 100))));

归属

依赖关系

~19–37MB
~558K SLoC