MSTR Cat

区块链/等级 IV · 深入协议/4.1 Script/课程 2

标准脚本:P2PKH和P2SH

将币锁定到密钥,再锁定到任意脚本的哈希

材料区块浏览器界面(例如 Blockstream.info 或 mempool.space)SHA-256与RIPEMD-160哈希工具十六进制对照表一款能够查看原始交易十六进制数据的区块浏览器

好奇

  1. 为什么比特币要将币锁定在哈希值上,而不是密钥本身?
  2. 四行脚本如何在一次执行中同时验证所有权与授权?
  3. 在比特币网络发展的八年多时间里,究竟是什么让 P2PKH 成为了默认的地址格式?

探索

    部分 I支付到公钥哈希(P2PKH)

  1. 创世区块只包含“支付到公钥”(P2PK)输出。这类脚本将完整的公钥(2009年时为65字节的未压缩公钥)直接放在输出中,在任何花费发生之前即可见,并且使输出体积较大。P2PKH 同样存在于2009年的原始软件中,用于普通的地址支付,它存储的是20字节的哈希值,从而在币被花费之前隐藏公钥。
  2. 锁定脚本为 `OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG`。执行开始时,栈上是花费方提供的数据:先是签名,栈顶是公钥。引擎复制该公钥,用 RIPEMD-160(SHA256(key)) 对其进行哈希,并将结果与存储的哈希值比较。如果两者一致,`OP_EQUALVERIFY` 通过;否则执行立即终止。
  3. 一旦哈希校验成功,`OP_CHECKSIG`就会使用已公开的公钥及交易数据来验证 ECDSA 签名。这种双重机制确保只有对应私钥的持有者才能解锁资金。该输出脚本的总长度为 25 字节,其简洁的结构成为了以 “1” 开头的传统地址的基础。
  4. 在比特币历史的大部分时间里,P2PKH 一直是普通支付中最常见的输出类型;2017年8月 SegWit 在区块高度481,824激活后,它仍保持这一地位多年,因为原生 SegWit 的普及是渐进的。它的成功在于简洁与兼容:除了原始协议规则之外,不需要任何共识升级。每个节点都能独立验证这些脚本,无需复杂的状态跟踪,这使它成为比特币早期发展阶段通用转账中最稳健的输出类型。
  5. 该地址格式采用 Base58Check 编码,其中包含一个四字节的校验和用于检测输入错误。只要有一个字符输入错误,校验和几乎必然会出错,从而导致钱包拒绝接受该地址。正是这种冗余设计,使得 P2PKH 即便在技术上较为复杂,依然易于使用,从而弥合了加密安全性与人类操作便捷性之间的差距。
  6. 打开区块浏览器,找到任意一笔输入引用了以“1”开头地址的交易。查看 `scriptSig` 字段:其中先是签名,后面是公钥的十六进制字符串。将该公钥与被引用输出的 `scriptPubKey` 中的20字节哈希值进行比较。对该公钥先计算 SHA-256、再计算 RIPEMD-160,即可得到存储的哈希值,从而确认二者的关联。
  7. 部分 II支付到脚本哈希(P2SH)

  8. 2012年之前,使用 5-of-5 多签这类复杂脚本时,必须将整段锁定代码直接放入输出中。这使输出体积变大,而相应的手续费由发送方承担。它还会把每位参与者的公钥和具体的签名要求暴露给任何观察区块链的人。发送方在发送前必须知道目标的确切结构,这给需要灵活安全配置的企业资金库或交易所带来了麻烦。
  9. 2012年初,Gavin Andresen 提出 BIP16 来解决这一问题。它允许输出只包含脚本的 HASH160 摘要,而非脚本本身。输出脚本缩小到23字节,略小于 P2PKH 的25字节。发送方不再需要知道花费条件,只需向一个哈希付款。复杂性完全转移到了花费这些币的人身上。
  10. 2012年4月,BIP16的启用引发了诸多争议。Luke Dashjr提出了另一种方案——BIP17,该方案采用了不同的操作码和编码方式。在开发者群体中,关于应采用哪种方案的争论愈发激烈。在矿工们表示支持之后,BIP16于2012年4月正式被启用,并成为封装复杂脚本的标准方式。
  11. 花费一个支付到脚本哈希的输出分为两个阶段。首先,花费方将完整的赎回脚本压入栈中。节点检查该脚本的 HASH160 是否与输出中的哈希值一致。如果不一致,执行立即失败。如果一致,节点就会用栈上剩余的数据执行这个被公开的赎回脚本,以验证实际的花费条件。
  12. 这一设计有个隐患:付款之前没有人能检查赎回脚本,因为链上只有它的哈希值。如果接收方的软件生成了有缺陷的脚本,或者脚本丢失,那么支付到该地址的币可能永远无法被花费。
  13. 2017年8月 SegWit 激活时,P2SH 充当了兼容性桥梁。用户可以将新的见证脚本封装在 P2SH 信封中,生成仍以“3”开头的“嵌套”地址。无法处理较新 bech32 地址的旧钱包仍可向 SegWit 用户转账,而支持 SegWit 的接收方在花费时可享受手续费折扣。如今,虽然出于效率考虑更推荐使用原生 SegWit,但 P2SH 仍是处理复杂合约和保持旧版兼容性的重要机制。

关键事实

  • P2PKH 输出存储的是公钥的 20 字节 HASH160 值,而非完整的公钥。
  • 该锁定脚本 `OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG` 的长度恰好为25字节。
  • 进行支出时,必须同时提供有效的 ECDSA 签名以及与存储的哈希值匹配的公钥。
  • 传统 P2PKH 地址以“1”开头,采用带校验和的 Base58Check 编码。
  • 在 SegWit 实施之前和之后,数年来 P2PKH 都是普通支付中最常用的输出类型。
  • 如果 `OP_EQUALVERIFY` 检测到哈希后的密钥与存储的哈希值不一致,执行将立即失败。
  • BIP16 由 Gavin Andresen 提出,并于2012年4月激活。
  • P2SH 输出脚本仅包含赎回脚本的 HASH160 值,长度为 23 字节。
  • 在2012年1月至3月的激烈争论中,Luke Dashjr 的 BIP17 与 BIP16 相互竞争。
  • 根据共识规则,赎回脚本最长为520字节,即单个压栈元素的最大大小。
  • P2SH地址采用Base58Check编码,且始终以数字“3”开头。
  • 嵌套式 SegWit(通常是 P2SH-P2WPKH)使得旧版钱包能够在 2017 年之后向使用 SegWit 的用户进行支付。

练习 九、六、三、一

9收集在比特币区块链上找出9个花费 P2PKH 地址资金的真实交易输入,记录其区块高度、scriptSig 中公开的公钥,以及对应输出中的哈希值。
6归类将这9个输入按时期分为6组:2009-2011年、2012-2013年、2014-2015年、2016-2017年、2018-2021年、2022年及以后。注意区分压缩公钥与未压缩公钥。
3提炼将这些分组归纳为3个不同的原因,解释为何在2017年后已有更高效的输出类型可用的情况下,P2PKH 依然保持主导地位。
1凝结写一句话,说明 `OP_EQUALVERIFY` 如何在签名验证之前将公钥转化为具有约束力的承诺。

事实核查

日期、数字及数据均依据下方列出的已发表资料进行核实。

在互动学院中打开 →

EN PT ES JA KO RU DE FR MS