该文档提出了在 Elements 网络中 Taproot 升级时添加的新操作码,包括用于流式哈希的流式操作码、用于交易内省的交易内省代码、有符号 64 位算术操作码、转换操作码和新的加密操作符,旨在增强智能合约的功能和效率,同时考虑了资源限制和安全性。
本文档提议将新的操作码添加到 elements 网络以及 taproot 升级中。新的 tapscript OP_SUCCESS
操作码允许比通过 OP_NOP
更干净地引入新的操作码。在本文档中,我们提议修改以下 OP_SUCCESS
以具有额外的语义。我们按顺序使用操作码 OP_SUCCESS196
,197
...,以避免与 bitcoin 可能使用的 OP_SUCESSSx
发生冲突(假设 bitcoin 根据可用性按顺序使用这些操作码)。本文档的初始版本具有额外的操作码(OP_FOR
,多字节操作码),但为了简化应用程序的复杂性,已更新为当前版本。
Taproot 已经极大地增加了 segwitv0 的资源限制,因此无需额外更改任何内容。特别是,根据 BIP 342
OP_CHECKSIG
、OP_CHECKSIGVERIFY
或 OP_CHECKSIGADD
)会将预算减少 50。如果这使预算低于零,则脚本会立即失败。80
字节。
用于流式哈希的流式操作码:由于 MAX_SCRIPT_ELEMENT_SIZE
(520 字节) 的限制,我们无法对超过 520 字节的消息执行诸如 OP_SHA256
之类的哈希函数。这允许对超过 520 字节的数据进行哈希,同时仍然保持现有的针对资源耗尽攻击的安全性。Russell O'Connor 对此的提议可以在此处的描述中找到。
OP_SUCCESS196
定义为 OP_SHA256INITIALIZE
,它弹出一个字节串,并通过将字节串添加到初始 SHA256 上下文中来 push SHA256 上下文。OP_SUCCESS197
定义为 OP_SHA256UPDATE
,它首先弹出一个字节串,然后弹出另一个 SHA256 上下文,并通过将字节串添加到正在哈希的数据流来 push 更新后的上下文。OP_SUCCESS198
定义为 OP_SHA256FINALIZE
,它首先弹出一个字节串,然后弹出另一个 SHA256 上下文,最后在添加字节串并完成填充后 push SHA256 哈希值。交易自省代码:通过使用 OP_CHECKSIGFROMSTACKVERIFY
,已经可以在 elements 脚本中进行交易自省,但是,当前的解决方案在诸如 covenants 之类的应用程序中非常昂贵。因此,我们没有通过支持自省来添加任何新功能,只是使其更易于使用。与 covenants 一样,警告仍然相同,如果用户从交易中未签名的部分检查数据,则脚本可能会导致意外行为。
对于从 sighash 中未提交的数据部分进行检查的操作码,自省是安全的,因为对见证数据的任何更改都会导致 wtxid 发生更改,并且它将再次重新验证交易。对于 pegin 输入,资产/价值/脚本信息将来自父链。
OP_SUCCESS199
定义为 OP_INSPECTINPUTOUTPOINT
:弹出一个 CScriptNum
输入索引 idx
,并将 outpoint 作为元组 push。首先 push prev_out
的 txid
(32),然后 push vout
的 4 字节,然后 push outpoint_flag(1),如 Elements 的修改版 BIP-341 SigMsg 中所定义。OP_SUCCESS200
定义为 OP_INSPECTINPUTASSET
:弹出一个 CScriptNum
输入索引 idx
,并将 nAsset
作为两个元素 push 到堆栈上。首先 push assetID(32),然后 push 前缀(1)。OP_SUCCESS201
定义为 OP_INSPECTINPUTVALUE
:弹出一个 CScriptNum
输入索引 idx
,并将 nValue
作为元组 push,值(8 字节 LE, 32) 后跟前缀(1)。OP_SUCCESS202
定义为 OP_INSPECTINPUTSCRIPTPUBKEY
:弹出一个 CScriptNum
输入索引 idx
,并根据 scriptPubkey 的类型 push 以下内容:
CScriptNum(-1)
以指示非原生的隔离见证 scriptPubKey。OP_SUCCESS203
定义为 OP_INSPECTINPUTSEQUENCE
:弹出一个 CScriptNum
输入索引 idx
,并将 nSequence
(4) 作为小端数字 push。OP_SUCCESS204
定义为 OP_INSPECTINPUTISSUANCE
:弹出一个 CScriptNum
输入索引 idx
,如果资产有发行,则 push 资产发行信息,否则 push 一个空向量。资产发行信息按如下方式 push
nInflationKeys
作为元组 push,值(8 字节 LE, 32) 后跟 push 前缀(1)。如果 nInflationKeys
为 null,则 push 一个 8 字节 LE 的 0
,后跟一个对于显式前缀(1)的 push。nAmount
作为元组 push,值(8 字节 LE, 32) 后跟 push 前缀(1)。如果 nAmount
为 null,则 push 一个 8 字节 LE 的 0
,后跟一个对于显式前缀(1)的 push。assetEntropy
assetBlindingNonce
OP_SUCCESS205
定义为 OP_PUSHCURRENTINPUTINDEX
,它将当前输入索引作为 CScriptNum
push。这可以与输入自省操作码结合使用,以检查当前输入。OP_SUCCESS206
定义为 OP_INSPECTOUTPUTASSET
:弹出一个 CScriptNum
输入索引 idx
,并将 nAsset
作为元组 push,首先 push assetID(32),然后 push 前缀(1)。OP_SUCCESS207
定义为 OP_INSPECTOUTPUTVALUE
:弹出一个 CScriptNum
输入索引 idx
,并将 nValue
作为元组 push,值(8 字节 LE, 32) 后跟前缀。OP_SUCCESS208
定义为 OP_INSPECTOUTPUTNONCE
:弹出一个 CScriptNum
输入索引 idx
,并将 nNonce
(33) push 到堆栈上。如果 nonce 为 null,则将一个空向量 push 到堆栈上。OP_SUCCESS209
定义为 OP_INSPECTOUTPUTSCRIPTPUBKEY
:弹出一个 CScriptNum
输入索引 idx
,并将 scriptPubkey push 到堆栈上。
CScriptNum(-1)
以指示非原生的隔离见证 scriptPubKey。OP_SUCCESS210
定义为 OP_INSPECTVERSION
:将 nVersion(4) 作为小端 push。OP_SUCCESS211
定义为 OP_INSPECTLOCKTIME
:将 nLockTime(4) 作为小端 push。OP_SUCCESS212
定义为 OP_INSPECTNUMINPUTS
:将输入的数量作为 CScriptNum pushOP_SUCCESS213
定义为 OP_INSPECTNUMOUTPUTS
:将输出的数量作为 CScriptNum pushOP_SUCCESS214
定义为 OP_TXWEIGHT
:将交易权重 (8) 作为小端 push有符号 64 位算术操作码: 当前对 CScriptNum
的操作限制为 4 字节,并且由于最小化规则而难以组合。使用 8 字节有符号操作的固定宽度小端操作有助于对编码为 8 字节小端的金额进行计算。
CScriptNum
返回,结果是从顶部开始的第二个元素。如果操作溢出,则首先将操作数 push 到堆栈上,然后 push 成功位。[a_second
a_top
] 溢出,操作后的堆栈状态为 [a_second
a_top
0
],如果操作未溢出,则堆栈状态为 [res
1
]。OP_IF\OP_ELSE
编写脚本来处理溢出,或者如果他们期望操作永远不会失败,则这使用户可以灵活地处理。
在定义可能失败的操作码时,我们只定义成功路径,并假设如上所述的溢出行为。
OP_SUCCESS215
定义为 OP_ADD64
:弹出第一个数字(8 字节 LE)作为 b
,然后弹出另一个 a
(8 字节 LE)。将 a + b push 到堆栈上。如果没有溢出,则 push 1 CScriptNum
。 溢出行为如上所述。OP_SUCCESS216
定义为 OP_SUB64
:弹出第一个数字(8 字节 LE)作为 b
,然后弹出另一个 a
(8 字节 LE)。将 a - b push 到堆栈上。如果没有溢出,则 push 1 CScriptNum
。 溢出行为如上所述。OP_SUCCESS217
定义为 OP_MUL64
:弹出第一个数字(8 字节 LE)作为 b
,然后弹出另一个 a
(8 字节 LE)。将 a*b
push 到堆栈上。如果没有溢出,则 push 1 CScriptNum
。 溢出行为如上所述。OP_SUCCESS218
定义为 OP_DIV64
:弹出第一个数字(8 字节 LE)作为 b
,然后弹出另一个 a
(8 字节 LE)。首先将余数 a%b
(必须为非负数且小于 |b|)push 到堆栈上,然后将商 (a//b
) push 到堆栈上。如果 b==0
或 a = -2<sup>63</sup> && b = -1
,则视为溢出,如上所述。如果没有溢出,则 push 1 CScriptNum
。OP_SUCCESS219
定义为 OP_NEG64
:弹出第一个数字(8 字节 LE)作为 a
,并将 -a
push 到堆栈顶部。如果数字为 -2<sup>63</sup>
(int64_min
),则视为溢出,否则 push CScriptNum
1 以指示没有溢出。OP_SUCCESS220
定义为 OP_LESSTHAN64
(不会失败!):弹出第一个数字(8 字节 LE)作为 b
,然后弹出另一个 a
(8 字节 LE)。Push a < b
。OP_SUCCESS221
定义为 OP_LESSTHANOREQUAL64
(不会失败!):弹出第一个数字(8 字节 LE)作为 b
,然后弹出另一个 a
(8 字节 LE)。Push a <= b
。OP_SUCCESS222
定义为 OP_GREATERTHAN64
(不会失败!):弹出第一个数字(8 字节 LE)作为 b
,然后弹出另一个 a
(8 字节 LE)。Push a > b
。OP_SUCCESS223
定义为 OP_GREATERTHANOREQUAL64
(不会失败!):弹出第一个数字(8 字节 LE)作为 b
,然后弹出另一个 a
(8 字节 LE)。Push a >= b
。OP_AND
、OP_OR
、OP_INVERT
和 OP_XOR
已经支持二进制运算转换操作码: 从 CScriptNum
转换为 8 字节 LE
、4 字节 LE
的方法。
OP_SUCCESS224
定义为 OP_SCIPTNUMTOLE64
:将堆栈弹出为最小的 CSciptNum
,push 与该数字对应的 8 字节有符号 LE。OP_SUCCESS225
定义为 OP_LE64TOSCIPTNUM
:将堆栈弹出为 8 字节有符号 LE。转换为 CScriptNum
并 push 它,失败则中止。OP_SUCCESS226
定义为 OP_LE32TOLE64
:将堆栈弹出为 4 字节无符号 LE。Push 相应的 8 字节有符号 LE 数字。不会失败,对于版本、locktime、序列、输入数量、输出数量、权重等操作很有用。加密: 为了允许在 elements 上进行更复杂的操作,我们引入了以下新的加密操作符。每个操作码在 sigops 预算中计为 50。
OP_SUCCESS227
定义为 OP_ECMULSCALARVERIFY
,它从堆栈中弹出三个元素,如下所述:1) 一个 32 字节的大端、无符号标量 k
。2) 压缩的 EC 点 P
,以及 3) 压缩的 EC 点 Q
。如果 P
、Q
无效或 k
不是 32 字节并且超出 secp256k1 曲线阶数,则中止。如果 Q != k*P
,则中止。OP_SUCCESS228
定义为 OP_TWEAKVERIFY
,具有以下语义:弹出以下三个元素:1) 32 字节的仅 X 内部密钥 P
,2) 一个 32 字节的大端、无符号标量 k
,以及 3) 33 字节的压缩点 Q
。如果 P
、Q
无效或 k
不是 32 字节并且超出 secp256k1 曲线阶数,则中止。如果 Q != P + k*G
,其中 G
是 secp256k1 的生成器,则中止。对现有操作码的更改:
OP_CHECKSIGFROMSTACK
和 OP_CHECKSIGFROMSTACKVERIFY
以在见证程序为 v1 时遵循 bip340 的语义。更详细地说,操作码弹出三个元素堆栈 1) 32 字节的 pk
仅 X 公钥 2) 可变长度消息 msg
和 3) 64 字节的 Schnorr 签名 sig
。令 res = BIP340_verify(pk, msg, sig)
,其中 BIP340_verify
被定义为 elements 在这里。如果操作码是 OP_CHECKSIGFROMSTACKVERIFY
,如果验证失败,则中止。OP_CHECKSIGFROMSTACK
,如果提供了一个空签名,则 push 0
,如果验证成功,则 push 1
。如果提供了未能通过验证的非空签名,则中止。OP_CHECKSIGFROMSTACK
和 OP_CHECKSIGFROMSTACKVERIFY
在 sigops 预算中都计为 50。OP_PUSHCURRENTINPUTINDEX
可以与 OP_INSPECTINPUTXX
结合使用,以获取有关堆栈上所花费输入的信息wtxid
中,因此无法进行自省。
- 原文链接: github.com/ElementsProje...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!