当你阅读本文时,我假定你是一个比特币的开发者,并且对比特币的代码细节有一定的兴趣。尤其是你在处理比特币的地址转换(我们看到的和代码用到的地址格式)时有一些疑惑的时候,也许本文能够帮助到你。
比特币地址对应的锁定脚本(ScriptPubKey)主要类型:P2PKH P2SH P2WSH P2WPKH P2SH-P2WSH P2SH-P2WPKH,不同的锁定脚本类型是由不同的地址生成的。
私钥、公钥、地址关系
公钥生成私钥过程
脚本类型 |
源类型 |
地址长度 |
P2PKH |
公钥 |
20 |
P2SH |
脚本 |
20 |
P2WPKH |
公钥 |
20 |
P2WSH |
脚本 |
32 |
P2SH-P2WSH |
公钥 |
20 |
P2SH-P2WPKH |
脚本 |
20 |
实际上我们看到的地址是经过Bash58编码或bech32编码的地址,地址中添加了地址类型和校验码所以不同的地址开头会呈现不同的数值。生成锁定脚本的时候要解码数据并且去掉地址类型码。
不同地址的标志位对照表如下:
地址类型 |
网络类型 |
对应的地址标志位 |
编码类型 |
说明 |
P2PKH地址 |
main |
0x00 |
Base58 |
支付到比特币地址的交易包含支付公钥哈希脚本(P2PKH)。由P2PKH 脚本锁定 的交易输出可以通过给出由相应私钥创建的公钥和数字签名来解锁(消费) |
testnet |
0x6F |
Base58 |
||
regtest |
0x6F |
Base58 |
||
P2SH地址 |
main |
0x05 |
Base58 |
P2SH 地址是基于Base58 编码的一个含有20 个字节哈希的脚本。P2SH 地址采用 “5”前缀。这导致基于Base58 编码的地址以“3”开头。P2SH 地址隐藏了所有的复 杂性,因此,运用其进行支付的人将不会看到脚本。 |
testnet |
0xC4 |
Base58 |
||
regtest |
0xC4 |
Base58 |
||
P2WPKH地址 |
main |
"bc" |
Bech32 |
P2WPKH地址是脚本做HASH160得到20位的地址经过Bech32编码后显示 |
testnet |
"tb" |
Bech32 |
||
regtest |
"bcrt" |
Bech32 |
||
P2WSH地址 |
main |
"bc" |
Bech32 |
P2WSH地址是脚本做HASH256得到到32位的地址经过Bech32编码后显示 |
testnet |
"tb" |
Bech32 |
||
regtest |
"bcrt" |
Bech32 |
||
P2SH-P2WPKH地址 |
main |
0x05 |
Base58 |
P2SH-P2WPK地址是为了满足旧钱包的需求,将P2WPKH对应的锁定脚本转换到普通的P2SH地址格式。 |
testnet |
0xC4 |
Base58 |
||
regtest |
0xC4 |
Base58 |
||
P2SH-P2WSH地址 |
main |
0x05 |
Base58 |
P2SH-P2SH地址是为了满足旧钱包的需求,将P2WPKH对应的锁定脚本转换到普通的P2SH地址格式。 |
testnet |
0xC4 |
Base58 |
||
regtest |
0xC4 |
Base58 |
P2PKH:
是利用公钥的哈希,相对来说比较简单,现在新版本的钱包应用的越来越少。
OP_DUP OP_HASH160 OPCODE_LEN ADDR OP_EQUALVERIFY OP_CHECKSIG
对应的字节表示 0x76 0xa9 0x14 20字节地址 0x88 0xac
P2PKH长度:25字节
OPCODE_LEN:0x14 即 地址ADDR的长度
ADDR:是由公钥生成的20字节
P2SH:
利用了脚本的哈希,并且锁定脚本相较于P2PKH更加简洁。由于脚本更加复杂,可以根据需要设计不同的逻辑控制,因此应用会被广泛应用。锁定脚本中表示简单,但是赎回脚本和签名处变的复杂了。
OP_HASH160 OPCODE_LEN ADDR OP_EQUAL
对应的字节表示: 0xa9 0x14 20字节地址 0x87
P2SH长度:23
OPCODE_LEN:0x14 即 地址ADDR的长度
ADDR:是由脚本经过HASH160生成的20字节
P2WPKH:
是隔离见证中公钥地址的表示,格式主要是为了与非隔离见证的锁定脚本区别。旧钱包是不支持的。
VER OPCODE_LEN ADDR
对应的字节表示 0x00 0x14 20字节地址
P2WPKH长度:22
0x00: 版本号,固定0
OPCODE_LEN:0x14 即 地址ADDR的长度
ADDR:是由公钥生成的20字节
P2WSH:
是隔离见证中脚本地址的表示,格式主要是为了与非隔离见证的锁定脚本区别。旧钱包是不支持的。因为可以用到复杂脚本,因此可以做复杂逻辑应用。
VER OPCODE_LEN ADDR
对应的字节表示 0x00 0x20 32字节地址
P2WSH长度:34
0x00: 版本号,固定0
OPCODE_LEN:0x20 即 地址ADDR的长度
P2SH-P2WPKH:
P2SH-P2WPKH是对P2WPKH进行HASH160得到20字节地址,此地址可在P2SH中应用,与普通的P2SH地址没有任何区别。格式见P2SH
P2SH-P2WSH
P2SH-P2WSH是对P2WSH进行HASH160得到20字节地址,此地址可在P2SH中应用,与普通的P2SH地址没有任何区别。格式见P2SH
比特币地址类型分为3中格式: legacy p2sh-segwit bech32
legacy类型实际上就是取公钥或脚本的HASH160值得到20位字节地址。
p2sh-segwit:对应生成P2SH-P2WPKH 和 P2SH-P2WSH中的地址
bech32:对应生成P2WPKH 和 P2WSH中的地址
隔离见证中生成地址用到的公钥必须是压缩的公钥,否则可能会无法赎回此地址的币。
隔离见证地址用长度32或20来判定地址是由脚本或公钥生成的,0(版本)开头表示是隔离见证地址。
我们在UI上看到的地址是带有地址类型码并且经过Bash58或Bech32编码后的地址的字符串,因此与实际地址长度并不符合。当我们传入此地址后,会解码并去除类型码,并根据类型码生成不同的ScriptPubkey(P2PKH P2SH P2WSH P2WPKH P2SH-P2WSH P2SH-P2WPKH)。
P2PKH地址:
显示的地址:mgjswfb6eXcmuJgLxvMxAo1tth2QCyyPYt
实际地址16进制表示:0x0d 0x69 0xe6 0x9c 0x75 0x72 0x53 0x4c 0xa3 0x5d 0xdd 0x12 0x64 0x6f 0x90 0x8b 0xf0 0x7b 0xf7 0xb6
P2SH地址:
显示的地址:2Mz5nE8zyxQDMZawYZ6cqbHZZdkih5CwQjU
实际地址16进制表示:0x4a 0xff 0xa1 0xed 0x45 0x54 0x17 0x5a 0x00 0xd6 0x54 0x78 0x8d 0x34 0xf3 0x13 0xd7 0x38 0x02 0xdd
P2WSH地址:
显示的地址:bcrt1qja4c5mpjw8hjlatgwud56naunfykxwupk65yev
实际地址16进制表示:0x14 0x97 0x6b 0x8a 0x6c 0x32 0x71 0xef 0x2f 0xf5 0x68 0x77 0x1b 0x4d 0x4f 0xbc 0x9a 0x49 0x63 0x3b 0x81
P2WPKH地址:
显示的地址:bcrt1q09zjqeetautmyzrxn9d2pu5c5glv6zcmj3qx5axrltslu90p88pqykxdv4
实际地址16进制表示:0x20 0x79 0x45 0x20 0x67 0x2b 0xef 0x17 0xb2 0x08 0x66 0x99 0x5a 0xa0 0xf2 0x98 0xa2 0x3e 0xcd 0x0b 0x1b 0x94 0x40 0x6a 0x74 0xc3 0xfa 0xe1 0xfe 0x15 0xe1 0x39 0xc2
P2PKH、P2SH:是现在所有钱包都支持的格式,应用最广。
P2WPKH、P2WSH是隔离见证的标准格式,判定简单,相对比较新,很多旧钱包没有支持,但随着隔离见证技术的应用(隔离见证优点及特性请查看相关资料,目前很火的闪电网络就应用了隔离见证技术),会有更多的钱包支持。
P2SH-P2WPKH、P2SH-P2WSH是为了支持旧钱包对P2WPKH、 P2WSH做的升值,应用此格式,旧钱包可以创建给隔离见证地址的交易, 对于P2SH-P2WPKH、P2SH-P2WSH作为输入的签名过程会更复杂一些。
由于能力有限,文中有错误的地方请指正,我将及时更正。
参考:
《精通比特币》第二版
bitcoin代码
libwally-core代码