- A+
多重签名
多重签名脚本设置了一个条件,其中N个公钥被记录在脚本中,并且至少有M个必须提供签名来解锁资金。这也称为M-N方案,其中N是密钥的总数,M是验证所需的签名的数量。
例如,2/3的多重签名是三个公钥被列为潜在签名人,至少有2个有效的签名才能花费资金。此时,标准多重签名脚本限制在最多15个列出的公钥,这意味着您可以从1到15之间的多重签名或该范围内的任何组合执行任何操作。在本书发布之前,限制15个已列出d的密钥可能会被解除,因此请检查isStandard()函数以查看当前网络接受的内容。
设置M-N多重签名条件的锁定脚本的一般形式是:
M <Public Key 1> <Public Key 2> ... <Public Key N> N CHECKMULTISIG
M是花费输出所需的签名的数量,N是列出的公钥的总数。 设置2到3多重签名条件的锁定脚本如下所示:
2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG
上述锁定脚本可由含有签名和公钥的脚本予以解锁: 或者由3个存档公钥中的任意2个相一致的私钥签名组合予以解锁。 两个脚本组合将形成一个验证脚本:
<Signature B> <Signature C> 2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG
当执行时,只有当未解锁版脚本与解锁脚本设置条件相匹配时,组合脚本才显示得到结果为真(Ture)。
CHECKMULTISIG执行中的bug
CHECKMULTISIG的执行中有一个bug,需要一些技巧处理。 当CHECKMULTISIG执行时,它应该消耗堆栈(stack) 上的M + N + 2个项目作为参数。 然而,由于该错误,CHECKMULTISIG将弹出(pop)超出预期的额外值或一个值。
我们来看看这个更详细的使用以前的验证示例:
<Signature B> <Signature C> 2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG
首先,CHECKMULTISIG弹出最上面的项目,这是N(在这个例子中N是“3”)。然后它弹出N个项目,这是可以签名的公钥。在这个例子中,公钥A,B和C.然后,它弹出一个项目,即M,仲裁(需要多少个签名)。这里M = 2。此时,CHECKMULTISIG应弹出最终的M个项目,这些是签名,并查看它们是否有效。
然而,不幸的是,实施中的错误导致CHECKMULTISIG再弹出一个项目(总共M + 1个)。检查签名时,不考虑额外的项目,因此它对CHECKMULTISIG本身没有直接影响。但是,必须存在额外的值,因为如果不存在,则当CHECKMULTISIG尝试弹出空堆栈时,会导致堆栈错误和脚本失败(将交易标记为无效)。因为额外的项目被忽略,它可以是任何东西,但通常使用0。
因为这个bug成为共识规则的一部分,所以现在它必须永远被复制。因此,正确的脚本验证将如下所示:
0 <Signature B> <Signature C> 2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG
这样解锁脚本就不是下面的:
<Signature B> <Signature C>
而是:
0 <Signature B> <Signature C>
从现在开始,如果你看到一个multisig解锁脚本,你应该期望看到一个额外的0开始,其唯一的目的是解决一个bug,意外地成为一个共识规则的解决方法。 【即保证例子中有3个私钥签名(其中2有效签名,其中1个为0的无效签名)对应3个公钥用于检查多重签名,从而保证脚本不产生bug。】
应用:采用多重签名作为会计账簿
Mohammed的公司采用比特币多重签名作为其公司会计账簿记账要求。多重签名脚本是比特币高级脚本最为常见的运用之一,是一种具有相当大影响力的脚本。针对所有的顾客支付(即应收账款),Mohammed的公司要求采用多重签名交易。基于多重签名机制,顾客的任何支付都需要至少两个签名才能解锁,一个来自Mohammed,另一个来自其合伙人或拥有备份钥匙的代理人。这样的多重签名机制能为公司治理提供管控便利,同时也能有效防范盗窃、挪用和遗失。
多重签名的弊端
- 虽然多重签名十分强大,但其使用起来还是多有不便。
- 基于之前的脚本,Mohammed必须在客户付款前将该脚本发送给每一位客户,而每一位顾客也必须使用特制的能产生客户交易脚本的比特币钱包软件,每位顾客还得学会如何利用脚本来完成交易。
- 此外,由于脚本可能包含特别长的公钥,最终的交易脚本可能是最初交易脚本长度的5倍之多。额外长度的脚本将给客户造成费用负担。
- 最后,一个长的交易脚本将一直记录在所有节点的随机存储器的UTXO集中,直到该笔资金被使用。采用这种复杂输出脚本使得在实际交易中变得困难重重。