Solidity实现默克尔树 Merkle Tree

这篇具有很好参考价值的文章主要介绍了Solidity实现默克尔树 Merkle Tree。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

​Merkle Tree​​​,也叫默克尔树或哈希树,是区块链的底层加密技术,被BTC和Ethereum区块链广泛采用。​​Merkle Tree​​​是一种自下而上构建的加密树,每个叶子是对应数据的哈希,而每个非叶子为它的​​2​​个子节点的哈希。

solidity 怎样定义树型结构,区块链

​Merkle Tree​​允许对大型数据结构的内容进行有效和安全的验证(​​Merkle Proof​​)。对于有​​N​​个叶子结点的​​Merkle Tree​​,在已知​​root​​根值的情况下,验证某个数据是否有效(属于​​Merkle Tree​​叶子结点)只需要​​log(N)​​个数据(也叫​​proof​​),非常高效。如果数据有误,或者给的​​proof​​错误,则无法还原出​​root​​根植。 下面的例子中,叶子​​L1​​的​​Merkle proof​​为​​Hash 0-1​​和​​Hash 1​​:知道这两个值,就能验证​​L1​​的值是不是在​​Merkle Tree​​的叶子中。为什么呢? 因为通过叶子​​L1​​我们就可以算出​​Hash 0-0​​,我们又知道了​​Hash 0-1​​,那么​​Hash 0-0​​和​​Hash 0-1​​就可以联合算出​​Hash 0​​,然后我们又知道​​Hash 1​​,​​Hash 0​​和​​Hash 1​​就可以联合算出​​Top Hash​​,也就是root节点的hash。

solidity 怎样定义树型结构,区块链

生成​​Merkle Tree​​

我们可以利用​​网页​​或者Javascript库​​merkletreejs​​来生成​​Merkle Tree​​。

这里我们用网页来生成​​4​​个地址作为叶子结点的​​Merkle Tree​​。叶子结点输入:

[
"0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
"0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2",
"0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db",
"0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB"
]

在菜单里选上​​Keccak-256​​, ​​hashLeaves​​和​​sortPairs​​选项,然后点击​​Compute​​,​​Merkle Tree​​就生成好了。​​Merkle Tree​​展开为:

└─ 根: eeefd63003e0e702cb41cd0043015a6e26ddb38073cc6ffeb0ba3e808ba8c097
├─ 9d997719c0a5b5f6db9b8ac69a988be57cf324cb9fffd51dc2c37544bb520d65
│ ├─ 叶子0:5931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229
│ └─ 叶子1:999bf57501565dbd2fdcea36efa2b9aef8340a8901e3459f4a4c926275d36cdb
└─ 4726e4102af77216b09ccd94f40daa10531c87c4d60bba7f3b3faf5ff9f19b3c
├─ 叶子2:04a10bfd00977f54cc3450c9b25c9b3a502a089eba0097ba35fc33c4ea5fcb54
└─ 叶子3:dfbe3e504ac4e35541bebad4d0e7574668e16fefa26cd4172f93e18b59ce9486

solidity 怎样定义树型结构,区块链

​​Merkle Proof​​验证

通过网站,我们可以得到​​地址0​​的​​proof​​如下,即图2中蓝色结点的哈希值:

[
"0x999bf57501565dbd2fdcea36efa2b9aef8340a8901e3459f4a4c926275d36cdb",
"0x4726e4102af77216b09ccd94f40daa10531c87c4d60bba7f3b3faf5ff9f19b3c"
]

solidity 怎样定义树型结构,区块链

我们利用​​MerkleProof​​库来验证:

library MerkleProof {
/**
* @dev 当通过`proof`和`leaf`重建出的`root`与给定的`root`相等时,返回`true`,数据有效。
* 在重建时,叶子节点对和元素对都是排序过的。
*/
function verify(
bytes32[] memory proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}

/**
* @dev Returns 通过Merkle树用`leaf`和`proof`计算出`root`. 当重建出的`root`和给定的`root`相同时,`proof`才是有效的。
* 在重建时,叶子节点对和元素对都是排序过的。
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}

// Sorted Pair Hash
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? keccak256(abi.encodePacked(a, b)) : keccak256(abi.encodePacked(b, a));
}
}

​MerkleProof​​库有三个函数:

  1. ​verify()​​函数:利用proof数来验证leaf是否属于根为rootMerkle Tree中,如果是,则返回true。它调用了processProof()函数。
  2. ​processProof()​​函数:利用proofleaf依次计算出Merkle Treeroot。它调用了_hashPair()函数。
  3. ​_hashPair()​​函数:用keccak256()函数计算非根节点对应的两个子节点的哈希(排序后)。

我们将​​地址0​​,​​root​​和对应的​​proof​​输入到​​verify()​​函数,将返回​​ture​​。因为​​地址0​​在根为​​root​​的​​Merkle Tree​​中,且​​proof​​正确。如果改变了其中任意一个值,都将返回​​false​​。

利用​​Merkle Tree​​发放​​NFT​​白名单

一份拥有800个地址的白名单,更新一次所需的gas fee很容易超过1个ETH。而由于​​Merkle Tree​​验证时,​​leaf​​和​​proof​​可以存在后端,链上仅需存储一个​​root​​的值,非常节省​​gas​​,项目方经常用它来发放白名单。很多​​ERC721​​标准的​​NFT​​和​​ERC20​​标准代币的白名单/空投都是利用​​Merkle Tree​​发出的,比如​​optimism​​的空投。

这里,我们介绍如何利用​​MerkleTree​​合约来发放​​NFT​​白名单:

contract MerkleTree is ERC721 {
bytes32 immutable public root; // Merkle树的根
mapping(address => bool) public mintedAddress; // 记录已经mint的地址

// 构造函数,初始化NFT合集的名称、代号、Merkle树的根
constructor(string memory name, string memory symbol, bytes32 merkleroot)
ERC721(name, symbol)
{
root = merkleroot;
}

// 利用Merkle树验证地址并完成mint
function mint(address account, uint256 tokenId, bytes32[] calldata proof)
external
{
require(_verify(_leaf(account), proof), "Invalid merkle proof"); // Merkle检验通过
require(!mintedAddress[account], "Already minted!"); // 地址没有mint过
_mint(account, tokenId); // mint
mintedAddress[account] = true; // 记录mint过的地址
}

// 计算Merkle树叶子的哈希值
function _leaf(address account)
internal pure returns (bytes32)
{
return keccak256(abi.encodePacked(account));
}

// Merkle树验证,调用MerkleProof库的verify()函数
function _verify(bytes32 leaf, bytes32[] memory proof)
internal view returns (bool)
{
return MerkleProof.verify(proof, root, leaf);
}
}

​MerkleTree​​合约继承了​​ERC721​​标准,并利用了​​MerkleProof​​库。

状态变量

合约中共有两个状态变量:

  • ​root​​存储了​​Merkle Tree​​的根,部署合约的时候赋值。
  • ​mintedAddress​​是一个​​mapping​​,记录了已经​​mint​​过的地址,某地址mint成功后进行赋值。

函数

合约中共有4个函数:

  • 构造函数:初始化​​NFT​​的名称和代号,还有​​Merkle Tree​​的​​root​​。
  • ​mint()​​函数:利用白名单铸造​​NFT​​。参数为白名单地址​​account​​,铸造的​​tokenId​​,和​​proof​​。首先验证​​address​​是否在白名单中,验证通过则把序号为​​tokenId​​的​​NFT​​铸造给该地址,并将它记录到​​mintedAddress​​。此过程中调用了​​_leaf()​​和​​_verify()​​函数。
  • ​_leaf()​​函数:计算了​​Merkle Tree​​的叶子地址的哈希。
  • ​_verify()​​函数:调用了​​MerkleProof​​库的​​verify()​​函数,进行​​Merkle Tree​​验证。

​​remix​​验证

我们使用上面例子的​​4​​个地址作为白名单并生成​​Merkle Tree​​。我们部署​​MerkleTree​​合约,​​3​​个参数分别为:

name = "WTF MerkleTree"
symbol = "WTF"
merkleroot = 0xeeefd63003e0e702cb41cd0043015a6e26ddb38073cc6ffeb0ba3e808ba8c097

solidity 怎样定义树型结构,区块链

接下来运行​​mint​​函数给地址0铸造​​NFT​​,​​3​​个参数分别为:

account = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
tokenId = 0
proof = [ "0x999bf57501565dbd2fdcea36efa2b9aef8340a8901e3459f4a4c926275d36cdb", "0x4726e4102af77216b09ccd94f40daa10531c87c4d60bba7f3b3faf5ff9f19b3c" ]

solidity 怎样定义树型结构,区块链

我们可以用​​ownerOf​​函数验证​​tokenId​​为0的​​NFT​​已经铸造给了地址0,合约运行成功!

solidity 怎样定义树型结构,区块链

此时,若再次调用mint函数,虽然该地址能够通过​​Merkle Proof​​验证,但由于地址已经记录在​​mintedAddress​​中,因此该交易会由于​​"Already minted!"​​被中止。

总结

这一讲,我们介绍了​​Merkle Tree​​的概念,如何生成简单的​​Merkle Tree​​,如何利用智能合约验证​​Merkle Tree​​,以及用它来发放​​NFT​​白名单。

在实际使用中,复杂的​​Merkle Tree​​可以利用​​javascript​​库​​merkletreejs​​来生成和管理,链上只需要存储一个根值,非常节省​​gas​​。很多项目方都选择利用​​Merkle Tree​​来发放白名单。文章来源地址https://www.toymoban.com/news/detail-794395.html

到了这里,关于Solidity实现默克尔树 Merkle Tree的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于Python实现的默克尔树

           默克尔树常见的结构是二叉树,但它也可以是多叉树,它具有树结构的全部特点。 默克尔树的基础数据不是固定的,想存什么数据都可以,因为它只要数据经过哈希运算得到的哈希值。 默克尔树是从下往上逐层计算,每个中间节点是根据相邻的两个叶子节点组合计算

    2024年02月02日
    浏览(23)
  • 区块链 — 默克尔树

    默克尔树(又叫哈希树)是一种典型的二叉树结构,有一个根节点、一组中间节点和一组叶节点组成。默克尔树最早由 Merkle Ralf 在 1980 年提出,曾广泛用于文件系统和P2P系统中。比如 git、区块链、IPFS 等。 主要特点: 最下面的叶节点包含存储数据或其哈希值; 非叶子节点(

    2024年02月12日
    浏览(45)
  • 区块链——默克尔树

    默克尔树是一种二叉树,由一组叶节点、一组中间节点和一个根节点构成,看下图: 我们从最底部开始看,D0、D1、D2和D3是叶子节点包含的数据,也就是叶子节点的value,继续往上看,N0、N1、N2和N3是就是叶子节点,它是将数据(也就是D0、D1、D2和D3)进行hash运算后得到的ha

    2024年04月10日
    浏览(26)
  • 【区块链】C语言编程实现三叉Merkle树

    1. Merkle树简介   如上图所示,Merkle 树的叶子节点为交易序列,对每一笔交易进行 Hash(SHA 256算法) 之后,然后对得到的 Hash 节点进行拼接再次进行 Hash 运算,如此递归直到递归至根节点。   如上图所示 Merkle 树的优点在于可快速验证某个区块是否存在指定交易,如要验

    2024年04月14日
    浏览(33)
  • 【区块链 | Merkle】使用Merkle Tree空投,白名单验证

      Merkle Tree在高效验证数据的同时减少了链上计算和存储,因为非常适合基于区块链的白名单验证,空投,IDO等需要验证数据的业务。 默克尔树,在区块链出现前,曾广泛用于文件系统和P2P系统中。 在区块链中,默克尔树常用于高效验证数据,如,实现空投,白名单,IDO,混

    2024年02月04日
    浏览(70)
  • Merkle Tree、Merkle Proof、SPV安全性分析、Bloom过滤器

    区块链基础参考前面翻译的白皮书 Merkle Tree的最大特点是:可以以一个很简短的方法来证明一棵树中存在某一个元素。即 Simplified Payment Verification,SPV 【问题】tx10、proof均为外部提供的信息,roothash又是公开信息,是否可以构造恶意数据对(tx,proof)骗过轻节点的验证,如果不能

    2024年02月09日
    浏览(30)
  • solidity函数签名的实现-solidity实现智能合约教程(8)

    猛戳订阅学习专栏🍁🍁 👉 solidity系列合约源码+解析 👈 🍁🍁 函数选择器: solidity调用函数时,calldata的前4个字节为指定要调用的函数,这4个字节称为函数选择器。 以下面的代码为例。它通过地址addr的调用合约的transfer方法。 abi.encodeWithSignature(…)返回的前4个字节是函数

    2024年02月16日
    浏览(40)
  • Merkle Tree 简介

    Merkle 树(Merkle Tree)是一种树状数据结构,通常用于验证大规模数据集的完整性和一致性。它的名字来源于其发明者 Ralph Merkle。Merkle 树在密码学、分布式系统和区块链等领域得到广泛应用,尤其在区块链中,它用于验证交易和区块的完整性,确保数据不被篡改。 下面是 Me

    2024年02月08日
    浏览(31)
  • 异步Merkle Tree

    前序博客: 利用多核的Rust快速Merkle tree Anoushk Kharangate 2023年论文《Asynchronous Merkle Trees》,其对Merkle tree数据结构进行修改,使得可跨多线程异步计算。 开源代码实现见: https://github.com/anoushk1234/async-merkle-tree(Rust) Merkle tree应用广泛,有各种变种,如: Jellyfish Merkle Tree Spa

    2024年01月18日
    浏览(29)
  • 科普|区块链中的Merkle Tree

    什么是Merkle Tree? - Merkle Tree也就是Merkle树,中文译名还有梅克尔树或默克尔树,因为这是一棵用哈希值搭建起来的树,树的所有节点都存储了哈希值,所以也叫哈希树,英文名为Hash Tree。默克尔树通常情况下看着是一棵倒置的树型结构,根节点在顶部,分叉向下,叶子节点

    2024年02月02日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包