BIP-0173:带有校验和的Base32格式“Bech32”以及使用它的原生隔离见证输出地址的标准

  • ajtowns
  • 发布于 2025-04-06 15:37
  • 阅读 22

该文档提出了一个带有校验和的Base32格式“Bech32”,以及使用它的原生隔离见证输出地址的标准。Bech32格式旨在改善比特币地址的用户体验,提高错误检测能力,并优化QR码的效率。它通过使用优化的字符集和BCH码校验和来实现这些目标,适用于主网和测试网。

跳到内容

ajtowns/ bips 公开

bitcoin/bips 派生

折叠文件树

文件

bip-anyprevout

搜索此仓库

/

bip-0173.mediawiki

复制路径

BlameMore 文件操作

BlameMore 文件操作

最新提交

hebastohebasto

BIP 173: 删除重复的 'the'

2019年7月18日

39a23b7 · 2019年7月18日

历史

历史

打开提交详情

查看此文件的提交历史。

405 行 (332 loc) · 19.9 KB

/

bip-0173.mediawiki

顶部

文件元数据和控件

  • 预览

  • 代码

  • Blame

405 行 (332 loc) · 19.9 KB

原始

复制原始文件

下载原始文件

大纲

编辑和原始操作

  BIP: 173
  Layer: Applications
  Title: Base32 address format for native v0-16 witness outputs
  Author: Pieter Wuille <pieter.wuille@gmail.com>
          Greg Maxwell <greg@xiph.org>
  Comments-Summary: No comments yet.
  Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0173
  Status: Final
  Type: Informational
  Created: 2017-03-20
  License: BSD-2-Clause
  Replaces: 142
## 目录<br>永久链接:目录<br>- 引言 <br> - 摘要<br> - 版权<br> - 动机<br> - 示例<br>- 规范 <br> - Bech32<br> - Segwit 地址格式<br> - 兼容性<br>- 原理<br>- 参考实现<br>- 已注册的人类可读前缀<br>- 附录 <br> - 测试向量<br> - 校验和设计<br>- 致谢

引言

永久链接:引言

摘要

永久链接:摘要

本文档提出了一种带有校验和的 base32 格式 “Bech32”,以及使用它的原生隔离见证输出地址的标准。

版权

永久链接:版权

此 BIP 基于 2-clause BSD 许可。

动机

永久链接:动机

在大部分历史中,比特币依赖于带有截断的双 SHA256 校验和的 base58 地址。它们是最初软件的一部分,并且它们的范围在 BIP13 中针对 Pay-to-script-hash ( P2SH) 进行了扩展。然而,字符集和校验和算法都存在局限性:

  • Base58 在二维码中需要大量空间,因为它无法使用字母数字模式
  • base58 中的混合大小写使得可靠地写下、在移动键盘上输入或大声读出变得不方便。
  • 双 SHA256 校验和速度慢,并且没有错误检测保证。
  • 大多数关于错误检测码的研究仅适用于字符集大小为 素数幂 的情况,而 58 不是。
  • Base58 解码复杂且相对较慢。

隔离见证提议中包含了一类新的输出(见证程序,参见 BIP141),以及它的两个实例(“P2WPKH” 和 “P2WSH”,参见 BIP143)。通过嵌入到 P2SH 输出中,旧客户端可以间接使用它们的功能,但是为了获得最佳效率和安全性,最好直接使用它。在本文档中,我们提出了一种新的地址格式,用于原生见证输出(当前和未来版本)。

这取代了 BIP142,并且之前在 此处 进行了讨论(总结 在此处)。

示例

永久链接:示例

所有示例都使用公钥 0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798。P2WSH 示例使用 key OP_CHECKSIG 作为脚本。

  • Mainnet P2WPKH: bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
  • Testnet P2WPKH: tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx
  • Mainnet P2WSH: bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3
  • Testnet P2WSH: tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7

规范

永久链接:规范

我们首先描述通用的带有校验和的 base32[ 1] 格式,称为 Bech32,然后使用它来定义隔离见证地址。

Bech32

永久链接:Bech32

一个 Bech32[ 2] 字符串最多 90 个字符,由以下组成:

  • 人类可读部分,旨在传达数据类型或与读者相关的任何其他内容。此部分必须包含 1 到 83 个 US-ASCII 字符,每个字符的值在 [33-126] 范围内。HRP 的有效性可能会受到特定应用程序的进一步限制。
  • 分隔符,始终为 “1”。如果允许在人类可读部分中使用 “1”,则字符串中的最后一个 “1” 是分隔符[ 3]。
  • 数据部分,至少 6 个字符长,并且仅包含字母数字字符,不包括 “1”、“b”、“i” 和 “o”[ 4]。
0 1 2 3 4 5 6 7
+0 q p z r y 9 x 8
+8 g f 2 t v d w 0
+16 s 3 j n 5 4 k h
+24 c e 6 m u a 7 l

校验和

数据部分的最后六个字符构成校验和,并且不包含任何信息。有效的字符串必须通过以下 Python3 代码段指定的有效性标准。当参数为:

  • hrp: 人类可读部分,作为字符串
  • data: 数据部分,作为整数列表,表示使用上表转换后的字符

时,函数 bech32_verify_checksum 必须返回 true。

def bech32_polymod(values):
  GEN = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
  chk = 1
  for v in values:
    b = (chk >> 25)
    chk = (chk & 0x1ffffff) &lt;&lt; 5 ^ v
    for i in range(5):
      chk ^= GEN[i] if ((b >> i) & 1) else 0
  return chk

def bech32_hrp_expand(s):
  return [ord(x) >> 5 for x in s] + [0] + [ord(x) & 31 for x in s]

def bech32_verify_checksum(hrp, data):
  return bech32_polymod(bech32_hrp_expand(hrp) + data) == 1

这实现了一个 BCH 码,保证检测到最多影响4个字符的任何错误,并且检测不到更多错误的可能性小于 1 in 109。有关属性的更多详细信息,请参见校验和设计附录。人类可读部分的处理方式是,首先将每个字符的 US-ASCII 值的高位输入到校验和计算中,然后是一个零,然后是每个字符的低位[ 5]。

要构造一个有效的校验和,给定人类可读部分和数据部分字符的(非校验和)值,可以使用以下代码:

def bech32_create_checksum(hrp, data):
  values = bech32_hrp_expand(hrp) + data
  polymod = bech32_polymod(values + [0,0,0,0,0,0]) ^ 1
  return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]

纠错

这些 BCH 码的属性之一是它们可用于纠错。纠错的一个不幸的副作用是它会削弱错误检测:纠正会将无效输入更改为有效输入,但是如果进行了多次错误,则有效输入可能不是正确的输入。使用不正确但有效的输入可能会导致资金无法挽回地丢失。因此,实现不应实现超出可能向用户建议在字符串中找到错误的位置的纠正,而不建议进行纠正。

大写/小写

小写形式用于确定字符的校验和目的值。

编码器必须始终输出全小写的 Bech32 字符串。 如果需要编码结果的大写版本(例如,为了演示目的或使用二维码),则可以在编码过程之外执行大写程序。

解码器不得接受某些字符为大写而某些字符为小写的字符串(此类字符串称为混合大小写字符串)。

为了演示,小写通常是首选,但是在二维码内部应使用大写,因为这些允许使用字母数字模式,该模式比普通的 字节模式 紧凑 45%。

Segwit 地址格式

永久链接:Segwit 地址格式

一个 segwit 地址[ 6] 是以下内容的 Bech32 编码:

  • 人类可读部分,主网为 “bc”[ 7],测试网为 “tb”[ 8]。
  • 数据部分值:
    • 1 字节:见证版本
    • 将 2 到 40 字节的见证程序(如 BIP141 中定义的)转换为 base32:
    • 从见证程序的位开始,每个字节的最高有效位优先。
    • 将这些位重新排列成 5 个一组,并在需要时在末尾用零填充。
    • 使用上表将这些位转换为字符。

解码

解释 segwit 地址的软件:

  • 必须验证人类可读部分对于主网是否为 “bc”,对于测试网是否为 “tb”。
  • 必须验证第一个解码的数据值(见证版本)是否在 0 到 16 之间(包括 0 和 16)。
  • 将剩余数据转换为字节:
    • 将值转换为 5 位,最高有效位优先。
    • 将这些位重新排列成 8 位一组。末尾的任何不完整组必须为 4 位或更少,必须全部为零,并且被丢弃。
    • 必须有 2 到 40 组,这些组被解释为见证程序的字节。

解码器强制执行对见证程序的已知长度限制。例如,BIP141 指定如果版本字节为 0,但见证程序既不是 20 字节也不是 32 字节,则脚本必须失败。

由于之前的规则,地址始终在 14 到 74 个字符之间,并且它们的长度模 8 不能为 0、3 或 5。 版本 0 见证地址始终为 42 或 62 个字符,但是实现必须允许使用任何版本。

在将地址转换为 scriptPubkey 时,实现应特别注意,其中见证版本 n 存储为 OP_n。OP_0 编码为 0x00,但 OP_1 到 OP_16 编码为 0x51 到 0x60(十进制 81 到 96)。如果将 bech32 地址转换为不正确的 scriptPubKey,则结果很可能变得无法花费或不安全。

兼容性

永久链接:兼容性

只有新的软件才能使用这些地址,并且仅适用于具有启用 segwit 的新软件的接收者。在所有其他情况下,可以使用 P2SH 或 P2PKH 地址。

原理

永久链接:原理

  1. ^ 为什么使用 base32? 缺少混合大小写使其在朗读或放入二维码中更加高效。它确实会使长度增加 15%,但是在复制粘贴地址时无关紧要。
  2. ^ 为什么称其为 Bech32? “Bech” 包含字符 BCH(使用的错误检测算法),听起来有点像 “base”。
  3. ^ 为什么在地址中包含分隔符? 这样,人类可读部分与数据部分明确分开,避免了与其他共享前缀的人类可读部分的潜在冲突。它还允许我们避免对人类可读部分进行字符集限制。分隔符为 1,因为使用非字母数字字符会使复制粘贴地址复杂化(在某些应用程序中无法双击选择)。因此,选择了正常字符集之外的字母数字字符。
  4. ^ 为什么不使用现有的字符集,例如 RFC3548z-base-32?根据 视觉相似性数据,选择字符集以最大程度地减少歧义,并且选择排序以最大程度地减少在超过 1 位上不同的相似字符对的数量(根据相同的数据)。由于选择校验和是为了最大程度地提高对少量位错误的检测能力,因此此选择在某些错误模型下可以提高其性能。
  5. ^ 为什么首先处理人类可读部分的高位? 这导致实际的校验和数据为 [high] 0 [low] [data]。这意味着在假设对人类可读部分的错误仅更改低 5 位(例如,将字母字符更改为另一个字母字符)的情况下,错误仅限于 [low] [data] 部分,该部分最多为 89 个字符,因此所有错误检测属性(请参见附录)仍然适用。
  6. ^ 为什么不制作一种对所有 scriptPubKeys 通用的地址格式? 这将导致对现有 scriptPubKey 类型的地址产生混淆。此外,如果引入了与 scriptPubKeys 没有一一对应的地址(例如基于 ECDH 的地址),则可以使用旧地址格式重新解释生成的 scriptPubKeys,如果将比特币发送到这些地址,则会导致资金损失。
  7. ^ 为什么使用 “bc” 作为人类可读部分而不是 “btc”? “bc” 更短。
  8. ^ 为什么对测试网使用 “tb” 作为人类可读部分? 选择它是为了与主网对应部分具有相同的长度(以简化实现对长度的假设),但仍然在视觉上有所不同。

参考实现

永久链接:参考实现

注册的人类可读前缀

永久链接:注册的人类可读前缀

SatoshiLabs 维护着一个完整的已注册人类可读部分列表,用于其他加密货币:

SLIP-0173:BIP-0173 的已注册人类可读部分

附录

永久链接:附录

测试向量

永久链接:测试向量

以下字符串是有效的 Bech32:

  • A12UEL5L
  • a12uel5l
  • an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs
  • abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw
  • 11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j
  • split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w
  • ?1ezyfcl 警告:在转换为 US-ASCII 期间,某些编码器可能会将无法映射的字符设置为有效的 US-ASCII 字符,例如 “?”。例如:
>>> bech32_encode('\x80'.encode('ascii', 'replace').decode('ascii'), [])
'?1ezyfcl'

以下字符串不是有效的 Bech32(带有无效原因):

  • 0x20 + 1nwldj5: HRP 字符超出范围
  • 0x7F + 1axkwrx: HRP 字符超出范围
  • 0x80 + 1eym55h: HRP 字符超出范围
  • an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx: 超过整体最大长度
  • pzry9x0s0muk: 没有分隔符字符
  • 1pzry9x0s0muk: 空 HRP
  • x1b4n0q5v: 无效的数据字符
  • li1dgmt3: 校验和太短
  • de1lg7wt + 0xFF: 校验和中的无效字符
  • A1G7SGD8: 使用 HRP 的大写形式计算的校验和
  • 10a06t8: 空 HRP
  • 1qzzfhee: 空 HRP

以下列表给出了有效的 segwit 地址以及它们转换为十六进制的 scriptPubKey。

  • BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4: 0014751e76e8199196d454941c45d1b3a323f1433bd6
  • tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7: 00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262
  • bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx: 5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6
  • BC1SW50QA3JX3S: 6002751e
  • bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj: 5210751e76e8199196d454941c45d1b3a323
  • tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy: 0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433

以下列表给出了无效的 segwit 地址及其无效原因。

  • tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty: 无效的人类可读部分
  • bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5: 无效的校验和
  • BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2: 无效的见证版本
  • bc1rw5uspcuh: 无效的程序长度
  • bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90: 无效的程序长度
  • BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P: 见证版本 0 的无效程序长度(根据 BIP141)
  • tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7: 混合大小写
  • bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du: 超过 4 位的零填充
  • tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv: 8 到 5 转换中的非零填充
  • bc1gmk9yu: 空数据段

校验和设计

永久链接:校验和设计

设计选择

BCH 码可以在任何素数幂字母表上构造,并且可以选择在大小和错误检测能力之间取得良好的权衡。尽管围绕 BCH 码的大多数工作都使用二进制字母表,但这不是必需的。这使得它们比 CRC 码 更适合我们的用例。与 [里德-所罗门码](https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_这里选择的具体代码是以下的结果

  • 从一个详尽的 159605 个 BCH 代码列表中开始,这些代码旨在检测长度高达 93、151、165、341、1023 和 1057 的 3 个或 4 个错误。
  • 从这些代码中,要求检测长度高达 71 的 4 个错误,从而得到剩余的 28825 个代码。
  • 从这些代码中,选择对于 5 个字符的错误具有最佳最坏情况窗口的代码,从而得到剩余的 310 个代码。
  • 从这些代码中,选择检测少量 bit 错误的可能性最低的代码。

由于朴素搜索将需要超过 6.5 * 1019 次校验和评估,因此使用了冲突搜索方法进行分析。该代码可以在这里找到。

属性

下表总结了检测失败的可能性(以十亿分之一的倍数表示)。

窗口长度 错误字符数
长度 描述 ≤4 5 6 7 8 ≥9
8 最长检测 6 个错误 0 1.127 0.909 n/a
18 最长检测 5 个错误 0 0.965 0.929 0.932 0.931
19 6 个错误的最坏情况 0 0.093 0.972 0.928 0.931
39 P2WPKH 地址的长度 0 0.756 0.935 0.932 0.931
59 P2WSH 地址的长度 0 0.805 0.933 0.931
71 40 字节程序地址的长度 0 0.830 0.934 0.931
89 最长检测 4 个错误 0 0.867 0.933 0.931

这意味着,当 5 个更改的字符随机分布在 P2WPKH 地址的 39 个字符中时,有 十亿分之 0.756 的可能性不会被检测到。当这 5 个更改随机发生在 19 个字符的窗口中时,该可能性会降至 十亿分之 0.093。随着错误数量的增加,该可能性收敛于 1/230 = 十亿分之 0.931

即使选择的代码在多达 1023 个字符的情况下表现相当不错,但对于超过 89 个字符的长度,其他设计是更可取的(不包括分隔符)。

致谢

永久链接:致谢

本文档的灵感来自 Rusty Russell 的地址提案、Mark Friedenbach 的 base32 提案,并得到了 Luke Dashjr、Johnson Lau、Eric Lombrozo、Peter Todd 和其他各种审阅者的投入。

  • 原文链接: github.com/ajtowns/bips/...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
ajtowns
ajtowns
江湖只有他的大名,没有他的介绍。