[学习笔记] 比特币的地址

Alice 向 Bob 支付比特币:

  • 使用 P2PK 交易,需要知道 Bob 的公钥,锁定脚本为
[Bob的公钥] OP_CHECKSIG
  • 使用 P2PKH 交易,需要知道 Bob 的公钥Bob 的公钥哈希,锁定脚本为
OP_DUP OP_HASH160 [Bob的公钥哈希] OP_EQUALVERIFY OP_CHECKSIG
  • 使用 P2SH 交易,需要知道 Bob 的脚本哈希,锁定脚本为
OP_HASH160 [Bob的脚本哈希] OP_EQUAL

了解了交易的细节,你可能会疑惑,这与日常收发比特币时的情况好像不太一样。

接收比特币时,通常会使用一串跟银行卡号类似的“神奇代码”,作为收款“地址”,形如

1BJhat1AMGYbT9HYJxVekoCaPaqB9ZyTyF

这篇文章介绍地址是怎么计算的。

P2PKH 地址

一句话解释,P2PKH 地址是 Base58Check 编码的公钥哈希。

我们用 App 支付比特币到某个地址,App 会先将地址反解成公钥哈希,然后构造一笔 P2PKH 交易,完成支付。

因为 Base58Check 编码是可逆的,所以可以这么做。

https://www.bitaddress.org/ 生成一对私钥和地址,整体演算一遍。

Imgur

私钥L2M6qFzrdDEv7eRT7p94Zf4QShLdWjicFpkiCro12CrRbCDb8ke3L开头,这是 WIF 压缩格式的私钥。

用这个工具,Base58Check 反解之后为(我加了空格)

80 98fd2a819a382f8e142e38242f6caf2a2f6f58e7fe6ca5f23c5b0818b15b4ba6 01 236803e8

私钥为98fd2a819a382f8e142e38242f6caf2a2f6f58e7fe6ca5f23c5b0818b15b4ba6

计算出对应的公钥点为

x = da52d817a5ae3555f36a94528322eb47016f1334b798f5b4fa614a892dabb3ea
y = f314bf38816673c55c1708cf1e36b55c936db97618d6460c4d223be83bec7788

公钥为02da52d817a5ae3555f36a94528322eb47016f1334b798f5b4fa614a892dabb3ea(P2PK 交易需要这个值)。

用这个工具,计算公钥 HASH160 后的结果,得到公钥哈希(P2PKH 交易需要这个值)为

710a35053db4296dc5f3476d10ae93924bc55c9a

公钥哈希做 Base58Check 编码,按规定添加0x00版本前缀。

类型 版本前缀的值(十六进制) Base58Check之后的前缀
P2PKH地址 00 1
P2SH地址 05 3

得到地址

1BJhat1AMGYbT9HYJxVekoCaPaqB9ZyTyF

编码过程如下。

# payload
710a35053db4296dc5f3476d10ae93924bc55c9a

# S1 = version + payload
00 710a35053db4296dc5f3476d10ae93924bc55c9a

# S2 = SHA256(SHA256(S1))
5f91f9a69fc02d537c93e41b127b2f5081fd25f82683c1eebe3c54aae1f83130

# S2的前4字节是Checksum
5f91f9a6

# S3 = S1 + Checksum
00 710a35053db4296dc5f3476d10ae93924bc55c9a 5f91f9a6

# 地址 = Base58(S3)
1BJhat1AMGYbT9HYJxVekoCaPaqB9ZyTyF

需要注意的是,从 P2PKH 地址只能反解出公钥哈希的值,而无法知道公钥本身,因为哈希是不可逆的,无法从公钥哈希计算公钥。

由于在 Base58Check 编码时加入了特定前缀0x00,所以这类地址都以1开头,方便识别。

地址中包含了校验和,能有效防止转录过程中的错误,这也是为什么不直接使用公钥哈希的原因。

当你在 App 里发送比特币到某个1开头的地址时,App 知道这是一个 P2PKH 地址,先校验地址是不是合法,再反解出编码前的公钥哈希,创建 P2PKH 交易,完成支付。

普通用户可以直接使用地址来收发比特币,而不用了解幕后细节,因为它们被地址隐藏了。

P2SH 地址

同样的,对于 P2SH 交易中用到的脚本哈希,也可以这么干。

但编码时,会使用0x05的版本前缀,所以 P2SH 地址都以3开头,形如347N1Thc213QqfYCz3PZkjoJpNv5b14kBd

Imgur

交易40eee3ae1760e3a8532263678cdf64569e6ad06abc133af64f735e52562bccc8

{
"txid":"40eee3ae1760e3a8532263678cdf64569e6ad06abc133af64f735e52562bccc8",
"hash":"40eee3ae1760e3a8532263678cdf64569e6ad06abc133af64f735e52562bccc8",
"version":1,
"size":189,
"vsize":189,
"weight":756,
"locktime":0,
"vin":[
{
"txid":"42a3fdd7d7baea12221f259f38549930b47cec288b55e4a8facc3c899f4775da",
"vout":0,
"scriptSig":{
"asm":"3044022048d1468895910edafe53d4ec4209192cc3a8f0f21e7b9811f83b5e419bfb57e002203fef249b56682dbbb1528d4338969abb14583858488a3a766f609185efe68bca[ALL] 031a455dab5e1f614e574a2f4f12f22990717e93899695fb0d81e4ac2dcfd25d00",
"hex":"473044022048d1468895910edafe53d4ec4209192cc3a8f0f21e7b9811f83b5e419bfb57e002203fef249b56682dbbb1528d4338969abb14583858488a3a766f609185efe68bca0121031a455dab5e1f614e574a2f4f12f22990717e93899695fb0d81e4ac2dcfd25d00"
},
"sequence":4294967295
}
],
"vout":[
{
"value":0.0099,
"n":0,
"scriptPubKey":{
"asm":"OP_HASH160 e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a OP_EQUAL",
"hex":"a914e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a87",
"reqSigs":1,
"type":"scripthash",
"addresses":[
"3P14159f73E4gFr7JterCCQh9QjiTjiZrG"
]
}
}
]
}

输出支付到了脚本哈希e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a,让我们计算一下对应的地址。

# payload
e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a

# S1 = version + payload
05 e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a

# S2 = SHA256(SHA256(S1))
# http://bit.ly/2RoiDBu
7f297f3156a14d114af23b33c339817a1241afcb52a154d19683c67c538b7278

# S2的前4字节是Checksum
7f297f31

# S3 = S1 + Checksum
05 e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a 7f297f31

# 地址 = Base58(S3)
# https://incoherency.co.uk/base58/
3P14159f73E4gFr7JterCCQh9QjiTjiZrG

同样的,从 P2SH 地址只能反解出脚本哈希的值,而无法知道赎回脚本的具体内容。

当你在 App 里发送比特币到某个3开头的地址时,App 知道这是一个 P2SH 地址,先校验地址是不是合法,再反解出编码前的脚本哈希,创建 P2SH 交易,完成支付。

总结

地址是公钥哈希或脚本哈希的 Base58Check 编码,这个编码是可逆的。

P2PKH 地址都以1开头,P2SH 地址都以3开头。

结合之前的文章,你知道:

  • 在比特币系统里其实没有“地址”的概念,交易输出会被锁定脚本锁定,与公钥哈希或脚本哈希关联
  • 地址是公钥哈希或脚本哈希的可逆编码,定义“地址”是为了方便用户使用,封装幕后细节,简化操作
  • 从私钥可以计算公钥,从公钥可以计算地址,但反过来都不成立
  • 私钥十分重要,拥有私钥就拥有了其对应公钥上锁定的比特币

参考