比特幣 區塊鏈 區塊頭 Merkle樹 目標難度nBits 交易 作業碼 地址轉換 原始交易格式 TxIn 一個交易輸出非-Coinbase Outpoint特定輸出的具體部分 TxOut 交易輸出 例子 Coinbase輸入 一個區塊中的第一個交易 CompactSize不帶正負號的整數 錢包 確定性錢包格式 類型1單鏈錢包 類型2分層確定性HD錢包 P2P網路 常量和預設值 協議版本 資訊頭 資料資訊 區塊 獲得區塊 獲得資料 獲得區塊頭 頭部 Inv 記憶體池 Merkle塊 未找到 Tx 控制資訊 地址 警報 費用過濾器 地址過濾器 FilterClear FilterLoad 獲得地址 Ping Pong 拒絕 發送頭 VerAck 版本 比特幣核心API 雜湊位元組順序 遠端程序呼叫RPCs 預覽 RPCs AbandonTransaction AddMultiSigAddress HTTP REST 預覽 Requests GET Block
比特幣 區塊鏈 區塊頭
| 位元組 |
名稱 |
資料類型 |
描述 |
| 4 |
Veesion |
int32_t |
版本號碼表示所遵循的規則 |
| 32 |
preBlockHeaderHash |
char[32] |
SHA256(SHA256())前一塊頭部的雜湊 |
| 32 |
MerkleRootHash |
char[32] |
這塊中所有交易的雜湊 |
| 4 |
time |
uint32_t |
Unix時間戳記 |
| 4 |
nbits |
uint32_t |
難度係數 |
| 4 |
Nonce |
uint32_t |
隨機數 |
Merkle樹
Merkle Root是根據這個塊中所有交易的TXID產生的: CoinBase的交易排在第一位 該塊內的任何輸入也可以在輸出中出現(假設花費有效)。但是,輸出對應的TXID必須放在輸入對應的TXID
之前的某個點。確保了在輸出之前被輸入了。也就是說想要花錢必須先有人給你轉過錢,而不是你先花了,再有人給你轉。
如果一個區塊僅有一個CoinBase的交易,這個CoinBase的TXID就被用作Merkle的根雜湊。
如果一個區塊有一個CoinBase的交易和一個其他交易,那麼就排好順序為64位元組然後進行SHA256(SHA256())形成Merkle根雜湊。
如果一個區塊有3個以上的交易,則形成中間Merkle樹。TXID按順序排列並配對,從CoinBase的TXID開始。每一對都拼接在一起然後進行SHA256(SHA256()),形成第二排散列。如果有一個非偶數(奇數)的TXID個數,則最後一個TXID複製一個自己然後SHA256(SHA256())。如果第二排有超過2個的hashed,則重複上一步的操作。直到只剩2個hashed的時候,再拼接並SHA256(SHA256())形成Merkle樹的根。
目標難度nBits
目標閾值是一個無符號的256-bit整數,頭部雜湊必須小於等於這個值才能成為區塊鏈的有效部分。
序列化塊
按照目前的共識規則,大於1MB的塊是無效的。下面介紹的大小全是序列化後的大小。
| 位元組 |
名稱 |
資料類型 |
描述 |
| 80 |
block header |
block_header |
上面曾描述過的結構 |
| Varies |
txn_count |
compactSizeUnit |
包括CoinBase在內的所有交易數目 |
| Varies |
txns |
raw trasaction |
此塊中的每一個交易,一個接一個。 |
塊中的第一個交易必須為CoinBase交易,用以收集本塊中的交易費用。
所有塊高不超過6,930,000的區塊都有權獲得建立區塊的獎勵。(區塊獎勵從50比特幣開始,每210,000塊減半,大約每四年一次,截至2017年11月,為12.5比特幣。) 交易
以下小節將簡要介紹核心交易的細節。 作業碼
在標準交易中的公有指令碼作業碼: 各種資料作業碼,從0x00到0x4e(1-78)。 OP_TRUE/OP_1(0x51)和OP_2到OP_16(0x52-0x60),表示把1-16壓入棧中。 OP_CHECKSIG消費一個簽名和一個公開金鑰,如果由SIGHASH標誌指定的交易資料被轉換為使用產生該公開金鑰的相同ECDSA私密金鑰的簽名就壓入TRUE, 否則,它會將FALSE壓入堆棧。 OP_DUP把棧頂元素複製並壓入棧中。 OP_HASH160消費棧頂元素,計算RIPEMD160(SHA256()),並把計算後的值壓入棧中。 OP_EQUAL消費棧頂的2個元素,比較,相同壓入真,否則壓入假。 OP_VERIFY消費棧頂元素,如果是0則終止指令碼。 OP_EQUALVERIFY 按順序運行 OP_EQUAL 和 OP_VERIFY 。
更多的作業碼請看Wiki和其實現script. 地址轉換
比特幣地址通常用P2PKH和P2SH來進行雜湊操作。
首先,擷取你的雜湊值。對於P2PKH,使用RIPEMD-160(SHA256()) 雜湊從你256-bit的ECDSA私密金鑰(隨機數)所對應的公開金鑰。對於P2SH,使用RIPEMD-160(SHA256()) 對序列化原始交易通過轉化指令碼來獲得雜湊(後續會講到)。獲得雜湊結果:
1. 在雜湊值前添加一個位元組版本 比特幣主網路(mainnet)上的P2PKH地址為0x00 比特幣測試網路(testnet)上的P2PKH地址0x6f 主網路上的P2SH地址為0x05 測試網路上的P2SH地址的0xc4
2.建立一個版本和雜湊值得副本,然後進行2次雜湊運算SHA256(SHA256(version . hash))
3.從雙重雜湊副本中提取前四個位元組。 這些被用作校正和以確保雜湊傳輸正確。
4.將校正和附加到版本和散列之後,並將其編碼為base58字串:BASE58(version . hash . checksum)
比特幣的base58編碼稱為Base58Check,與其他一般實現不太一樣。Wiki
code_string = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"x = convert_bytes_to_big_integer(hash_result)output_string = ""while(x > 0) { (x, remainder) = divide(x, 58) output_string.append(code_string[remainder]) }repeat(number_of_leading_zero_bytes_in_hash) { output_string.append(code_string[0]); }output_string.reverse();
要將地址轉換回雜湊值,先base58解碼,提取校正和,重複這些步驟以建立校正和,並將其與提取的校正和進行比較,然後刪除版本位元組。 原始交易格式
比特幣的交易以序列化的位元組格式在點對點之間播發,SHA256(SHA256())交易去建立TXID,最終是包含交易的塊的Mekle樹根。
原始交易具有以下格式:
| 位元組 |
名稱 |
資料類型 |
描述 |
| 4 |
version |
uint32_t |
交易版本號碼,現在的版本號碼是1;使用更新的共識規則規則建立的交易可能有更高的版本號碼。 |
| Varies |
tx_in count |
compactSize uint |
交易輸入的數量 |
| Varies |
tx_in |
txIn |
交易輸入。 請參閱下面的txIn的描述。 |
| Varies |
tx_out count |
compactSize uint |
交易輸出的數量。 |
| Varies |
tx_out |
txOut |
交易輸出。 請參閱下面的txOut的描述。 |
| 4 |
local_time |
unit32_t |
Unix時間或塊號,請參閱locktime解析規則。 |
一個交易可能有多筆的輸入和輸出,所以txIn和txOut結構可能在一個結構中重複出現。CompactSize不帶正負號的整數是可變長整數的一種形式; 它們在CompactSize部分中進行了描述。 TxIn: 一個交易輸出(非-Coinbase)
每一個非CoinBase的輸入花費一個outpoint來自之前的交易。(Coinbase輸入在下面的樣本部分之後單獨描述。)
| 位元組 |
名稱 |
資料類型 |
描述 |
| 36 |
previous_output |
outpoint |
之前被消費的outpoint,請參閱下面的outpoint描述。 |
| Varies |
script bytes |
compactSize uint |
簽名指令碼中的位元組數。 最大值為10,000位元組。 |
| Varies |
signature script |
char[] |
一個指令碼語言,滿足outpoint的pubkey指令碼中的條件。 只應該包含資料推送; 請參閱簽名指令碼修改警告。 |
| 4 |
sequence |
uint32_t |
序號。 比特幣核心和幾乎所有其他程式的預設值是0xffffffff。 |
Outpoint:特定輸出的具體部分
由於一個單一的交易可以包含多個輸出,outpoint結構包含一個TXID和一個輸出索引號指向一個具體的輸出。
| 位元組 |
名稱 |
資料類型 |
描述 |
| 32 |
hash |
char[32] |
交易的TXID輸出的花費,TXID是以內部位元組順序提供的雜湊。 |
| 4 |
index |
uint32_t |
交易中具體花費的具體輸出索引號。第一個輸出是0x00000000 |
TxOut: 交易輸出
每個輸出花費一定數量的聰,任何可以提供滿足pubkey script.的人都可以使用它。
| 位元組 |
名稱 |
資料類型 |
描述 |
| 8 |
value |
int64_t |
花費聰的數量。可能是零;所有輸出的總和不得超過以前用於輸入部分所提供的聰的總和。 (例外:coinbase交易花費區塊獎勵和收取的交易費用。) |
| 1+ |
pk_script bytes |
compactSize uint |
pubkey指令碼中的位元組數。 最大值是10,000位元組。 |
| Varies |
pk_script |
char[] |
定義花費這個輸出必須滿足的條件。 |
例子
一個交易的例子。
01000000 ................................... Version01 ......................................... Number of inputs|| 7b1eabe0209b1fe794124575ef807057| c77ada2138ae4fa8d6c4de0398a14f3f ......... Outpoint TXID| 00000000 ................................. Outpoint index number|| 49 ....................................... Bytes in sig. script: 73| | 48 ..................................... Push 72 bytes as data| | | 30450221008949f0cb400094ad2b5eb3| | | 99d59d01c14d73d8fe6e96df1a7150de| | | b388ab8935022079656090d7f6bac4c9| | | a94e0aad311a4268e082a725f8aeae05| | | 73fb12ff866a5f01 ..................... Secp256k1 signature|| ffffffff ................................. Sequence number: UINT32_MAX01 ......................................... Number of outputs| f0ca052a01000000 ......................... Satoshis (49.99990000 BTC)|| 19 ....................................... Bytes in pubkey script: 25| | 76 ..................................... OP_DUP| | a9 ..................................... OP_HASH160| | 14 ..................................... Push 20 bytes as data| | | cbc20a7664f2f69e5355aa427045bc15| | | e7c6c772 ............................. PubKey hash| | 88 ..................................... OP_EQUALVERIFY| | ac ..................................... OP_CHECKSIG00000000 ................................... locktime: 0 (a block height)
Coinbase輸入: 一個區塊中的第一個交易
在區塊中的第一個交易,叫做Coinbase交易,有且只有一個輸入,叫做Coinbase。Coinbase輸入的格式如下:
| 位元組 |
名稱 |
資料類型 |
描述 |
| 32 |
hash (null) |
char[32] |
一個32位元組的null,作為coinbase沒有先前的outpoint。 |
| 4 |
index (UINT32_MAX) |
uint32_t |
0xffffffff, coinbase 沒有先前的outpoint。 |
| Varies(4) |
script bytes |
compactSize uint |
coinbase指令碼中的位元組數,最大為100個位元組。 |
| Varies |
height |
script |
塊高度。使用指令碼語言:從資料壓棧作業碼開始,該作業碼指示將多少位元組推送到堆棧,然後將塊高度作為小端不帶正負號的整數。 該指令碼必須儘可能短,否則可能會被拒絕。資料推送作業碼將是0x03,大小為四個位元組到距離現在約300年的16,777,216塊。 |
| Varies |
coinbase script |
None |
Coinbase欄位:任意資料,不超過100位元組減去(4)高度位元組。 礦工們通常在這個欄位中放置一個額外的隨機數,以便在散列期間更新塊頭merkle根。 |
| 4 |
sequence |
uint32_t |
序號 |
在塊高度227,836之前的大多數(但不是全部)塊使用1.0版本,其不需要將高度參數作為幣基指令碼的首碼。 塊高度參數現在是必需的。
一個coinbase的交易展示:
01000000 .............................. Version01 .................................... Number of inputs| 00000000000000000000000000000000| 00000000000000000000000000000000 ... Previous outpoint TXID| ffffffff ............................ Previous outpoint index|| 29 .................................. Bytes in coinbase| || | 03 ................................ Bytes in height| | | 4e0105 .......................... Height: 328014| || | 062f503253482f0472d35454085fffed| | f2400000f90f54696d65202620486561| | 6c74682021 ........................ Arbitrary data| 00000000 ............................ Sequence01 .................................... Output count| 2c37449500000000 .................... Satoshis (25.04275756 BTC)| 1976a914a09be8040cbf399926aeb1f4| 70c37d1341f3b46588ac ................ P2PKH script| 00000000 ............................ Locktime
CompactSize不帶正負號的整數
交易格式和部分點對點網路訊息使用一種變長的整數來指示資料中的位元組數。比特幣核心代碼和本文檔將這些可變整數稱為compactSize。
對於從0到252的數字,compactSize不帶正負號的整數看起來像普通的不帶正負號的整數。 對高於0xffffffffffffffff的其他數字,一個位元組以數字為首碼以指示其長度,其餘部分數字看起來像小端順序的常規不帶正負號的整數。
| 值 |
位元組使用 |
格式 |
| >= 0 && <= 252 |