web3默克尔树MerleTree白名单校验

默克尔树(⼜叫哈希树)是⼀种典型的⼆叉树结构,有⼀个根节点、⼀组中间节点和⼀ 组叶节点组成。

曾⼴泛⽤于⽂件系统和P2P系统中。⽐如 git 、 区块链 、 IPFS 等

主要特点:类似二叉树, 最下⾯的叶节点包含存储数据或其哈希值; ⾮叶⼦节点(包括中间节点和根节点)都是它的两个⼦节点内容的哈希值
在这里插入图片描述
比特币中的默克尔树
在这里插入图片描述

MerkleTree的校验

判断某个叶⼦节点是否存在于树中,不需要知道整棵树的所有 节点的hash值,只需要找到需要校验的叶⼦节点的相邻节点的HASH,以及祖先节点相 邻节点的HASH即可

空投白名单应用

步骤简单概括

  1. 创建默克尔树, 拿到merkleRoot和对应地址的Proof, 其中merkleRoot上传到智能合约
  2. 使用地址和对应的Proof调用合约去验证

相关开源库

合约开源库: https://docs.openzeppelin.com/contracts/4.x/api/utils#MerkleProof
前端开发库:https://github.com/miguelmota/merkletreejs

步骤

  1. 前端配置的⽩名单地址,⽣成根节点hash。

  2. 合约存根节点hash值。

  3. 前端传⼊领取空投的address,和兄弟节点以及祖先的兄弟节点hash

合约代码

pragma solidity ^0.8.9;
 pragma abicoder v2;
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
contract Merkletree{
    bytes32 public rootHash;
    function setRootHash(bytes32 _rootHash) public{
        // 设置节点hash,需要做权限管理 ,方便测试,不做限制
        rootHash = _rootHash; 
    }
    function claimable(bytes32[] memory proof, bytes32 leaf)  public view returns(bool) {
        // 校验 
        return MerkleProof.verify(proof, rootHash, leaf); 
    }

    function claim(bytes32[] memory proof, bytes32 leaf) public {
        // 验证当前地址是否是msg.sender
        require(leaf == keccak256(abi.encodePacked(msg.sender)), "only by sender"); 
        // 验证叶⼦是否在⽩名单
        require(claimable(proof, leaf), 'auth faild');
        // mint Token and transfer to leaf address
    }
}

js代码

import { MerkleTree } from "merkletreejs";
import keccak256 from "keccak256";
import { newContract,ChainId, multicallClient } from "@chainstarter/multicall-client.js";

const WhiteList = [
  "0xd4D75e2eB480D61822B9cA40EB54cb322F08d920",
  "0xdafea492d9c6733ae3d56b7ed1adb60692c98bc5",
  "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
  "0x8b8a11755a3f2B9f2cE384bc42Cb25053Eb4FF33",
  "0xd2Ece3F5A7738E4B14c13C0336E3e879755FCd77"
]

const leaves = WhiteList.map((x) => keccak256(x));
const merkleTree = new MerkleTree(leaves, keccak256);
const rootHash = merkleTree.getRoot().toString("hex");

const leaf = keccak256(inputAccount);
const proof = merkleTree.getProof(leaf);
//前端校验
const isWhiteList = merkleTree.verify(proof, leaf, rootHash)

// 合约校验
// 在此之前,需要调用setRootHash,将rootHash存入合约
const leaf32 = `0x${leaf.toString("hex")}`;
const proof32 = proof.map((x) => "0x" + x.data.toString("hex"));
const contract = newContract(
  MerkleTreeAbi,
  MerkleTreeAddress,
  ChainId.RINKEBY
);
multicallClient([
  contract.claimable(proof32, leaf32),
  contract.rootHash(),
]).then((res) => {
  console.log("是否存在白名单", res[0].returnData);
  console.log("合约rootHash", res[1].returnData);
  setIsWhiteList(!!res[0].returnData);
});

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值