比特幣腳本執行期間“特殊情況”的完整列表(p2sh、p2wsh 等)?
在執行比特幣腳本時,有一些“特殊情況”,解釋器會執行額外的驗證,而不僅僅是執行
scriptSig
thenscriptPubKey
。例如,如果
scriptPubKey
具有以下特定格式:OP_HASH160 <20 byte hash> OP_EQUAL
然後解釋器將另外應用BIP 0016“支付到腳本雜湊”(P2SH)規則。
在腳本執行期間可能遇到的“特殊情況”的完整列表是什麼,以及每種情況何時遇到?
截至 2021 年 1 月,網路上所有活動共識規則的“高級”腳本驗證大致如下:
頂級評價
執行
scriptSig
, 並呼叫生成的堆棧stack
。如果執行中止,則失敗。執行
scriptPubKey
withstack
作為輸入,並呼叫生成的 stackresult
。如果執行中止,則失敗。如果
result
為空,或其頂部元素的數值為 0,則失敗。如果
scriptPubKey
正好等於一個 OP_n(n 介於 0 和 16 之間,含),然後直接推送正好 2 到 40 個字節(含):
- 如果
scriptSig
不為空,則失敗。- 使用 as 程序執行 segwit 驗證
scriptPubKey
,將 n 值作為版本,並witness
作為輸入(見進一步)。如果此執行中止,則失敗。如果
scriptPubKey
恰好等於 OP_HASH160 + 20 字節推送 + OP_EQUAL,則執行 P2SH 驗證:
如果
scriptSig
不只包含推送,則失敗。如果
result
為空,則失敗。將 的頂部元素解釋
result
為腳本,然後執行它,其餘部分result
作為輸入。呼叫生成的堆棧p2sh_result
。如果此執行中止,則失敗。如果
p2sh_result
為空,或其頂部元素的數值為 0,則失敗。如果頂部元素
result
恰好是 OP_n(n 介於 0 和 16 之間),然後直接推送 2 到 40 個字節(包括):
- 如果
scriptSig
不完全是 的頂部元素的直接推送,則result
失敗。- 使用 as 程序執行 segwit 驗證
scriptPubKey
,將 n 值作為版本,並witness
作為輸入(見進一步)。如果此執行中止,則失敗。如果在此之前沒有發生故障,則腳本有效。
遵循驗證
version
版本、程序program
和輸入的 Segwit 驗證input
:
如果版本為 0:
如果程序不是 20 或 32 字節,則失敗。
如果程序是 20 字節
hash
:
hash
使用初始堆棧執行腳本 OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIGinput
。如果執行中止,則失敗。- 如果結果堆棧不完全是一個元素,或者該元素的數值為 0,則失敗。
如果程序是 32 字節
hash
:
- 如果
input
為空,或者其頂部元素的 SHA256 雜湊不等於hash
,則失敗。- 執行
input
as 腳本的頂部元素,其他元素作為輸入。如果執行中止,則失敗。- 如果結果堆棧不完全是一個元素,或者該元素的數值為 0,則失敗。
如果到此為止沒有發生故障,則返回成功。
此答案不包括 BIP341 和 BIP342 引入的更改,因為它們在網路上不活動。它也不包括各種標準/政策規則。
來源:https ://github.com/bitcoin/bitcoin/blob/v0.20.1/src/script/interpreter.cpp ,函式
VerifyScript
,,,。VerifyWitnessProgram``ExecuteWitnessScript
TL;DR:只有 BIP16 P2SH 模式(OP_HASH160 <20 字節> OP_EQUAL)和 BIP141 segwit 模式(OP_n <2 到 40 字節>)是觸發附加規則的實際特殊情況。但細節更複雜。