新人科普丨什么是比特币地址?

CN
PANews
关注
1年前

作者:SJORS PROVOOST

来源:https://sprovoost.nl/2022/11/10/what-is-a-bitcoin-address/

比特币地址不是比特币区块链的一部分,而是一种记号,比特币(钱包)软件用它来沟通将比特币发送至何处:要么是发给某个公钥(P2PK)、要么是某个公钥的哈希值(P2PKH)、脚本的哈希值(P2SH)、隔离见证公钥的哈希(P2WPKH),或者是隔离见证脚本的哈希(P2WSH)。地址中还包含一些关于其自身所属类型的元数据。

(译者注:比特币的地址类型会随着比特币网络的升级和脚本编写方式的标准化而不断增加。其实上面提到的地址类型,除了 P2PK 和 P2PKH 是随着比特币的初次发布就出现的,其余都是后来才出现的。现在,由于 Taproot 升级在 2021 年激活,比特币又多了一种地址类型 “P2TR”。)

比特币地址使用独有的编号系统来表达上述付款方式。本文将分别介绍这些互不相同的编号系统,并深入分析一般的比特币地址和 bech32 地址具备哪些优点。此外,我们还将解释第一版 bech32 地址所包含的那个(威胁程度较低的)漏洞从何而来,又是如何解决的。最后,我们谈到了量子计算的影响。

Base58 和 Pay-to-Public-Key-Hash

这与 P2PKH 有什么关系?P2PKH 地址以 1 开头,紧跟着的是用 base58 编码的公钥哈希值。

这就是当你想要从其他人那里接收比特币时,你需要发送给他们的信息。你也可以只发送 0x005和公钥给他们。或许他们能够成功将 0x00 翻译出来,但是大概率不行。

从理论上来说,你可以向其他人发送用十六进制(区块链上使用的格式)表示的比特币脚本,因为比特币脚本是二进制信息。在区块链上,这样的比特币脚本的大意是:“如果这个人拥有正确的公钥哈希和与之对应的公钥,你就可以花费这笔比特币。”如果你想更深入了解比特币脚本是如何运作的,请参见第十章。

虽然有如此多表示方式可以选择,但是人们选择的通常是标准化的地址格式。这就解释了为什么所有传统比特币地址都以 1 开头,而且长度也都差不多。

除了用来发送比特币地址,base58 也可以用来传递私钥。在这种情况下,为首的符号是 5(代表 128,作为版本字节),后面跟着私钥。

过去,用户用的是可以打印出来的纸钱包。如果它们是在没有后门的情况下安全生成的,那么这张纸的一面是以“1”开头的字符串,另一面是以“5”开头的字符串,并注明只可以出示比特币地址,不应共享私钥。

也有以“3”开头的地址,表示把比特币锁在脚本哈希值里面,而非公钥哈希值内。我们将在第十章介绍 Pay to Script Hash (P2SH)。这类地址通常是多签地址,不过也有可能是 SegWit 地址6

虽然 base58 地址表现良好,但还是有改进空间。于是,我们有了 bech32。

bech32 登场

2017 年 3 月,Pieter Wuille 谈到了一种新的地址格式 bech32。自 SegWit 成功激活以来,bech32 就一直被应用至今。顾名思义,bech32 是一种 base32 系统。也就是说,你可以使用几乎所有字母和所有数字,除去少数容易产生混淆的数字和字母。

讲解视频:https://youtu.be/NqiN9VFE4CU

bech32 和 base58 之间最大的区别是不混用大小写字母。每个字母只会出现一次(要么全部大写,要么全部小写),因此读出口会容易得多。每个字母或数字与其对应值之间的精准映射是固定的,但是相当随意:Q 就表示 0,P 就表示 1,背后没有深层含义。

新人科普丨什么是比特币地址?

- bech32 映射表。例如,q 表示 0,3 表示 17(1+16) -

bech327地址由使用“1”分隔的两部分组成,例如,bc1q9kdcd08adkhg35r4g6nwu8ae4nkmsgp9vy00gf

前半部分是有意让人读懂的,例如,“bc”(代表 Bitcoin)或“Inbc”(比特币上的闪电网络)。“b”和“c”等字母代表的值没有任何含义。它们的存在只是为了让人识别:“懂了,如果地址以 ‘bc’ 开头,指的就是作为密码学货币的比特币。”但是,钱包会查看这些值是否存在,作为可信度检查,而且这些值也包含在校验和内。

“1”只是分隔字符,不代表任何值。如果你查看 bech32 的映射表,你会发现“1”不包含在内,意思是“跳过它”。

后半部分以 SegWit 版本号为开头。版本 0 由 Q(bc1q…)代表(见第三章)。版本 1 就是我们所说的 Taproot(见本书的第 4 部分),用“P”(bc1p…)表示。如果是版本 0 SegWit,版本号后面会跟着 20 或 32 个字节,分别表示公钥哈希值或脚本哈希值。二者的长度不同,是因为 SegWit 使用的是脚本的 SHA256 哈希(32 个字节), 而非脚本的 RIPEMD160 哈希(20 个字节)。

在 base58 中,脚本哈希值与公钥哈希值长度相同。但是在 SegWit 中,二者的长度不同。因此,只要查看地址的长度,你立马就可以知道你是在向脚本还是公钥哈希付款。顺带一提,Taproot 消除了这种长度差异,进一步提高了隐私性。

因此,bench32 的特征是地址的后半部分只使用 32 种字符,除此之外与 base58 区别不大。看到这个特征,你就会明白:“啊哈,这是一个 P2PKH 地址。”在这种情况下,Pay-to-Witness-Public-Key-Hash (P2WPKH),其中“Witness”指的是 SegWit,但核心思想没有变:让人和电脑能够根据一个简短的前缀识别地址的类型,前缀后面跟着公钥或脚本的哈希值。

32 维掷镖游戏

但是,简洁性并非唯一的优点。还有一个优点是纠错性,至少是检错性。

如果你输错了地址,最坏的结果是你将比特币发送到了错误的公钥哈希值上。当接收方试图花费比特币时,会发现自己的公钥的哈希值并不符合区块链的要求,因为发送方之前输错了地址。这笔比特币就再也找不回来了。

幸好 base58 地址在末端有一个校验和。如此一来,如果你输错了地址,地址末端的校验和验证就会失败。你的钱包会向你发出告警,并拒绝发送该交易(区块链不会保护你,好在你的钱包会)。但是,如果你实在不走运,在输错的情况下也有可能恰好得到正确的校验和。

Bech32 就是为了避免出现如此极端的巧合而设计的。另外,Bech32 不仅会告诉你输错了,还会告诉你错在何处。具体方法是取地址的所有字节,使用某种复杂的数学公式对其进行哈希运算。即使你输错了 4 处,Bech32 依然可以知道哪里输错了,以及实际的值是什么。如果你输错了不止 4 处,Bech32 就没办法了。

我们通过一则比喻进行说明:你在一堵墙上画了一堆没有重叠的圆圈。每个圆圈的靶心代表一个正确的值,而圆圈内其它点各代表一个输入错误。如果你是个技术高超的飞镖玩家,大多数时候你会命中靶心,这意味着你输对了值。如果你稍稍错过靶心,但是依然落在圆圈内,这意味着你输入的值稍微有点不对。检错就是知道你错过了靶心。纠错就是将飞镖移动到最近的靶心。

这里面的思路是,你想要尽可能扩大圆圈来方便最粗枝大叶的飞镖玩家,却又不想浪费太多空间。同样地,我们不想将比特币地址变成数百个字符那么长。这是数学家最喜欢的优化问题。

不同于二维墙,bech32 好比是一面带有 32 维超球面的 32 维墙。当你输入地址时,在这个 32 维空间内的某处产生了轻微偏差,但无论看起来如何,你仍位于这个超球面内。在这种情况下,你的钱包知道错在哪里,可以有效防止因发错地址而造成比特币丢失的问题8

bech32 的漏洞

在 2019 年,人们发现如果一个 bech32 地址的最后一个字符是 P,你又意外在后面多输入了一个或几个 Q,依然能通过校验和验证,你也不会收到输入错误的提示。你的钱包软件会认为地址输入正确,任由你将比特币发送至错误地址,导致这笔比特币无法被花费,就像我们在上文解释的那样。

好消息是,bech32 只用于 SegWit,而 SegWit 地址有长度限制 —— 只能是 20 个字节或 32 个字节。幸运的是,如果你在长度为 20 或 32 字节的地址后面多输了一个 Q,你输入的地址就会因为超出长度限制而无效。你的钱包会发现这个问题,并拒绝发送比特币。人们原本考虑针对 Taproot 引入类似的地址长度限制,但是下文提到的解决方案免去了这一需求。灵活的地址长度更有助于我们未来改进 Taproot。

bech32m 诞生

为了修复 bech32 的漏洞,有人提议了一个叫作 bech32m 的新标准9。bech32m 实际上是非常简单的改变:在 bech32 校验和公式中额外添加了一个数字,以确保任何新增字符都会生成无效校验和。

这个新标准只应用于 Taproot 地址和未来地址。对于 SegWit 地址来说,一切都没有改变,因为它们已经有了 20 或 32 字节长度限制的保护。在笔者撰文期间,大多数钱包软件都支持新的 bech32m 标准。

是什么让我摆脱焦虑,爱上量子计算?

顺带一提,Pay-to-Public-Key-Hash (P2PKH) 被认为更能抵御量子攻击,因为你无需透露自己的公钥。缺点是哈希占用的空间更大 —— 但这在当时不成问题,因为区块远不到填满的程度。

很多人担心量子计算机最终会破坏比特币密码学的安全性,让妄图窃取比特币的量子黑客有可趁之机。如果他们成功窃取数百万个比特币,甚至会导致市场崩盘。

问题是,尽管 P2PKH 被广泛采用,其中有 500 万至 1000 万比特币的公钥已经公开。具有讽刺意味的是,鉴于如此多比特币容易遭到量子黑客窃取,试图以此保护剩余的比特币已经意义不大。即使你的比特币因为使用了 P2PKH 二不会被盗,也免不了因价格崩盘而变得一文不值。

物理学家 Stepan Snigirev和数学家Andrew Poelstra在两集题为《比特币做了什么》的播客中解释了量子攻击在短期内造成毁灭性后果的可能性以及可行的应对措施。

区块空间现在变得非常稀缺,因此无需将公钥哈希存储在宝贵的区块空间内可以帮助用户节省费用。这就是为什么在新的 Taproot 软分叉中(见本书的第四部分),比特币地址又成了 P2PK10。请注意使用 Taproot 地址不具有强制性,因此如果你不认同上述推理,你可以选择不使用 Taproot。

脚注

1.为满足代码“考古”爱好者的好奇心:发送方节点会有一个 UI 对话框提示转账数额和 IP 地址。函数 StartTransfer() 创建一个空白支票交易,接收方节点上的 checkorder 会在其中插入一个 P2PK 脚本(作为 scriptPubKey)。随后,OnReply2() 会插入数额,签署交易,将交易返回给接收者并进行广播。源代码

2.而且是不安全的,中本聪也承认了这点。

3.为什么中本聪最初发布的版本同时支持 P2PK 和 P2PKH?我们并不确定具体原因。P2PK 的支付方式实际上只用来向 IP 地址付款,以及向矿工支付区块奖励。二者都不需要人际交互。在涉及人际交互的场景中,用户使用的是 P2PKH。使用地址指的是 P2PKH 而非 P2PK 。自动化系统不需要地址的概念,因为它们也可以处理脚本,也就不需要像 P2PK 地址这样的概念。

4.到目前为止,脚本都与银行账户类似。我们将在第十章了解到脚本的功能远不只是为所有者保管资金而已。

5.一对以 0x 为前缀的十六进制数字通常被用来表示一个字节,它可以表示 16 × 16 = 256 个不同值。因此,0x00 表示一个字节且它的值为 0。

6.正如第三章解释的那样,SegWit 通常使用 bech32 地址。但是,过了很长时间,我们才等到所有钱包和交易所都支持向 bech32 地址付款。为了继续利用 SegWit 的一些优点,我们引入了一种在发送方角度看起来像是普通 P2SH 的地址类型,但是背后包含了 SegWit 的魔力。这类地址叫作P2SH-P2WPKH 地址

7.bech32 由 BIP173 提出。

8.早期的以太坊钱包不使用错误检测,因为它们的地址标准缺少校验和。虽然 EIP55 在 2016 年引入了校验和,但不是所有钱包都执行错误检测。即使到了 2017 年末,仍有人因输错地址而丢失以太币

9.bech32m 由 BIP 350 提出。

10.具体原因见BIP 341 的注释

免责声明:本文章仅代表作者个人观点,不代表本平台的立场和观点。本文章仅供信息分享,不构成对任何人的任何投资建议。用户与作者之间的任何争议,与本平台无关。如网页中刊载的文章或图片涉及侵权,请提供相关的权利证明和身份证明发送邮件到support@aicoin.com,本平台相关工作人员将会进行核查。

分享