术语表 /地址与密钥
压缩公钥
- 压缩公钥是什么?
- 压缩公钥只存储曲线上某一点的 x 坐标,外加一个1字节的奇偶标志,使一个完整公钥只需33字节,而不是65字节。
对于给定的 x,secp256k1 曲线上的每个点都有两个可能的 y 值,因此记录究竟是哪一个只需1个字节,而不是32个字节。自2012年3月发布的 Bitcoin Core 0.6起,钱包默认生成压缩密钥,节省的字节会从您日后花费的每一笔输入的大小中扣除。更低的花费成本就是全部好处,而且这种格式在日常使用中无从察觉。
运作方式
公钥压缩是代数运算,而不是数据压缩。曲线方程为 y 的平方等于 x 的立方加7,对于任意给定的 x,y 至多有两个解,而这两个解总是一个偶数和一个奇数。因此,只要存储 x 以及说明采用哪个解的1位信息,任何人都能通过解方程并选取奇偶性正确的根,精确还原这个点。
编码把这一位放在首字节中。前缀0x02 表示 y 值为偶数,0x03 表示 y 值为奇数,后面的32个字节是 x 坐标。总长度:33字节。旧格式以前缀0x04 标识,完整携带两个坐标,共65字节。任何读取密钥的软件仅凭第一个字节就能区分这两种格式,钱包正是借此在过渡期间保持了兼容。
节省的32个字节落在何处,取决于输出类型。在传统(legacy)输入中,密钥位于解锁脚本内,按全额权重计费,因此32字节相当于32 vbytes,按20 sat/vB 的费率约为640聪。在 SegWit 输入中,密钥位于见证数据内,按四分之一折算,因此同样的32字节只相当于8 vbytes。这两个数字单独看都不算大,但它们会在您签署的每一笔交易的每一个输入上重复出现。
在哪里会遇到它
您会在原始交易数据中见到压缩密钥。在区块浏览器中打开任意一笔近期的花费,见证数据或脚本中的公钥会以02或03开头,后面跟着64个十六进制字符。以04开头的密钥是遗留产物。
这种格式还决定了地址的外观。对压缩密钥做哈希与对同一密钥的未压缩版本做哈希,结果不同,因此一个私钥可以对应两个完全独立、余额各自独立的传统地址。钱包靠约定而非技巧来处理这一点:通过 BIP-32派生的一切,涵盖日常使用的所有助记词钱包,全程都是压缩的,而以 K 或 L 开头的钱包导入格式(Wallet Import Format)字符串则表明该密钥属于这一分叉中的压缩一侧。
SegWit 彻底消除了这种歧义。BIP-143禁止在版本0的见证程序中使用未压缩密钥,因此按规则,任何 bc1q 地址都是压缩的,而 Taproot 更进一步,定义了仅含 x 坐标的32字节密钥,完全省去了奇偶字节。
压缩公钥 vs 未压缩公钥
压缩与未压缩两种形式编码的是同一个点,区别仅在于需要写下什么。压缩形式保留 x,需要时再推算 y,这需要几微秒的运算,却永远节省32字节。未压缩形式直接存储 y,这在2009年的硬件上曾节省计算量,如今已没有任何益处。由于两种字节串不同,它们哈希出的地址也不同,偶尔导致非常古老的钱包中的资金被困的,正是这种不匹配,而不是字节数。