4

ECDSA使用,实现多签 (二)

 2 years ago
source link: https://learnblockchain.cn/article/3548
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

ECDSA使用,实现多签 (二)

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];
        }
    }

转账函数定义:

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");
    }

_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;
        }
    }
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;
    }

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

本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 2天前
  • 阅读 ( 129 )
  • 学分 ( 7 )
  • 分类:Solidity

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK