私钥 → P2SH-P2WPKH 地址(嵌套 SegWit)
3… 嵌套 SegWit 地址:先哈希压缩公钥,把那 20 字节包成 0x0014‖程序,再对这 22 字节脚本求一次哈希,最后用版本字节 0x05 做 Base58Check。一共六层,全部展示。
请在上方输入内容后点击「转换」。不知道填什么?点「填入示例」即可载入占位符里的演示数据。
本页计算了什么
这是嵌套 SegWit(nested SegWit)地址:把 SegWit 的锁定逻辑藏进一层 P2SH 外壳里,从而得到
一个看起来平平无奇的 3… 地址。它一共有六层,本页把每一层都打印出来:
由于内层值被哈希了两次 —— 一次作为公钥,一次作为 redeem script —— 这类地址恰好夹在传统 P2PKH 与原生 SegWit 之间,位置有些尴尬。文末的对比表会把这份代价量化出来。
1. P2SH:支付给脚本哈希
P2SH 由 BIP16 引入,于 2012 年 4 月 1 日激活。在它之前,发送方必须把收款方的完整花费条件
写进输出里:比如一个多重签名地址,就意味着要把整段
2 <公钥> <公钥> <公钥> 3 OP_CHECKMULTISIG 程序 —— 几百字节 —— 塞进交易,并且
为它付费。
P2SH 把这件事倒了过来:输出只承诺一个脚本的哈希,脚本本身要等到花费时才公开:
P2SH 的 scriptPubKey: OP_HASH160 <20 字节脚本哈希> OP_EQUAL
花费者稍后提供: <……完整的 redeem script……>
让它安全成立的规则才是重点所在:
- 花费者的解锁脚本里必须包含哈希能对上的redeem script,以及满足该脚本所需的其它数据。
- 解释器对提供的脚本求哈希,与
OP_EQUAL比较,只有通过之后,才把它当作一段独立程序来执行。 - redeem script 不在地址里。地址只是一个哈希,因此它无法告诉你花费条件是什么 —— 这个细节 对整个 SegWit 设计至关重要。
| 传统的「支付给脚本」 | P2SH | |
|---|---|---|
| 条件写在哪里 | 完整写在发送方的输出里 | 只写哈希;脚本到花费时才出现 |
| 3-of-3 多签的 scriptPubKey 大小 | 约 105 字节 | 永远 23 字节 |
| 那段大脚本由谁付费 | 发送方(收款时就付) | 花费方(花钱时才付) |
| 主网地址前缀 | — | 3…(版本字节 0x05) |
BIP141 在 P2SH 之上追加了一条共识规则:当一笔 P2SH 花费的解锁脚本恰好只包含一次压入操作,而压入的字节看起来
像一个合法的 witness 程序(一个版本字节加 2–40 字节程序)时,这段脚本不会按传统方式执行,而是改为用
该交易的 witness 去对照这个程序做验证。正是这一条规则让嵌套 SegWit 成为可能 —— 同样一个 3…
形式的输出,既可以承载传统 redeem script,也可以承载 witness 程序。
2. SegWit 改变了什么
SegWit(隔离见证,BIP141,2017 年 8 月 24 日激活)把签名数据 —— 也就是 witness —— 移出了计算交易 ID 的结构,并给它一种更便宜的计量单位:
| SegWit 之前 | SegWit 之后 |
|---|---|
| 签名位于输入的 scriptSig 里,而它参与 txid 哈希 | 签名位于独立的 witness 字段,不参与 txid |
| 任何第三方都能改动签名的编码方式从而改变 txid(可塑性) | 确认前 txid 就稳定 —— 这是闪电网络的前提 |
| 只有一种计量:1 字节 = 1 字节区块空间 | 两种计量:普通字节 4 个重量单位,witness 字节 1 个 |
| 1 MB 区块上限 | 4 000 000 重量上限 ≈ 可容纳约 4 倍的交易 |
| 脚本哈希放在 scriptSig 里 | witness 程序放在 scriptPubKey 里:OP_0 <20 或 32 字节> |
体积计量是你能在手续费上直接感受到的那部分。重量以重量单位(WU)计,有效体积以虚拟字节(vB)计:
因此每个 witness 字节的成本只有基础层字节的四分之一,这正是 SegWit 输入更便宜的原因。原生 P2WPKH 的输出就是
OP_0 <20 字节 hash160> —— 22 字节,没有 OP_DUP、没有 OP_CHECKSIG,
除了「witness 必须满足这个程序」之外没有任何要执行的东西。
旧节点仍然会把 witness 输出看作「谁都能花」,并且会乐意接受一笔完全忽略 witness 的交易。witness 规则只由升级 过的节点执行,所以 SegWit 花费要按一套更严格的标志集合来判定:例如非压缩公钥就不允许出现在 witness 程序里 (见「常见错误」一节)。
3. 嵌套 SegWit 到底为什么存在
SegWit 的原生地址格式是 bech32:bc1q…。在 2017 年,那是一种老钱包、交易所和支付处理商根本不认识的
新字符串格式 —— 许多系统会直接判为非法,有些干脆拒绝向它转账。
嵌套 SegWit(3…)解决的是部署问题,而不是密码学问题:
3…地址与普通的 P2SH 地址无法区分。任何早就能向多签3…地址付款 的钱包,无需任何升级就能向 SegWit 的3…地址付款 —— 发送方根本不必理解 witness。- 收款方拿到了 SegWit 的好处:签名可塑性消失,花费时享受重量折扣。(手续费由花费方支付, 所以这份节省落在收款方手里。)
- 代价是真实的:外壳让 scriptSig 多出 22 字节的 redeem script 和一次额外哈希,因此嵌套 SegWit 比原生
bc1q…贵。BIP49 为此规范了派生路径m/49'/0'/0'/0/i,好让钱包能够确定性地恢复 这类地址。
它让整个生态可以渐进式采纳 SegWit:收款方先升级,发送方什么时候跟上都行。今天仍在维护的钱包普遍支持
bech32,新钱包默认使用 bc1q…;嵌套 SegWit 主要还留在 2017–2019 年恢复出来的钱包,以及过渡期
采用了它的服务里。
4. 逐字节看 redeem script
这段 redeem script 是单密钥场景下最小的合法 witness 程序 —— 22 字节,无一多余:
| 偏移 | 长度 | 字节 | 含义 |
|---|---|---|---|
| 0 | 1 字节 | 0x00 | OP_0 —— 压入一个空数组,同时充当 witness 版本 0 |
| 1 | 1 字节 | 0x14 | 压入接下来的 0x14 = 20 字节 |
| 2 – 21 | 20 字节 | 21f57b6d…9012 | witness 程序本体:压缩公钥的 hash160 |
| — | 共 22 字节 | 001421f57b6debcfc5b67182dfb4af1641f0a8189012 | 这就是被哈希成 P2SH 脚本哈希的东西 |
有两个细节值得注意。第一,版本字节是 OP_0,并不是一个单独的「版本字段」—— witness 版本是用一个小的
脚本数字编码的,这也正是 v1(Taproot)以 OP_1(0x51)开头、并改用 bech32m 的原因。
第二,这 22 字节的字符串与原生 P2WPKH 的 scriptPubKey 完全相同:同一个程序被两种方式使用,一次直接放进
输出,一次包在 P2SH 哈希里面。
redeem script(22 字节) = 00 14 21f57b6d…9012
P2SH 的 scriptPubKey(23 字节) = a9 14 823333d5…8b6e 87
│ │ └─ 20 字节 hash160(redeem script)
│ └──── 压入 20 字节
└─────── OP_HASH160 … OP_EQUAL(87)
5. 双重哈希,以及它的代价
原生 P2WPKH 的链条是:对公钥哈希一次,把 20 字节做 bech32 编码。嵌套地址的链条则是:对公钥哈希一次,拼出 22 字节脚本,再哈希一次,然后把第二个哈希做 Base58Check 编码。两次哈希、两份不同输入,得到两个彼此无关的 20 字节值 —— 而地址携带的是第二个。
| 层 | 输入 | 输出 | 演示取值 |
|---|---|---|---|
| 哈希 1 | 33 字节压缩公钥 | 20 字节 witness 程序 | 21f57b6debcfc5b67182dfb4af1641f0a8189012 |
| 脚本 | 0x0014 ‖ 程序 | 22 字节 redeem script | 001421f57b6debcfc5b67182dfb4af1641f0a8189012 |
| 哈希 2 | 那 22 字节 redeem script | 20 字节脚本哈希 | 823333d5fd23a83661e8e47629552c4a5bfc8b6e |
| 编码 | 0x05 ‖ 脚本哈希 ‖ 校验和 | 25 字节 → Base58Check | 3DZT76KyKyc5zkzvLugP8umgt4RPY4XPQw |
花费时,scriptSig 必须携带这 22 字节脚本(1 字节压入操作码 + 22 字节 = 23 字节),网络才能对它求哈希、看到 witness 程序。这 23 字节落在交易的基础部分,每字节要付 4 个重量单位,这也正是嵌套 SegWit 不如原生便宜的 全部原因:
| 输入类型 | 基础字节 | scriptSig | witness 字节 | 重量(WU) | 体积(vB) | 按 10 sat/vB 的手续费 |
|---|---|---|---|---|---|---|
| P2PKH(传统) | 36 + 1 + 4 = 41 | 107 | 0 | 592 | 148 | 1480 sat |
| P2SH-P2WPKH(本页) | 36 + 1 + 4 = 41 | 23 | 108 | 364 | 91 | 910 sat |
| P2WPKH(原生) | 36 + 1 + 4 = 41 | 0 | 108 | 272 | 68 | 680 sat |
所以嵌套 SegWit 相比传统 P2PKH 省下约 57 vB(38%),但仍比原生 bech32 多付 23 vB(25%)。输出侧两种 SegWit 都 更小,因为 scriptPubKey 更短:P2SH 输出 32 字节、P2WPKH 输出 31 字节、P2PKH 输出 34 字节。
6. 对比表
| P2PKH | P2SH-P2WPKH | P2WPKH | |
|---|---|---|---|
| 主网地址 | 1… | 3… | bc1q… |
| 版本字节 / 格式 | 0x00,Base58Check | 0x05,Base58Check | witness v0,bech32 |
| 地址长度 | 34 字符 | 34 字符 | 42 字符 |
| scriptPubKey | OP_DUP OP_HASH160 <h> OP_EQUALVERIFY OP_CHECKSIG | OP_HASH160 <h'> OP_EQUAL | OP_0 <h> |
| scriptPubKey 大小 | 25 字节 | 23 字节 | 22 字节 |
| 地址承诺的是 | hash160(公钥) | hash160(0x0014 ‖ hash160(公钥)) | hash160(公钥) |
| 花费时的 scriptSig | 签名 + 公钥(约 107 字节) | 压入 22 字节 redeem script(23 字节) | 空 |
| 抗可塑性 | 否 | 是 | 是 |
| 输入体积 | 148 vB | 91 vB | 68 vB |
| 发送方需不需要懂 bech32 | 不需要 | 不需要 | 需要 |
| 典型时期 | 2009 – 至今 | 2017 – 2019 过渡期 | 2017 – 至今 |
7. 用演示私钥做的实例演算
| 步骤 | 取值 |
|---|---|
| 私钥 k | 0824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca |
| 压缩公钥(33 字节) | 02ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80 |
| hash160 = witness 程序(20 字节) | 21f57b6debcfc5b67182dfb4af1641f0a8189012 |
| redeem script(22 字节) | 001421f57b6debcfc5b67182dfb4af1641f0a8189012 |
| redeem script 的 SHA-256 | a78eb2472f4853354a86bd16be63eb2f5c2a3511b74a40073b3e1973135ec2e6 |
| redeem script 的 hash160(20 字节) | 823333d5fd23a83661e8e47629552c4a5bfc8b6e |
载荷 = 05 ‖ 脚本哈希(21 字节) | 05823333d5fd23a83661e8e47629552c4a5bfc8b6e |
| 校验和(4 字节) | acbfef44 |
| 被编码的 25 字节 | 05823333d5fd23a83661e8e47629552c4a5bfc8b6eacbfef44 |
| P2SH-P2WPKH 地址 | 3DZT76KyKyc5zkzvLugP8umgt4RPY4XPQw |
| 支付它的 scriptPubKey(23 字节) | a914823333d5fd23a83661e8e47629552c4a5bfc8b6e87 |
| 同一私钥的原生 SegWit 姊妹地址 | bc1qy86hkm0telzmvuvzm76279jp7z5p3yqjnaerk6 |
| 同一私钥的 P2PKH 姊妹地址 | 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT |
注意原生与嵌套这两个姊妹地址共用同一个 20 字节 witness 程序 21f57b6d…9012,却给出完全不同的
地址 —— 而且从外部看,scriptPubKey 也毫不相干。只有嵌套的那一个被包进了第二层哈希。
8. 这个地址不是什么
- 不是多签地址。
3…是 P2SH 前缀,多签钱包也用它。字符串里没有任何信息告诉你 隐藏的脚本是单密钥 witness 程序还是 2-of-3 多签。 - 并不自动比
bc1q…便宜。 它只相对传统 P2PKH 省钱。如果收款方钱包支持 bech32, 原生格式对所有人都更便宜、也更简单。 - 不能用来隐藏什么。 币被花掉时,redeem script 会公开在 scriptSig 里,witness 程序也出现在 witness 中。地址只是把透明性推迟到第一次花费;区块链是永远公开的。
- 恢复时不能与姊妹地址互换。 一个只推导
1…和bc1q…地址的钱包, 即使种子完全正确,也看不到躺在3…上的币。更麻烦的是,光看地址根本猜不出它是哪一种 P2SH —— 必须让钱包主动去派生嵌套 SegWit 地址。
witness 程序必须是 33 字节压缩公钥的哈希。若对 65 字节非压缩公钥求哈希再构造 3… 地址,会得到
一个看起来完全合法的字符串,但按标准性策略你无法花掉它。如果你正在清空一把 2009 年前后的密钥,请先推导出
压缩公钥 —— 这个区别的来龙去脉见非压缩地址页面。
9. 这一步在推导链上的位置
- 同一私钥的其它外壳:压缩 P2PKH、 非压缩 P2PKH、原生 P2WPKH、 Taproot P2TR。
- 不需要私钥即可拆解外壳:Base58Check 解码器会显示
0x05版本字节 和 20 字节脚本哈希。 - 解读内层程序:bech32 页面会展示同样的 20 字节作为 witness v0 出现在
bc1q…形式里。
10. 安全须知
谁看见了私钥,谁就能花掉由它派生的一切地址上的币 —— 3… 地址也不例外,因为钱包随时可以公开
redeem script。本服务器在本地用 PHP 计算且不做记录,但这条保证的边界就是运营者本身。真要管钱,请用离线工具或
硬件钱包。
- P2SH 隐藏的是花费条件,不是金额或地址。隐私来自每笔付款使用新地址,而不是来自这层外壳。
3…地址上的 4 字节 Base58Check 校验和能以 1 − 2-32 的概率抓住笔误;它不是签名, 防不住被替换的地址。- 在用助记词恢复之前,请先确认目标钱包确实会派生嵌套 SegWit 地址,再下「资金不见了」的结论。
11. 常见错误
- 以为
3…就代表多签。 2017 年以后,链上绝大多数3…地址都是单密钥 的嵌套 SegWit。 - 指望嵌套 SegWit 的手续费与 bech32 一样。 多出的 22 字节 redeem script 和第二次哈希,使它 严格比原生 SegWit 更贵。
- 把非压缩公钥的哈希当作 witness 程序。 地址看着合法,实际上花不出去。
- 把种子恢复到脚本类型列表不对的钱包。 BIP49(
m/49'/0'/0'/0/i)存在的意义就是让 嵌套地址可复现;只支持 BIP44 的钱包会显示为零。 - 以为 redeem script 在地址里。 并不在 —— 地址是一个哈希,脚本只在币移动时才出现。
12. 速查表
| 项目 | 取值 |
|---|---|
| 公式 | Base58Check(0x05 ‖ hash160(0x0014 ‖ hash160(压缩公钥))) |
| redeem script | 0x00 0x14 ‖ 20 字节 hash160(公钥) = 22 字节 |
| 脚本哈希 | 对这 22 字节做 hash160 |
| 版本字节 | 主网 0x05(3…),测试网 0xC4(2…) |
| 被编码的载荷 | 25 字节 = 1 + 20 + 4 |
| scriptPubKey | a914 <脚本哈希> 87 = 23 字节 |
| 花费时的输入体积 | 91 vB(P2PKH 148,P2WPKH 68) |
| 派生路径约定 | BIP49,m/49'/0'/0'/0/i |
| 演示地址 | 3DZT76KyKyc5zkzvLugP8umgt4RPY4XPQw |
| 抗可塑性 | 是 —— 签名在 witness 里,不在 txid 里 |