您的位置:首页 > 其它

区块链-多重签名中CHECKMULTISIG执行中的bug

2019-05-21 19:14 746 查看

目录:https://blog.csdn.net/qq_40452317/article/details/89646633

来看看多重签名(https://blog.csdn.net/qq_40452317/article/details/90412143)一个例子,比特币的正确的验证脚本如下:

[code]0 <Signature B> <Signature C> 2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG

对比多重签名中的验证脚本会发现,这个正确的验证脚本前面多了个0,这个0是什么回事?

这是因为在CHECKMULTISIG的执行中有一个bug,来看看这个bug是怎么产生的。

[code]<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。

0取出后它被立刻丢去,并不用于之后的运算。这个数具体是什么值无关紧要,可堆栈上不能缺失它,不然无法正常执行CHECKMULTISIG。为了保证共识机制的向后兼容,每个解锁脚本就多压入一个零,而CHECKMULTISIG实现代码里的错误只能年复一年地遗留下来。

来看正确的脚本执行:

[code]0 <Signature B> <Signature C> 2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG

解锁脚本是:

[code]0 <Signature B> <Signature C>
[code]   // 首先运行解锁脚本
0: [] // 初始状态:空堆栈
1: [0] // 0 被压入栈顶
2: [0, 签名B] // PUSHDATA 入栈第一个签名
3: [0, 签名B, 签名C] // PUSHDATA 入栈第二个签名
4: [0, 签名B, 签名C, 脚本] // PUSHDATA 入栈完整脚本
// 复制堆栈后运行上锁脚本
5: [0, 签名B, 签名C, 脚本哈希] // HASH160 取出栈顶脚本,压入它的哈希
6: [0, 签名B, 签名C, 脚本哈希, 目标脚本哈希] // PUSHDATA 入栈目标脚本哈希
7: [0, 签名B, 签名C, TRUE] // EQUAL 取出栈顶两个哈希,判断是否相等,压入检测结果
// 取出栈顶结果,如果非真,则验证失败,否则运行原始脚本
8: [0, 签名B, 签名C] // 准备运行原始脚本
9: [0, 签名B, 签名C, 2] // 2 被压入栈顶
10: [0, 签名B, 签名C, 2, 公钥A] // PUSHDATA 入栈第一个公钥
11: [0, 签名B, 签名C, 2, 公钥A, 公钥B] // PUSHDATA 入栈第二个公钥
12: [0, 签名B, 签名C, 2, 公钥A, 公钥B, 公钥C] // PUSHDATA 入栈第三个公钥
13: [0, 签名B, 签名C, 2, 公钥A, 公钥B, 公钥C, 3] // 3 被压入栈顶
14: [0, 签名B, 签名C, 2, 公钥A, 公钥B, 公钥C] // CHECKMULTISIG 先取出公钥数N(3)
15: [0, 签名B, 签名C, 2] // 接着取出N(3)个公钥
16: [0, 签名B, 签名C] // 再取出签名数M(2)
17: [TRUE] // 接着取出M(2)个签名和数字0,根据交易验证签名,压入检查结果
// 栈顶为真则验证成功

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: