【从0学习Solidity】36. 默克尔树 Merkle Tree

【从0学习Solidity】36. 默克尔树 Merkle Tree

在这里插入图片描述

  • 博主简介:不写代码没饭吃,一名全栈领域的创作者,专注于研究互联网产品的解决方案和技术。熟悉云原生、微服务架构,分享一些项目实战经验以及前沿技术的见解。
  • 关注我们的主页,探索全栈开发,期待与您一起在移动开发的世界中,不断进步和创造!
  • 本文收录于 不写代码没饭吃 的学习汇报系列,大家有兴趣的可以看一看。
  • 欢迎访问我们的微信公众号:不写代码没饭吃,获取更多精彩内容、实用技巧、行业资讯等。您关注的是我们前进的动力!

这一讲,我将介绍Merkle Tree,以及如何利用Merkle Tree发放NFT白名单。

Merkle Tree

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

36-1.png

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

36-2.png

生成Merkle Tree

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

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

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

在菜单里选上Keccak-256, hashLeavessortPairs选项,然后点击ComputeMerkle Tree就生成好了。Merkle Tree展开为:

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

36-3.png

Merkle Proof验证

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

["0x999bf57501565dbd2fdcea36efa2b9aef8340a8901e3459f4a4c926275d36cdb","0x4726e4102af77216b09ccd94f40daa10531c87c4d60bba7f3b3faf5ff9f19b3c"
]

36-4.png

我们利用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 Hashfunction _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()函数计算非根节点对应的两个子节点的哈希(排序后)。

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

利用Merkle Tree发放NFT白名单

一份拥有800个地址的白名单,更新一次所需的gas fee很容易超过1个ETH。而由于Merkle Tree验证时,leafproof可以存在后端,链上仅需存储一个root的值,非常节省gas,项目方经常用它来发放白名单。很多ERC721标准的NFTERC20标准代币的白名单/空投都是利用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树验证地址并完成mintfunction 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); // mintmintedAddress[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 Treeroot
  • mint()函数:利用白名单铸造NFT。参数为白名单地址account,铸造的tokenId,和proof。首先验证address是否在白名单中,验证通过则把序号为tokenIdNFT铸造给该地址,并将它记录到mintedAddress。此过程中调用了_leaf()_verify()函数。
  • _leaf()函数:计算了Merkle Tree的叶子地址的哈希。
  • _verify()函数:调用了MerkleProof库的verify()函数,进行Merkle Tree验证。

remix验证

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

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

36-5.png

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

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

36-6.png

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

36-7.png

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

总结

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

在实际使用中,复杂的Merkle Tree可以利用javascriptmerkletreejs来生成和管理,链上只需要存储一个根值,非常节省gas。很多项目方都选择利用Merkle Tree来发放白名单。

在这里插入图片描述

如果这份博客对大家有帮助,希望各位给作者一个免费的点赞👍作为鼓励,并评论收藏一下⭐,谢谢大家!!!
制作不易,如果大家有什么疑问或给作者的意见,欢迎评论区留言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/142413.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通俗易懂-OpenCV角点检测算法(Harris、Shi-Tomas算法实现)

目录 1 图像的特征 2&#xff0c;Harris角点检测 2.1 代码实现 2.2结果展示 3&#xff0c;Shi-Tomasi角点检测算法 3.1 &#xff0c; 代码实现 3.2结果展示 1 图像的特征 2&#xff0c;Harris角点检测 、 2.1 代码实现 import cv2 as cv import matplotlib.pyplot as …

QFrame类学习笔记

1、QFrame的作用 QFrame类继承于QWidget类&#xff0c;被QAbstractScrollArea, QLabel, QLCDNumber, QSplitter, QStackedWidget, and QToolBox等类继承。 QFrame作为许多基础控件的基类&#xff0c;提供许多成员方法给子类&#xff0c;实现子类的框架样式的设计。框架样式主要…

基于微信小程序的健身小助手打卡预约教学系统(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;用户的功能设计为&#xff1a;管理员的功能设计为&#xff1a;健身房的功能设计为&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获…

【数据结构】插入排序:直接插入排序、折半插入排序、希尔排序的学习知识总结

目录 1、排序的基本概念 2、直接插入排序 2.1 算法思想 2.2 代码实现 3、折半插入排序 3.1 算法思想 3.2 代码实现 4、希尔排序 4.1 算法思想 4..2 代码实现 1、排序的基本概念 排序是将一组数据按照预定的顺序排列的过程&#xff0c;排序的基本概念包括以下内容…

electron快速入门

新建electronstu01文件夹 以管理员身份运行powershell&#xff0c;切换到该文件下 npm init -y安装依赖包 npm install --save-dev electron失败 npm install -g cnpm --registryhttps://registry.npm.taobao.org cnpm install --save-dev electron修改 package.json &qu…

正则表达式的应用(前端写法)

文章目录 1、匹配字符串中&#xff0c;a标签的href值2、校验邮箱3、校验手机号码3、待添加... 1、匹配字符串中&#xff0c;a标签的href值 (1) 代码 /*** description 匹配字符串中&#xff0c;a标签的href值* param {string} str 匹配的字符串* return {Array} 返回href值*/…

冒泡排序与选择排序(最low的两兄弟)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言&#xff1a; 在我们的生活中&#xff0c;无处不在用到排序&#xff0c;比如说成绩的排名&#xff0c;淘宝&#xff0c;京东等等商品在各个方面的排序&#xff0c;这样看来一个好的算 法很重要&#xff0c;接下来我们要先…

JVM对象创建与内存分配机制

对象的创建 对象创建的主要流程: ​ 1.类加载检查 虚拟机遇到一条new指令时&#xff0c;首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用&#xff0c;并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有&#xff0c;那必须先执行相应…

Lua学习笔记:debug.sethook函数

前言 本篇在讲什么 使用Lua的debug.setHook函数 本篇需要什么 对Lua语法有简单认知 依赖Sublime Text工具 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&#xff0c;快速上手 提供全流程的源码内容 ★提高阅读体验★ &#x1f449; ♠ 一级标题 &…

【AI视野·今日NLP 自然语言处理论文速览 第三十八期】Thu, 21 Sep 2023

AI视野今日CS.NLP 自然语言处理论文速览 Thu, 21 Sep 2023 Totally 57 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Chain-of-Verification Reduces Hallucination in Large Language Models Authors Shehzaad Dhuliawala, Mojt…

华为杯数学建模比赛经验分享

再过一周左右,第二十届华为杯数学建模比赛就要开赛了&#xff0c;所以今天分享一下个人数学建模比赛的经验。 今天给大家分享一期关于华为杯数学建模比赛的经验分享&#xff0c;我将从以下三个方面展开说明&#xff1a; &#xff08;1&#xff09;如何准备数学建模比赛&#x…

系统集成|第十七章(笔记)

目录 第十七章 变更管理17.1 项目变更的基本概念17.2 变更管理的基本原则17.3 角色职位与工作程序17.4 相关事宜 上篇&#xff1a;第十六章、信息&#xff08;文档&#xff09;和配置管理 下篇&#xff1a;第十八章、安全管理 第十七章 变更管理 17.1 项目变更的基本概念 变更…

获取热门电影算法

功能#2&#xff1a;获取热门电影 为我们的“Netflix”项目实现“获取热门电影”功能。 我们将介绍以下内容 描述 解决方案 复杂性措施 时间复杂度 空间复杂度 描述# 现在&#xff0c;我们需要建立一个标准&#xff0c;以便将来自多个国家的顶级电影组合成一个单一的顶级电影…

24. 图论 - 图的表示种类

Hi,你好。我是茶桁。 之前的一节课中,我们了解了图的来由和构成,简单的理解了一下图的一些相关概念。那么这节课,我们要了解一下图的表示,种类。相应的,我们中间需要穿插一些新的知识点用于更好的去理解图,比如说邻接矩阵。 图的表示 我们一般用什么样的形式来表示图…

Linux su sudo命令

1、su命令——切换用户 1.1、切换到root用户(需要密码) su - root 1.2、切换到其他用户&#xff0c;比如jackma&#xff08;无需密码&#xff09; su - jackma 2、sudo命令——给普通用户添加root权限 2.1、用法 切换到root用户&#xff0c;执行visudo命令&#xff0c;会自动…

配置pytorchGPU虚拟环境-python3.7

cuda版本的pytorch包下载地址戳这里 winR->输入cmd->输nvcc -V回车 cuda 11.0 输入以下命令来查找 CUDA 的安装路径&#xff1a; Windows: where nvcc 输入以下命令来查找 cuDNN 的版本号&#xff1a; Windows: where cudnn* cuDNN 8.0 本机安装的是cuda 11.0&…

C语言数组和指针笔试题(三)(一定要看)

目录 字符数组四例题1例题2例题3例题4例题5例题6例题7 结果字符数组五例题1例题2例题3例题4例题5例题6例题7结果字符数组六例题1例题2例题3例题4例题5例题6例题7 结果 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412;个…

第二证券:迎政策助力,新型工业化爆发,德恩精工3日涨超60%

新式工业化概念26日盘中大幅拉升&#xff0c;到发稿&#xff0c;德恩精工、精伦电子、天永智能等涨停&#xff0c;固高科技涨约8%&#xff0c;亚威股份涨逾6%&#xff0c;金自天正、创世纪涨约5%。 值得注意的是&#xff0c;精伦电子已接连5个交易日涨停&#xff0c;公司昨日晚…

2023-09-21 buildroot linux 查看应用的log打印信息,命令cat /var/log/messages

一、应用会调用syslog 把打印信息输出到串口&#xff0c;debug 串口会打印kernel的log和上层应用的的log。 二、linux 命令cat /var/log/messages查看应用log

Spire.OCR for .NET 1.9.0 Crack

Spire.OCR for .NET 是一个专业的 OCR 库&#xff0c;用于从 JPG、PNG、GIF、BMP 和 TIFF 格式的图像中读取文本。开发人员可以轻松地在 C# 和 VB.NET 的 .NET 应用程序中添加 OCR 功能。它支持常用的图像格式&#xff0c;并提供从图像中​​读取多个字符和字体、粗体和斜体样式…