https://aaron67.cc/2019/01/04/bitcoin-address/
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/ 生成一對私鑰和位址,整體演算一遍。

私鑰
L2M6qFzrdDEv7eRT7p94Zf4QShLdWjicFpkiCro12CrRbCDb8ke3
以
L
開頭,這是 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
。
交易
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
開頭。
結合之前的文章,你知道:
- 在比特币系統裡其實沒有“位址”的概念,交易輸出會被鎖定腳本鎖定,與公鑰哈希或腳本哈希關聯
- 位址是公鑰哈希或腳本哈希的可逆編碼,定義“位址”是為了友善使用者使用,封裝幕後細節,簡化操作
- 從私鑰可以計算公鑰,從公鑰可以計算位址,但反過來都不成立
- 私鑰十分重要,擁有私鑰就擁有了其對應公鑰上鎖定的比特币
參考
- 精通比特币(第二版)譯文 原文