比特幣資料結構
首先看一個區塊
https://webbtc.com/block/000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506
比特幣區塊分為2部分,區塊頭和交易資訊
從https://webbtc.com/block/000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506.hex可以看到這個區塊的16進製表示
#0100000050120119172a610421a6c3011dd330d9df07b63616c2cc1f1cd00200000000006657a9252aacd5c0b2940996ecff952228c3067cc38d4885efb5a4ac4247e9f337221b4d4c86041b0f2b5710 #04 #01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08044c86041b020602ffffffff0100f2052a010000004341041b0e8c2567c12536aa13357b79a073dc4444acb83c4ec7a0e2f99dd7457516c5817242da796924ca4e99947d087fedf9ce467cb9f7c6287078f801df276fdf84ac00000000 #0100000001032e38e9c0a84c6046d687d10556dcacc41d275ec55fc00779ac88fdf357a187000000008c493046022100c352d3dd993a981beba4a63ad15c209275ca9470abfcd57da93b58e4eb5dce82022100840792bc1f456062819f15d33ee7055cf7b5ee1af1ebcc6028d9cdb1c3af7748014104f46db5e9d61a9dc27b8d64ad23e7383a4e6ca164593c2527c038c0857eb67ee8e825dca65046b82c9331586c82e0fd1f633f25f87c161bc6f8a630121df2b3d3ffffffff0200e32321000000001976a914c398efa9c392ba6013c5e04ee729755ef7f58b3288ac000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00000000 #0100000001c33ebff2a709f13d9f9a7569ab16a32786af7d7e2de09265e41c61d078294ecf010000008a4730440220032d30df5ee6f57fa46cddb5eb8d0d9fe8de6b342d27942ae90a3231e0ba333e02203deee8060fdc70230a7f5b4ad7d7bc3e628cbe219a886b84269eaeb81e26b4fe014104ae31c31bf91278d99b8377a35bbce5b27d9fff15456839e919453fc7b3f721f0ba403ff96c9deeb680e5fd341c0fc3a7b90da4631ee39560639db462e9cb850fffffffff0240420f00000000001976a914b0dcbf97eabf4404e31d952477ce822dadbe7e1088acc060d211000000001976a9146b1281eec25ab4e1e0793ff4e08ab1abb3409cd988ac00000000 #01000000010b6072b386d4a773235237f64c1126ac3b240c84b917a3909ba1c43ded5f51f4000000008c493046022100bb1ad26df930a51cce110cf44f7a48c3c561fd977500b1ae5d6b6fd13d0b3f4a022100c5b42951acedff14abba2736fd574bdb465f3e6f8da12e2c5303954aca7f78f3014104a7135bfe824c97ecc01ec7d7e336185c81e2aa2c41ab175407c09484ce9694b44953fcb751206564a9c24dd094d42fdbfdd5aad3e063ce6af4cfaaea4ea14fbbffffffff0140420f00000000001976a91439aa3d569e06a1d7926dc4be1193c99bf2eb9ee088ac00000000
第一行就是區塊頭,80位元組
第二行04代表這個區塊有4個交易資訊
後面4行分別代表這個4個交易
把區塊轉成json格式看一下都有什麼內容
{ "hash": "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506", "ver": 1, "prev_block": "000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250", "mrkl_root": "f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766", "time": 1293623863, "bits": 453281356, "nonce": 274148111, "n_tx": 4, "size": 957, "tx": [ { "hash": "8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87", "ver": 1, "vin_sz": 1, "vout_sz": 1, "lock_time": 0, "size": 135, "in": [ { "prev_out": { "hash": "0000000000000000000000000000000000000000000000000000000000000000", "n": 4294967295 }, "coinbase": "044c86041b020602" } ], "out": [ { "value": "50.00000000", "scriptPubKey": "041b0e8c2567c12536aa13357b79a073dc4444acb83c4ec7a0e2f99dd7457516c5817242da796924ca4e99947d087fedf9ce467cb9f7c6287078f801df276fdf84 OP_CHECKSIG", "next_in": { "hash": "f3e6066078e815bb24db0dfbff814f738943bddaaa76f8beba360cfe2882480a", "n": 12 } } ], "nid": "70ab531a68f973f7d20b8260cb5e7fecba3699c48715b8b44539ff9776d0b88e" }, { "hash": "fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4", "ver": 1, "vin_sz": 1, "vout_sz": 2, "lock_time": 0, "size": 259, "in": [ { "prev_out": { "hash": "87a157f3fd88ac7907c05fc55e271dc4acdc5605d187d646604ca8c0e9382e03", "n": 0 }, "scriptSig": "3046022100c352d3dd993a981beba4a63ad15c209275ca9470abfcd57da93b58e4eb5dce82022100840792bc1f456062819f15d33ee7055cf7b5ee1af1ebcc6028d9cdb1c3af774801 04f46db5e9d61a9dc27b8d64ad23e7383a4e6ca164593c2527c038c0857eb67ee8e825dca65046b82c9331586c82e0fd1f633f25f87c161bc6f8a630121df2b3d3" } ], "out": [ { "value": "5.56000000", "scriptPubKey": "OP_DUP OP_HASH160 c398efa9c392ba6013c5e04ee729755ef7f58b32 OP_EQUALVERIFY OP_CHECKSIG", "address": "1JqDybm2nWTENrHvMyafbSXXtTk5Uv5QAn", "next_in": { "hash": "5aa8e36f9423ee5fcf17c1d0d45d6988b8a5773eae8ad25d945bf34352040009", "n": 6 } }, { "value": "44.44000000", "scriptPubKey": "OP_DUP OP_HASH160 948c765a6914d43f2a7ac177da2c2f6b52de3d7c OP_EQUALVERIFY OP_CHECKSIG", "address": "1EYTGtG4LnFfiMvjJdsU7GMGCQvsRSjYhx", "next_in": { "hash": "220ebc64e21abece964927322cba69180ed853bb187fbc6923bac7d010b9d87a", "n": 0 } } ], "nid": "fc7704fdd7ec5e69163e51b827fea2133990a26defee2b475408b3c16fd9a968" }, { "hash": "6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4", "ver": 1, "vin_sz": 1, "vout_sz": 2, "lock_time": 0, "size": 257, "in": [ { "prev_out": { "hash": "cf4e2978d0611ce46592e02d7e7daf8627a316ab69759a9f3df109a7f2bf3ec3", "n": 1 }, "scriptSig": "30440220032d30df5ee6f57fa46cddb5eb8d0d9fe8de6b342d27942ae90a3231e0ba333e02203deee8060fdc70230a7f5b4ad7d7bc3e628cbe219a886b84269eaeb81e26b4fe01 04ae31c31bf91278d99b8377a35bbce5b27d9fff15456839e919453fc7b3f721f0ba403ff96c9deeb680e5fd341c0fc3a7b90da4631ee39560639db462e9cb850f" } ], "out": [ { "value": "0.01000000", "scriptPubKey": "OP_DUP OP_HASH160 b0dcbf97eabf4404e31d952477ce822dadbe7e10 OP_EQUALVERIFY OP_CHECKSIG", "address": "1H8ANdafjpqYntniT3Ddxh4xPBMCSz33pj", "next_in": { "hash": "ae1933ba2b7dc9702c96b99fb00f1df1392d9dea998a24b88d61974e8da8d2ab", "n": 0 } }, { "value": "2.99000000", "scriptPubKey": "OP_DUP OP_HASH160 6b1281eec25ab4e1e0793ff4e08ab1abb3409cd9 OP_EQUALVERIFY OP_CHECKSIG", "address": "1Am9UTGfdnxabvcywYG2hvzr6qK8T3oUZT", "next_in": { "hash": "20ed3fc9688a13fceeae5fdd606266c351b1f15b90404d9df387644e4c3d5b90", "n": 3 } } ], "nid": "fe8c78250fb2a8e5a91e60a93ca7ddaf048a0d0d7dfb5663456c2265a0a0aaea" }, { "hash": "e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d", "ver": 1, "vin_sz": 1, "vout_sz": 1, "lock_time": 0, "size": 225, "in": [ { "prev_out": { "hash": "f4515fed3dc4a19b90a317b9840c243bac26114cf637522373a7d486b372600b", "n": 0 }, "scriptSig": "3046022100bb1ad26df930a51cce110cf44f7a48c3c561fd977500b1ae5d6b6fd13d0b3f4a022100c5b42951acedff14abba2736fd574bdb465f3e6f8da12e2c5303954aca7f78f301 04a7135bfe824c97ecc01ec7d7e336185c81e2aa2c41ab175407c09484ce9694b44953fcb751206564a9c24dd094d42fdbfdd5aad3e063ce6af4cfaaea4ea14fbb" } ], "out": [ { "value": "0.01000000", "scriptPubKey": "OP_DUP OP_HASH160 39aa3d569e06a1d7926dc4be1193c99bf2eb9ee0 OP_EQUALVERIFY OP_CHECKSIG", "address": "16FuTPaeRSPVxxCnwQmdyx2PQWxX6HWzhQ", "next_in": { "hash": "1ebf2dd645b815a59e35485dd4ceebc0587a1b7588b810e42085b479ce507bfa", "n": 1 } } ], "nid": "9e763d097af86cb157abacc0bdb3e31db5968390d065f2af0453e3f03c9260b0" } ], "mrkl_tree": [ "8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87", "fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4", "6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4", "e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d", "ccdafb73d8dcd0173d5d5c3c9a0770d0b3953db889dab99ef05b1907518cb815", "8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49", "f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766" ], "next_block": "00000000000080b66c911bd5ba14a74260057311eaeb1982802f7010f1a9f090" }
- 計算區塊hash
看一下
"hash": "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506",
這個值怎麼來的
import codecs
import hashlib
import struct
ver = 1
prev_block = "000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250"
mrkl_root = "f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766"
time = 1293623863
bits = 453281356
nonce = 274148111
coefficient = bits & 0xffffff
exponent = bits >> 24
target = coefficient * (256 ** (exponent - 3))
# < 代表小端序 # L 代表 unsigned long
hex_str = struct.pack("<L", ver) + codecs.decode(prev_block, 'hex_codec')[::-1] + codecs.decode(mrkl_root, 'hex_codec')[
::-1] + struct.pack("<LLL", time,
bits, nonce)
hash_str = hashlib.sha256(hashlib.sha256(hex_str).digest()).digest()
# 這就是bitcoin礦機的工作 , 找到一個合適的nonce
# 使得做2次sha256運算的結果符合某個條件
block_hash = hash_str[::-1].hex()
print(block_hash) #output:000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506
計算過程:
首先把 ver
, prev_block
, mrkl_root
, time
, bits
, nonce
拼接起來,得到 header_hex
。
在拼接之前需要先把 ver
, time
, bits
, nonce
轉換為十六進位制字串,然後將這六個屬性由大端序轉換為小端序,最後才拼接成一個字串。
然後做兩次 sha256 計算,這一步也就是挖礦做的工作:找到一個 nonce 使得這個結果滿足某個條件(比如前八位都是 0)。
hash = hashlib.sha256(hashlib.sha256(header_bin).digest()).digest()
最後將結果轉回大端序,即為當前區塊的地址。
- 計算merkle tree root
mrkl_root怎麼出來的呢?
接著算
"mrkl_tree": [
"8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87", H1
"fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4", H2
"6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4", H3
"e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d", H4
"ccdafb73d8dcd0173d5d5c3c9a0770d0b3953db889dab99ef05b1907518cb815", H12
"8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49", H34
"f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766" Hroot
],
tx1 = "8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87"
tx2 = "fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4"
tx3 = "6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4"
tx4 = "e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d"
tx1 = codecs.decode(tx1, 'hex_codec')[::-1]
tx2 = codecs.decode(tx2, 'hex_codec')[::-1]
tx3 = codecs.decode(tx3, 'hex_codec')[::-1]
tx4 = codecs.decode(tx4, 'hex_codec')[::-1]
tx12 = hashlib.sha256(hashlib.sha256(tx1 + tx2).digest()).digest()
print(tx12[::-1].hex()) #output:ccdafb73d8dcd0173d5d5c3c9a0770d0b3953db889dab99ef05b1907518cb815
tx34 = hashlib.sha256(hashlib.sha256(tx3 + tx4).digest()).digest()
print(tx34[::-1].hex()) #output:8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49
tx1234 = hashlib.sha256(hashlib.sha256(tx12 + tx34).digest()).digest()
print(tx1234[::-1].hex()) #output:f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766
- 計算交易hash
那麼
tx1 = "8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87"
tx2 = "fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4"
tx3 = "6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4"
tx4 = "e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d"
這幾個值又是從哪兒來的呢?最開始的原始資料說了有4條交易資料
#0100000050120119172a610421a6c3011dd330d9df07b63616c2cc1f1cd00200000000006657a9252aacd5c0b2940996ecff952228c3067cc38d4885efb5a4ac4247e9f337221b4d4c86041b0f2b5710
#04
#01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08044c86041b020602ffffffff0100f2052a010000004341041b0e8c2567c12536aa13357b79a073dc4444acb83c4ec7a0e2f99dd7457516c5817242da796924ca4e99947d087fedf9ce467cb9f7c6287078f801df276fdf84ac00000000
#0100000001032e38e9c0a84c6046d687d10556dcacc41d275ec55fc00779ac88fdf357a187000000008c493046022100c352d3dd993a981beba4a63ad15c209275ca9470abfcd57da93b58e4eb5dce82022100840792bc1f456062819f15d33ee7055cf7b5ee1af1ebcc6028d9cdb1c3af7748014104f46db5e9d61a9dc27b8d64ad23e7383a4e6ca164593c2527c038c0857eb67ee8e825dca65046b82c9331586c82e0fd1f633f25f87c161bc6f8a630121df2b3d3ffffffff0200e32321000000001976a914c398efa9c392ba6013c5e04ee729755ef7f58b3288ac000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00000000
#0100000001c33ebff2a709f13d9f9a7569ab16a32786af7d7e2de09265e41c61d078294ecf010000008a4730440220032d30df5ee6f57fa46cddb5eb8d0d9fe8de6b342d27942ae90a3231e0ba333e02203deee8060fdc70230a7f5b4ad7d7bc3e628cbe219a886b84269eaeb81e26b4fe014104ae31c31bf91278d99b8377a35bbce5b27d9fff15456839e919453fc7b3f721f0ba403ff96c9deeb680e5fd341c0fc3a7b90da4631ee39560639db462e9cb850fffffffff0240420f00000000001976a914b0dcbf97eabf4404e31d952477ce822dadbe7e1088acc060d211000000001976a9146b1281eec25ab4e1e0793ff4e08ab1abb3409cd988ac00000000
#01000000010b6072b386d4a773235237f64c1126ac3b240c84b917a3909ba1c43ded5f51f4000000008c493046022100bb1ad26df930a51cce110cf44f7a48c3c561fd977500b1ae5d6b6fd13d0b3f4a022100c5b42951acedff14abba2736fd574bdb465f3e6f8da12e2c5303954aca7f78f3014104a7135bfe824c97ecc01ec7d7e336185c81e2aa2c41ab175407c09484ce9694b44953fcb751206564a9c24dd094d42fdbfdd5aad3e063ce6af4cfaaea4ea14fbbffffffff0140420f00000000001976a91439aa3d569e06a1d7926dc4be1193c99bf2eb9ee088ac00000000
所以直接對這每條交易資料的原始hex進行hash就得到了merkle tree的最下面一層的hash值
txHex = '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08044c86041b020602ffffffff0100f2052a010000004341041b0e8c2567c12536aa13357b79a073dc4444acb83c4ec7a0e2f99dd7457516c5817242da796924ca4e99947d087fedf9ce467cb9f7c6287078f801df276fdf84ac00000000'
txHash = hashlib.sha256(hashlib.sha256(codecs.decode(txHex, 'hex_codec')).digest()).digest()
print(txHash[::-1].hex()) #output:8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87
txHex = '0100000001032e38e9c0a84c6046d687d10556dcacc41d275ec55fc00779ac88fdf357a187000000008c493046022100c352d3dd993a981beba4a63ad15c209275ca9470abfcd57da93b58e4eb5dce82022100840792bc1f456062819f15d33ee7055cf7b5ee1af1ebcc6028d9cdb1c3af7748014104f46db5e9d61a9dc27b8d64ad23e7383a4e6ca164593c2527c038c0857eb67ee8e825dca65046b82c9331586c82e0fd1f633f25f87c161bc6f8a630121df2b3d3ffffffff0200e32321000000001976a914c398efa9c392ba6013c5e04ee729755ef7f58b3288ac000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00000000'
txHash = hashlib.sha256(hashlib.sha256(codecs.decode(txHex, 'hex_codec')).digest()).digest()
print(txHash[::-1].hex()) #output:fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4
txHex = '0100000001c33ebff2a709f13d9f9a7569ab16a32786af7d7e2de09265e41c61d078294ecf010000008a4730440220032d30df5ee6f57fa46cddb5eb8d0d9fe8de6b342d27942ae90a3231e0ba333e02203deee8060fdc70230a7f5b4ad7d7bc3e628cbe219a886b84269eaeb81e26b4fe014104ae31c31bf91278d99b8377a35bbce5b27d9fff15456839e919453fc7b3f721f0ba403ff96c9deeb680e5fd341c0fc3a7b90da4631ee39560639db462e9cb850fffffffff0240420f00000000001976a914b0dcbf97eabf4404e31d952477ce822dadbe7e1088acc060d211000000001976a9146b1281eec25ab4e1e0793ff4e08ab1abb3409cd988ac00000000'
txHash = hashlib.sha256(hashlib.sha256(codecs.decode(txHex, 'hex_codec')).digest()).digest()
print(txHash[::-1].hex()) #output:6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4
txHex = '01000000010b6072b386d4a773235237f64c1126ac3b240c84b917a3909ba1c43ded5f51f4000000008c493046022100bb1ad26df930a51cce110cf44f7a48c3c561fd977500b1ae5d6b6fd13d0b3f4a022100c5b42951acedff14abba2736fd574bdb465f3e6f8da12e2c5303954aca7f78f3014104a7135bfe824c97ecc01ec7d7e336185c81e2aa2c41ab175407c09484ce9694b44953fcb751206564a9c24dd094d42fdbfdd5aad3e063ce6af4cfaaea4ea14fbbffffffff0140420f00000000001976a91439aa3d569e06a1d7926dc4be1193c99bf2eb9ee088ac00000000'
txHash = hashlib.sha256(hashlib.sha256(codecs.decode(txHex, 'hex_codec')).digest()).digest()
print(txHash[::-1].hex()) #output:e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d
- 挖礦難度
"bits": 453281356,
計算區塊hash的使用用到一個bits,這個bits就代表了挖礦的難度
coefficient = bits & 0xffffff exponent = bits >> 24 target = coefficient * (256 ** (exponent - 3))簡單說
453281356二進位制為0x1b04864c,前2個位元組為exponent,後6個位元組為coefficient。
為了使區塊頭的SHA256結果小於某個目標值(target),平均要嘗試的計算次數,定義為難度(difficulty),
1 difficulty ≈ 2^32次 = 4294967296次 ≈ 4.2 * 10^9次 ≈ 4G次運算
創世區塊的bits為 0x1d00ffff
難度 difficulty_當前 = target_創世區塊 / target_當前
出塊時間(單位:秒) ≈ difficulty_當前 * 2^32 / 全網算力
難度調節
Difficulty_新 = Difficulty_原 * ( 20160分鐘 / 產生2016個區塊的實際花費時長 ) 從創世區塊起,每產生2016個區塊,網路中的所有全節點都會自動調整難度,以保證比特幣約十分鐘的出塊速度
挖礦的過程本質就是找到一個nonce,使算出來的hash小於target。那為什麼通常說的比特幣就是算以多少個0開頭的hash是什麼意思呢
print(hex(bits)) # 0x1b04864c
print(hex(coefficient))
print(hex(exponent))
print("{0:#0{1}x}".format(target, 64 + 2))
output:
0x000000000004864c000000000000000000000000000000000000000000000000
因為區塊的hash是64位,所以比0x000000000004864c000000000000000000000000000000000000000000000000小的話,必然前面是0x00000000000開頭。