ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

为什么合约中需要的验签方法?

2021-08-18 21:57:43  阅读:464  来源: 互联网

标签:为什么 hash offer uint256 address memory 验签 合约 maker


为什么合约中需要的验签方法?

文章目录

场景

我一直有这么一个疑惑,疑惑来源于openzeppelin utilities当中的验签方法。代码如下

using ECDSA for bytes32;

function _verify(bytes32 data, address account) pure returns (bool) {
    return keccak256(data)
        .toEthSignedMessageHash()
        .recover(signature) == account;
}

既然所有的交易每个节点都会验证签名,那也就是保证了上链的数据确定是由msg.sender发出来了,那我在合约里面用这个工具方法的作用是什么?再验证一次?这个问题确实困扰了挺长时间的。直到我发现了一个市场合约,来源于 Meets (一个像素风格的3D人物NFT)。在 Meets 的市场合约部分,代码如下。为了方便阅读省略了其中的部分代码,完整地址请查看 另外一篇博文 产生不重复的随机数

    ///
    /// market
    ///
    
    struct Offer {...}

    function hashOffer(Offer memory offer) private pure returns (bytes32){
        //讲Offer 结构体中的参数紧打包之后生成hash
        return keccak256(abi.encode(....));
    }
    //获取
    function hashToSign(address maker, address taker, uint256 makerWei, uint256[] memory makerIds, uint256 takerWei, uint256[] memory takerIds, uint256 expiry, uint256 salt) public pure returns (bytes32) {
        Offer memory offer = Offer(maker, taker, makerWei, makerIds, takerWei, takerIds, expiry, salt);
        return hashOffer(offer);
    }

    function hashToVerify(Offer memory offer) private pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hashOffer(offer)));
    }
    //验证签名
    function verify(address signer, bytes32 hash, bytes memory signature) internal pure returns (bool) {
        //signer对hash 签名 判断是否与signature 一致。也是我开头提到的工具方法
    }

    function tradeValid(address maker, address taker, uint256 makerWei, uint256[] memory makerIds, uint256 takerWei, uint256[] memory takerIds, uint256 expiry, uint256 salt, bytes memory signature) view public returns (bool) {
        Offer memory offer = Offer(maker, taker, makerWei, makerIds, takerWei, takerIds, expiry, salt);
        //验证交易是否被取消
        bytes32 hash = hashOffer(offer);
        require(cancelledOffers[hash] == false, "Trade offer was cancelled.");
        //根据当前订单生成结果hash,与传入的signature参数是否相等
        bytes32 verifyHash = hashToVerify(offer);
        require(verify(offer.maker, verifyHash, signature), "Signature not valid.");
        // 其他验证
        ....
        return true;
    }
	//取消订单
    function cancelOffer(address maker, address taker, uint256 makerWei, uint256[] memory makerIds, uint256 takerWei, uint256[] memory takerIds, uint256 expiry, uint256 salt) external {
        cancelledOffers[hash] = true;
        emit OfferCancelled(hash);
    }

    function acceptTrade(address maker, address taker, uint256 makerWei, uint256[] memory makerIds, uint256 takerWei, uint256[] memory takerIds, uint256 expiry, uint256 salt, bytes memory signature) external payable nonReentrant {
		//验证交易是否属实
        require(tradeValid(maker, taker, makerWei, makerIds, takerWei, takerIds, expiry, salt, signature), "Trade not valid.");
        // 交换双方交易中达成的ETH
        ethBalance[offer.maker] = ethBalance[offer.maker].sub(offer.makerWei);
		...
        //交换双方达成交易中的指定的NFT
        for (uint i = 0; i < makerIds.length; i++) 
        ...
        for (uint i = 0; i < takerIds.length; i++) 
        ...
        // 预防重放攻击
        bytes32 hash = hashOffer(offer);
        cancelledOffers[hash] = true;
    }

为了方阅读删除了一部分的代码。主要关注acceptTrade 方法,在验证交易是否属实这一步
require(tradeValid(maker, taker, makerWei, makerIds, takerWei, takerIds, expiry, salt, signature), "Trade not valid.")
这个方法提供了一个验证链下数据的真实的功能。情况是这样的,用户A需要制造一个卖出订单,卖出1个NFT。那么链下客户端就可以按照Offer的数据结构生成一个hash然后对它进行钱包签名。同时把下单源数据和签名一起发布出去(不需要使用交易发布上链)。可以cdn或者ifps或者项目方维护的服务器,以便买家可以获取到交易的源数据,以及签名信息。
当买家想要达成交易的时候,可以链下验证这笔交易是否是真实的。如果通过验证,就可以调用合约的交易方法。这笔交易可以确保是买家发出的,合约中验证卖家的签名,确保交易订单时卖家签名的。此时就可以去信任,直接按照订单中规定的条件进行交换了。

总结

通过这样的方式,完成整个交易只需要发起一笔交易,也就是买家的买入交易。验签的合约函数,可以把一系列流水线操作,通过一次交易的方式完成。就像区块链本身一样,一个头咬着一个头。

标签:为什么,hash,offer,uint256,address,memory,验签,合约,maker
来源: https://blog.csdn.net/topc2000/article/details/119789184

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有