Merkle Tree

这个 crate 提供了一组用于在链上验证 Merkle Tree 证明的实用程序。树和证明可以使用这个 JavaScript 库 生成。

这个模块提供:

  • verify - 可以证明某个值是 Merkle 树的一部分。

  • verify_multi_proof - 可以证明多个值是 Merkle 树的一部分。

注意:openzeppelin_merkle_tree 没有 corelib 之外的依赖项,并且可以在与 Starknet 无关的项目中使用。

要将其用作独立包,您可以将其添加到您的 Scarb.toml 中,如下所示:

openzeppelin_merkle_tree = "3.0.0-alpha.0"

模块

merkle_proof

use openzeppelin_merkle_tree::merkle_proof;

这些函数处理 Merkle Tree 证明的验证。

树和证明可以使用这个 JavaScript 库 生成。您将在自述文件中找到快速入门指南。

警告:在哈希之前,应该避免使用长度为两个 felt252 值 的 leaf 值,或者使用与用于哈希内部节点的哈希函数不同的哈希函数来哈希叶子。这是因为 Merkle 树中排序的一对内部节点的连接可以被重新解释为 leaf 值。这个 JavaScript 库生成的 Merkle 树可以防范这种攻击。

函数

verify<+CommutativeHasher>(proof: Span<felt252>, root: felt252, leaf: felt252) → bool public

如果可以证明 leaf 是由 root 定义的 Merkle 树的一部分,则返回 true。

为此,必须提供一个 proof,其中包含从树的 leaf 到 root 的分支上的兄弟哈希值。

假定每对叶子和每对 pre-image 都已排序。

此函数需要 CommutativeHasher 实现。有关更多信息,请参阅 hashes::CommutativeHasher

verify_pedersenverify_poseidon 已经包含了相应的 Hasher 实现。

verify_pedersen(proof: Span<felt252>, root: felt252, leaf: felt252) → bool public

使用 Pedersen 作为哈希函数的 verify 版本。

verify_poseidon(proof: Span<felt252>, root: felt252, leaf: felt252) → bool public

使用 Poseidon 作为哈希函数的 verify 版本。

process_proof<+CommutativeHasher>(proof: Span<felt252>, leaf: felt252) → felt252 public

返回通过使用 proofleaf 遍历 Merkle 树向上重建的哈希值。

当且仅当重建的哈希值与树的 root 匹配时,proof 才有效。

在处理证明时,假定叶子和 pre-image 对已排序。

注意:此函数需要 CommutativeHasher 实现。有关更多信息,请参阅 hashes::CommutativeHasher

verify_multi_proof<+CommutativeHasher>(proof: Span<felt252>, proof_flags: Span<bool>, root: felt252, leaves: Span<felt252>) → bool public

如果可以同时证明 leaves 是由 root 定义的 Merkle 树的一部分,则返回 true,根据 process_multi_proof 中描述的 proofproof_flags

leaves 必须独立验证。

警告:并非所有 Merkle 树都允许使用多重证明。有关详细信息,请参见 process_multi_proof

注意:考虑 root == proof.at(0) && leaves.len() == 0 的情况,因为它将返回 true

注意:此函数需要 CommutativeHasher 实现。有关更多信息,请参阅 hashes::CommutativeHasher

process_multi_proof<+CommutativeHasher>(proof: Span<felt252>, proof_flags: Span<bool>, leaves: Span<felt252>) → felt252 public

返回从 leavesproof 中的兄弟节点重建的树的 root。

重建过程通过将 leaf/内部节点与另一个 leaf/内部节点或证明兄弟节点结合,增量重建所有内部节点,具体取决于每个 proof_flags 项是 true 还是 false。

并非所有 Merkle 树都允许使用多重证明。 要使用多重证明,足以确保:

  1. 树是完整的(但不一定是完美的)。

  2. 要证明的叶子的顺序与它们在树中的顺序相反。 (即,从最深层开始,从右到左看,然后在下一层继续)。

注意:空集(即 proof.len() == 1 && leaves.len() == 0 的情况)被认为是无操作,因此是有效的多重证明(即,它返回 proof.at(0))。如果您不在其他地方验证叶子,请考虑禁止这种情况。

注意:此函数需要 CommutativeHasher 实现。有关更多信息,请参阅 hashes::CommutativeHasher

hashes

use openzeppelin_merkle_tree::hashes;

模块为 merkle_proof 中使用的交换哈希函数提供 trait 和默认实现。

注意:PedersenCHasher 实现与 JavaScript 库 中使用的默认节点哈希函数匹配。

Traits

CommutativeHasher trait

声明一个具有以下签名的交换哈希函数:

commutative_hash(a: felt252, b: felt252) → felt252;

它计算一对排序的 felt252 值的交换哈希。

这通常作为非交换哈希函数的扩展来实现,例如 Pedersen 或 Poseidon,通过首先对两个值进行排序,然后返回两个值连接后的哈希。

通常在处理 merkle 证明时使用。

注意:commutative_hash 函数必须遵循 commutative_hash(a, b) == commutative_hash(b, a) 的不变性。

Impls

PedersenCHasher impl

CommutativeHasher trait 的实现,它计算链式连接两个输入值(长度为 2)的 Pedersen 哈希,首先对这对输入值进行排序。

PoseidonCHasher impl

CommutativeHasher trait 的实现,它计算两个值连接后的 Poseidon 哈希,首先对这对值进行排序。