DEV Community

晓道
晓道

Posted on

ECDSA使用,实现多签 (二)

昨天留下多签的代码还没写,今天还是写了一会会儿,前文在这里:ECDSA使用,实现多签 (一) | 登链社区 | 深入浅出区块链技术 (learnblockchain.cn)
这篇文章有参考一个老外的文章,但是做了一些优化,思路一致。
Signature Replay | Hack Solidity #13 | by Zuhaib Mohammed | Jan, 2022 | CoinsBench (medium.com)

一个简单的多签,运用到一个转账业务中就是,一个老板小李建立了一个多签合约,初始化公司股东,小张,小王,小陈,小马几个人做为操作人,有这几个人同意,就可以通过多签合约给其他人转钱。

首先初始化合约,最多5个操作人,最少3个人同意就可以转:

constructor(address[] memory _operators) public payable { owner = msg.sender; require(_operators.length <= 5, "Too many operators"); for (uint8 i = 0; i < _operators.length; i++) { operators[i] = _operators[i]; } } 
Enter fullscreen mode Exit fullscreen mode

转账函数定义:

function transfer( address _to, uint256 _amount, bytes[] memory sigs ) external { bytes32 txHash = getTxHash(_to, _amount); require(_checkSigs(txHash, sigs, 2), "Only operators can transfer"); (bool sender, ) = _to.call{value: _amount}(""); require(sender, "sender failed"); } 
Enter fullscreen mode Exit fullscreen mode

_checkSigs是我们的关键函数,检查签名是不是这个人签出来的。

function _checkSigs( bytes32 txhash, bytes[] memory sigs, uint8 numSigs // ) private view returns (bool) { uint8 c = 0; //emit log_named_uint("sigs len", sigs.length); bool[] memory bops = new bool[](operators.length); for (uint8 i = 0; i < sigs.length; i++) { //emit log_named_bytes("txHash", txHash); if (!_findOpt(txhash.recover(sigs[i]), bops)) { return false; } c++; } //emit log_named_uint("c", c); if (c > numSigs) { return true; } else { return false; } } 
Enter fullscreen mode Exit fullscreen mode
function _findOpt(address sigaddr, bool[] memory bops) private view returns ( bool ) { for (uint8 i = 0; i < operators.length; i++) { //emit log_named_address("operators", operators[i]); if (operators[i] != address(0x0)) { if (bops[i] == false) { if (operators[i] == sigaddr) { //emit log_named_address("find", operators[i]); bops[i] = true; //emit log("set true"); return true; } } } else { break; } } return false; } 
Enter fullscreen mode Exit fullscreen mode

为什么这样就可以?
检查签名是不是这个人签出来的,看我前面的ECDSA用法讲解。 ECDSA使用,实现多签 (一) | 登链社区 | 深入浅出区块链技术 (learnblockchain.cn)
相对于老外的代码,我做了一些升级,操作人变成5个,转账时候的签名,可以不按照顺序进行签名对比。
对比网站上其他人的文章,我这个更像一个技术原型,所以我会继续更新,弄一个更偏向业务的合约。测试用例什么的,都在github上,看测试用例,应该更能理解是怎么回事。
更详细的,看我github上的仓库:
SimpleMultiSig

Top comments (0)