为什么合约中需要的验签方法?
2021/8/18 23:11:53
本文主要是介绍为什么合约中需要的验签方法?,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
为什么合约中需要的验签方法?
文章目录
- 为什么合约中需要的验签方法?
- 场景
- 总结
场景
我一直有这么一个疑惑,疑惑来源于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或者项目方维护的服务器,以便买家可以获取到交易的源数据,以及签名信息。
当买家想要达成交易的时候,可以链下验证这笔交易是否是真实的。如果通过验证,就可以调用合约的交易方法。这笔交易可以确保是买家发出的,合约中验证卖家的签名,确保交易订单时卖家签名的。此时就可以去信任,直接按照订单中规定的条件进行交换了。
总结
通过这样的方式,完成整个交易只需要发起一笔交易,也就是买家的买入交易。验签的合约函数,可以把一系列流水线操作,通过一次交易的方式完成。就像区块链本身一样,一个头咬着一个头。
这篇关于为什么合约中需要的验签方法?的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-15鸿蒙生态设备数量超8亿台
- 2024-05-13TiDB + ES:转转业财系统亿级数据存储优化实践
- 2024-05-09“2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”实战课程已上线
- 2024-05-09聊聊如何通过arthas-tunnel-server来远程管理所有需要arthas监控的应用
- 2024-05-09log4j2这么配就对了
- 2024-05-09nginx修改Content-Type
- 2024-05-09Redis多数据源,看这篇就够了
- 2024-05-09Google Chrome驱动程序 124.0.6367.62(正式版本)去哪下载?
- 2024-05-09有没有大佬知道这种数据应该怎么抓取呀?
- 2024-05-09这种运行结果里的10.100000001,怎么能最快改成10.1?