实战比特币脚本编程(2)困局

在前一篇可以想到3种分割完整脚本的办法。

# PUSH ONLY

但现实因为要考虑安全因素,比特币不允许在解锁脚本中放入OP_ADD这样的操作符

也就是下面的形式不允许。

第一段解锁脚本(不允许)

OP_2
OP_3
OP_ADD

第二段锁定脚本

OP_5
OP_EQUAL

OP_2和OP_3将2和3推入栈中,而OP_ADD对栈进行操作。在比特币节点里有设置SCRIPT_VERIFY_SIGPUSHONLY,只允许数据入栈的操作。

// File: validation.cpp Line:3464
flags |= SCRIPT_VERIFY_SIGPUSHONLY;

否则会出现下面的错误

16: mandatory-script-verify-flag-failed (Only non-push operators allowed in signatures)

如果允许解锁脚本带有操作符,那么下面的解锁代码可以解锁任意脚本

OP_TRUE
OP_RETURN

PUSHONLY属于一刀切的禁止方式,应该有更好的实现方式。

# Redeem Script

那么是否有绕开的方式呢?曾经有一种机制叫做兑换脚本(RedeemScript), 用于将脚本完全放在解锁脚本中,这个机制的名字叫做支付到脚本(P2SH)

例子如下

const redeem = 'OP_ADD OP_5 OP_EQUAL'
const redeemScript = Script.fromASM(redeem)
const redeemScriptHex = redeemScript.toHex()
const redeemScriptBuffer = redeemScript.toBuffer()
const redeemScriptHash = Hash.sha256ripemd160(redeemScriptBuffer)
const unlock = `OP_2 OP_3 ${redeemScriptHex}`
const lockingScript = `OP_HASH160 ${redeemScriptHash.toString('hex')} OP_EQUAL`

制作一段兑换脚本,比如OP_ADD OP_5 OP_EQUAL,对这段脚本的Hex进行Hash160计算(sha256(ripedmd160()), 将得到的hash填入锁定脚本。将hex放入解锁脚本。

比特币节点运行的时候,会先连接解锁脚本和锁定脚本,计算Hex的Hash160,看看Hex是否等于事先的约定代码。如果是,则解释Hex部分组合成兑换脚本,执行

OP_2 OP_3 OP_ADD OP_5 OP_EQUAL

这种兑换脚本(RedeemScript)的方案属于黑盒,无法从公开在区块链上的锁定脚本看出程序的语义。

此方案已经在2020年2月被比特币禁止。

如果还想广播这样的脚本,比特币节点会返回

16: bad-txns-vout-p2sh

# 困局

车到山前,路呢?

柳暗花明,村呢?

享受比特币带来的安全自由, 关注使用NoteSV (opens new window)