在 BSV 脚本中,将数据 0x01 送到栈上,似乎有两种做法:
- 直接使用操作码 OP_1,对应的脚本为 { 0x51 }。根据定义,OP_1 会将 0x01 送到栈顶
- 使用 pushdata 的方式,对应的脚本为 { 0x01 0x01 }。第一个 0x01 表示接下来的 1 字节数据(第二个 0x01)会被送到栈上
实际上,[2] 是错误的,因为它违反了“最小推送”(minimal push)规则。
- 推送空的字节序列,必须使用操作码 OP_0,即 { 0x00 }
- 推送 0x01 ~ 0x10,必须使用操作码 OP_1 ~ OP_16,即 { 0x51 } ~ { 0x60 }
- 推送 0x81,必须使用操作码 OP_1NEGATE,即 { 0x4f }
- 推送其他数据,根据定义使用对应的 pushdata 操作码
这个规则很简单,可以用一句话概括:针对 18 种要压栈的数据,特定的操作码让我们能在脚本里用更短的指令(1 字节)表达动作,不再需要使用 pushdata 的方式(2 字节)。
如果违反该规则,节点会报错:
64: non-mandatory-script-verify-flag (Data push larger than necessary) |
请注意,推送 0x00 不在这 18 个特例范围内,所以正确的脚本应该是 { 0x01 0x00 }。
另一个要注意的点是,在 OP_RETURN 输出里推送数据不受此规则限制,因为 OP_RETURN 操作码之后的脚本不会被执行。
特别感谢 @xhliu 的指点和帮助,其他参考资料如下:
代码实现:
def encode_pushdata(pushdata: bytes, minimal_push: bool = True) -> bytes: |