区块链:Merkle树的逻辑和证明

什么是Merkle树

定义

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

如何生成Merkle树的数据

在solidity中我们通过keccak256算法计算hash值:

keccak256(abi.encodePacked(toHashValue)e.g.:hash前0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2hash后0x999bf57501565dbd2fdcea36efa2b9aef8340a8901e3459f4a4c926275d36cdb

a16z Crypto发布纪念以太坊合并的NFT“Proof-of-Merge”:9月15日消息,a16z Crypto 发布纪念以太坊合并的 NFT“Proof-of-Merge”,用户在合并发生前可免费铸造。该NFT是一个动态NFT,根据“难度”的值和合并的估计时间输出不同的元数据和插图,并以 ASCII 艺术为特色,用计算机语言呈现不同视觉效果。

其中该NFT的生命周期有三个阶段,所有阶段都基于对 EVM 中嵌入的上述“难度”的读取。第一阶段,预合并时显示两个分开的圆圈。在第二阶段,随着合并的临近,两个圆圈将开始相交,直到它们重叠,形成类似日食的画面;一旦合并发生,形状将转化为最终形式:阴阳符号。[2022/9/15 6:57:00]

在对叶子节点的值进行hash运算之后,再把相邻的节点再进行hash运算,直到只剩下一个根节点。假设存在两个相邻的节点A和B,那么在进行hash运算的时候到地址是hash(A+B)呢?还是hash(B+A)呢?其实这是由A和B的大小决定的,在openzeppelin对应的merkle代码中我们可以找到这么一段代码:

Hyosung America与比特币ATM机运营商DigitalMint达成合作:7月14日消息,Hyosung America与美国主要比特币ATM机运营商DigitalMint签署了一项合作协议,有望为17.5万台ATM机集成购买比特币的服务。

除了提供自己的BTC和LTC支付通道,如ATM机、银行电汇和柜员机,DigitalMint还提供软件API集成,允许零售商或ATM运营商通过他们的机器销售BTC。

作为协议的一部分,Hyosung America将把DigitalMint的加密货币购买服务添加到其即将推出的基于API的应用商店中,该应用商店是为该公司的ATM机创建的。然而,这将取决于特定的ATM运营商决定他们是否要纳入DigitalMint的服务,这意味着Hyosung America的17.5万台ATM机中的大多数不太可能真正支持比特币购买。(Cointelegraph)[2022/7/14 2:12:50]

function_hashPair(bytes32a,bytes32b)privatepurereturns(bytes32){returna<b?_efficientHash(a,b):_efficientHash(b,a);}

富达高管Jurrien Timmer:比特币价格似乎已经触底,是时候看涨了:富达投资高管Jurrien Timmer表示,在展望比特币的下一步走势时,是时候看涨而不是看跌了。他表示:“在我看来,比特币的底部似乎已经到了。”(Cointelegraph)[2021/6/15 23:38:15]

总结来说就是把相对小的数值放到前面去这么来排序计算hash值。这个地方在自己动手实际运算的时候可能会有些许困惑。在实际的项目中一般只需要把计算的最后结果的根hash值存储到合约中,如果大量的地址都需要存到合约中的话会消耗大量的gas费。经过merkle树计算之后,大大的减少了需要存储的数据。通过一段foundry的setUp演示下如何计算和存储roothash值:

bytes32publicroot;bytes32publicleafs;bytes32publicl2;functionsetUp()public{addressmemoryaddrss=newaddress(4);addrss=0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2;addrss=0x2d886570A0dA04885bfD6eb48eD8b8ff01A0eb7e;addrss=0xed857ac80A9cc7ca07a1C213e79683A1883df07B;addrss=0x690B9A9E9aa1C9dB991C7721a92d351Db4FaC990;//通过地址列表计算叶子节点的hash值leafs.push(keccak256(abi.encodePacked(addrss)));leafs.push(keccak256(abi.encodePacked(addrss)));leafs.push(keccak256(abi.encodePacked(addrss)));leafs.push(keccak256(abi.encodePacked(addrss)));//计算第二层的hash值l2.push(keccak256(abi.encodePacked(leafs,leafs)));l2.push(keccak256(abi.encodePacked(leafs,leafs)));//计算根的hash值root=keccak256(abi.encodePacked(l2,l2));}

热币全球品牌战略官Merry:热币致力布局全产业应用:金色财经现场报道,9月20日,由金色财经主办,水桥区块链总冠名的“共为·创业者大会”在厦门举办。热币全球品牌战略官Merry做了主题为《乘风破浪的热币三年》的演讲,Merry在演讲中介绍了热币的发展历程。Merry表示,热币的使命是要成为一个开放、进取、共享、回报型的平台,为全球用户搭建一个安全便利的交易服务中心,构建全球开放的生态联盟,共享区块链的发展红利,力争交易服务平台潮头,为区块链行业作出我们应有的贡献。目前热币的日活跃是在6万+以上,24小时交易额达到7亿美金。接下来,我们希望在今年十月份能把抵押借贷,杠杆借贷,法币借贷以及期权借贷上线,在明年底之前搭建全球化的价值社区,布局全产业的应用升级。[2020/9/20]

为了演示方便我们值写了4个地址,实际项目中可能地址数量非常大。

如何来验证Merkle树

在合约中存储到roothash值之后我们如何去验证由客户端发过来的地址是否是有效地址或者说在白名单中的地址呢?首先我们需要将地址进行hash运算,作为第三个参数,然后将地址相邻的hash值作为proof传到验证函数中。proof列表对应下面图片中的红色标记区域

测试的验证方法:

functiontestVerify()public{addressproofAddress=0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2;bytes32memoryproof=newbytes32(2);proof=leafs;proof=l2;assert(MerkleProof.verify(proof,root,keccak256(abi.encodePacked(proofAddress))));}

在实际项目中的应用场景

发放空投

NFT的白名单

在合约审计中的常见漏洞

functionparentHash(bytes32a,bytes32b)publicpurereturns(bytes32){if(a<b){returnkeccak256(abi.encode(a,b));}else{returnkeccak256(abi.encode(b,a));}}

abi.encode(address,uint)将会输出64字节。由于abi.encode(bytes32,bytes32)也是64字节,因此在叶子节点和父节点之间可能会发生哈希碰撞。

郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。

地球链

[0:15ms0-0:522ms