比特幣區(qū)塊的數(shù)據(jù)維度有哪些括儒?

本文目的

通過上一篇筆記python-bitcoinrpc下載比特幣數(shù)據(jù)Windows(完成)可以直接通過不同的API獲得解析后的區(qū)塊數(shù)據(jù)或交易記錄,本文分析這些數(shù)據(jù)能給我們提供哪些對分析比特幣網(wǎng)絡(luò)有用的信息锐想。

Block原始數(shù)據(jù)維度

getblock.png

利用bitcoinrpc提供的getblock接口可以幫助我們獲取區(qū)塊數(shù)據(jù)帮寻。該接口需要輸入?yún)^(qū)塊哈希,另外一個(gè)可選變量有三個(gè)取值痛倚,0规婆,1,2。

  • 取值為0時(shí)抒蚜,返回原始的16進(jìn)制編碼的數(shù)據(jù)
  • 取值為1時(shí)掘鄙,返回解碼后的字典數(shù)據(jù)
  • 取值為2時(shí),基本和取值為1時(shí)返回結(jié)果一致嗡髓,只在鍵為tx的值中包含了交易的全數(shù)據(jù)
block原始數(shù)據(jù).PNG

上圖展示了在pycharm里面運(yùn)行以下代碼獲得的rawdata返回結(jié)果:

from bitcoinrpc.authproxy import AuthServiceProxy
rpc_connection = AuthServiceProxy("http://%s:%s@127.0.0.1:8332"%('xxx', 'xxx'))best_block_hash = rpc_connection.getbestblockhash()  #獲取當(dāng)前最長鏈的最后一個(gè)區(qū)塊哈希
rawdata = rpc_connection.getblock(best_block_hash)  #獲取指定區(qū)塊哈希的區(qū)塊數(shù)據(jù)

rawdata中包含的數(shù)據(jù)維度有:

# 區(qū)塊數(shù)據(jù)維度
hash              #當(dāng)前區(qū)塊的哈希
confirmations     #當(dāng)前區(qū)塊已被確認(rèn)數(shù)(即后續(xù)跟著的區(qū)塊數(shù)+1操漠,或者可以直接用當(dāng)前區(qū)塊鏈總高度—當(dāng)前區(qū)塊高度+1計(jì)算獲得),需要注意的是饿这,該數(shù)值會隨著新區(qū)塊的不斷增加而變化浊伙,沒必要作為數(shù)據(jù)維度之一存入數(shù)據(jù)庫
strippedsize      #剔除隔離見證數(shù)據(jù)后的區(qū)塊字節(jié)數(shù)
size              #區(qū)塊字節(jié)數(shù)
weight            #BIP141定義的區(qū)塊權(quán)重
height            #當(dāng)前區(qū)塊高度(第一個(gè)區(qū)塊高度為0,于2009-01-04 02:15生成)
version           #區(qū)塊版本(代表支持不同的軟长捧、硬分叉方案)
versionHex        #用16進(jìn)制表示的區(qū)塊版本
merkleroot        #區(qū)塊的默克爾樹根嚣鄙,是根據(jù)當(dāng)前區(qū)塊內(nèi)所有交易哈希生成的默克爾樹的根節(jié)點(diǎn)哈希
tx                #當(dāng)前區(qū)塊包含的交易列表,列表中是交易id
time              #當(dāng)前區(qū)塊創(chuàng)建的時(shí)間戳(unix timestamp)
mediantime        #過去11個(gè)區(qū)塊創(chuàng)建時(shí)間戳的中值(unix timestamp)
nonce             #用于挖礦工作量證明的隨機(jī)數(shù)
bits              #難度目標(biāo)串结,標(biāo)識了當(dāng)前區(qū)塊頭Hash之后要小于等于的目標(biāo)值(target)
difficulty        #區(qū)塊挖礦的難度值
chainwork         #當(dāng)前區(qū)塊鏈的工作量加總
nTx               #當(dāng)前區(qū)塊包含的交易總數(shù)
previousblockhash #當(dāng)前區(qū)塊鏈接的前序區(qū)塊哈希
nextblockhash     #(如有)鏈接當(dāng)前區(qū)塊的后序區(qū)塊哈希

漲知識Tips:

  • BIP即Bitcoin Improvement Proposal的首字字母縮寫哑子,意譯為“比特幣改進(jìn)提議”,每個(gè)BIP都牽涉到對比特幣源碼的改動肌割。而BIP僅僅是提議卧蜓,實(shí)施與否需要社區(qū)達(dá)成共識。
  • BIP141定義了當(dāng)前的比特幣隔離見證激活方案把敞,大概方法是保存區(qū)塊數(shù)據(jù)時(shí)移除比特幣交易過程中的簽名字段弥奸,從而在不擴(kuò)大區(qū)塊大小的情況下實(shí)現(xiàn)“變相擴(kuò)容”。
  • 區(qū)塊頭里面的默克爾樹根是根據(jù)nTx筆交易的哈希作為葉子節(jié)點(diǎn)生成的默克爾樹的根哈希奋早,可參考這篇文章比特幣區(qū)塊結(jié)構(gòu)Merkle樹及簡單支付驗(yàn)證分析中的示意圖理解盛霎。
  • unix時(shí)間戳是從1970年1月1日(UTC/GMT的午夜)開始所經(jīng)過的秒數(shù),不考慮閏秒伸蚯。
  • mediantime用于確認(rèn)區(qū)塊:只有當(dāng)某個(gè)區(qū)塊的時(shí)間戳大于mediantime摩渺,并且小于某個(gè)調(diào)整后的網(wǎng)絡(luò)時(shí)間(p2p網(wǎng)絡(luò)節(jié)點(diǎn)報(bào)時(shí)中值+2小時(shí)?)時(shí)剂邮,這個(gè)區(qū)塊才會被確認(rèn)。

上面理清了區(qū)塊數(shù)據(jù)的維度横侦,其中有助于分析比特幣交易網(wǎng)絡(luò)的維度主要有:

  • hash(可作為區(qū)塊的唯一查詢標(biāo)識)
  • height(可作為區(qū)塊的唯一查詢標(biāo)識并用于排序)
  • tx(最重要的交易數(shù)據(jù))
  • time(時(shí)間戳)
  • nTx (當(dāng)前區(qū)塊包含的交易總數(shù))

獲取交易數(shù)據(jù)

獲取比特幣交易數(shù)據(jù)可以通過兩種途徑:

  1. 使用上述getblock接口并將verbosity設(shè)置為2挥萌,可獲得該區(qū)塊內(nèi)所有交易的詳細(xì)數(shù)據(jù)
rawdata = rpc_connection.getblock(block_hash, 2)
txlist = rawdata['tx']
for txdata in txlist:
    ...
  1. 使用getrawtransaction接口并將verbose設(shè)置為True:


    getrawtransaction.png
txdata = rpc_connection.getrawtransaction(tx_id,True)

這兩種獲得交易數(shù)據(jù)的方法都能返回一致的結(jié)果,下圖是返回結(jié)果對比枉侧,第一種方式適用于一次性獲取某一個(gè)區(qū)塊里的交易列表引瀑;第二種方式適用于查詢某個(gè)已知txid的特定交易數(shù)據(jù),當(dāng)然榨馁,在單獨(dú)查詢交易數(shù)據(jù)時(shí)也會返回交易所屬區(qū)塊的信息(黃框所示)

兩種方式返回結(jié)果對比憨栽,txdata是方式二返回結(jié)果,txlist是方式一返回結(jié)果.jpg

交易數(shù)據(jù)維度

從返回的交易數(shù)據(jù),我們可以獲得以下維度的數(shù)據(jù):

# 交易數(shù)據(jù)維度
txid         #交易id屑柔,和所要查詢的交易id一致
hash         #交易哈希屡萤,對采用隔離驗(yàn)證(segwit)的交易生成的哈希,與txid不同掸宛,若交易未采用隔離驗(yàn)證死陆,則與txid一致
version      #版本
size         #交易數(shù)據(jù)占據(jù)的字節(jié)數(shù)
vsize        #隔離驗(yàn)證后交易數(shù)據(jù)占據(jù)的字節(jié)數(shù)(總是小于size)
weight       #BIP141定義的方法計(jì)算占據(jù)權(quán)重,是vsize的4倍取整
locktime     #該交易能被加入到區(qū)塊內(nèi)的最早時(shí)間
vin          #交易的發(fā)送地址列表
vout         #交易的接收地址列表
hex          #txid16進(jìn)制編碼后的序列

漲知識Tips:

  • 每個(gè)交易都可有多個(gè)發(fā)送地址和多個(gè)接收地址唧瘾,每個(gè)發(fā)送地址都會附帶一個(gè)由發(fā)送地址持有人秘鑰生成的scriptSig措译,即unlocking script,用于解鎖該地址的余額饰序,這個(gè)scriptSig在密碼學(xué)上被稱為“witness”领虹。
  • 交易的txid,是對交易信息進(jìn)行兩次sha256的結(jié)果求豫。
  • 打包交易的節(jié)點(diǎn)有可乘之機(jī)掠械,作惡節(jié)點(diǎn)可以通過對發(fā)送者提供的witness進(jìn)行包裝生成一個(gè)新的txid,而驗(yàn)證節(jié)點(diǎn)驗(yàn)證整個(gè)交易時(shí)察覺不出txid被篡改注祖。這樣作惡節(jié)點(diǎn)就可以欺騙發(fā)送者交易未成功發(fā)送猾蒂,但實(shí)際上交易已經(jīng)以另一個(gè)txid上鏈了,導(dǎo)致發(fā)送者掉入重復(fù)支付陷阱是晨。
  • BIP141建議的隔離驗(yàn)證肚菠,是將witness從交易數(shù)據(jù)中分離出來,放在區(qū)塊底部罩缴,這樣按原來方式算txid就不包括驗(yàn)證信息了蚊逢,而包括驗(yàn)證信息生成的即為hash:
    txID: [nVersion][txins][txouts][nLockTime]
    hash: [nVersion][marker][flag][txins][txouts][witness][nLockTime]
    這就是交易數(shù)據(jù)里面txid和hash有可能不一樣的原因。
  • 有關(guān)segregated witness如何擴(kuò)容的解釋可參考這篇Medium文章

因?yàn)樵趖xin引用前序交易時(shí)都是指向前序交易的txid箫章,故在保存交易數(shù)據(jù)時(shí)以txid作為其唯一標(biāo)識比較方便烙荷。其他維度中對分析比特幣交易網(wǎng)絡(luò)比較有用的就是vin和vout了,在下面詳細(xì)展開檬寂。

vin和vout包含的內(nèi)容

每一個(gè)區(qū)塊可能包含多筆交易终抽,但第一筆交易都是系統(tǒng)直接向礦工發(fā)送,金額是當(dāng)下挖礦獎勵(lì)+該區(qū)塊內(nèi)的手續(xù)費(fèi)加總桶至。數(shù)據(jù)格式如下:

vin=[{"coinbase": "xxxxxx很長的一串字符串xxxxxx",
      "sequence": 0}]

vout=[{"value": Decimal("12.64059504"),
       "n": 0昼伴,
       "scriptPubKey": {"asm": "xxx",
                        "hex": "xxx", 
                        "reqSigs": 1, 
                        "type": "pubkeyhash", 
                        "addresses": ["xxx"]}
      },
      {"value": Decimal("0E-8"),
       "n": 1,
       "scriptPubKey": {"asm": "xxx",
                        "hex": "xxx",
                        "type": "nulldata"}
      },
      ...]

vin是發(fā)送方地址列表,如果一個(gè)vin列表中只有一個(gè)字典镣屹,并且其中存在鍵“coinbase”圃郊,就可以判斷該筆交易是礦工獎勵(lì)。
vout是接收方地址列表女蜈,可能有一至多個(gè)接收方持舆,每個(gè)接收方用一個(gè)字典表示色瘩,一般包含:

value          #接收到的比特幣數(shù)額,八位小數(shù)
n              #接收方的排序號逸寓,從0開始居兆,便于后續(xù)花費(fèi)時(shí)引用該筆txid,并指明是第n筆
scriptPubKey   #接收方信息
  - asm        #用于分析scriptPubKey的腳本席覆,不同type對應(yīng)的asm不同
  - hex        #asm的16進(jìn)制編碼
  - type       #接收方地址類型史辙,可以是pubkeyhash, scripthash, witness_v0_scripthash, multisig, nulldata等
  - reqSigs    #要求的簽名數(shù)
  - addresses  #接收方地址,是個(gè)列表佩伤,多重簽名時(shí)可能會有多個(gè)地址

實(shí)際上聊倔,vout的接收方可有多種類型,具體可參考An Analysis of Non-standard Transactions這篇論文【1】生巡,里面詳細(xì)介紹了標(biāo)準(zhǔn)交易類型和非標(biāo)準(zhǔn)交易類型耙蔑。

標(biāo)準(zhǔn)交易類型(Standard Type)

  1. P2PKH(比特幣網(wǎng)絡(luò)默認(rèn)類型)
  2. P2PK (多出現(xiàn)在礦工接收獎勵(lì)和手續(xù)費(fèi)的coinbase交易中)
  3. Multi-signature (多簽)
  4. P2SH(將另一筆交易的script哈希后作為新script,壓縮字節(jié))
  5. P2WPKH孤荣、P2WSH:隔離見證采用后P2PKH的另一種實(shí)現(xiàn)方式甸陌,字節(jié)占用更少,且簽名從unlocking script中移出
  6. nulldata (OP_RETURN): 隔離見證采用后用于存儲見證信息的默克爾樹根( Merkle root of the witness tree)盐股,在coinbase交易的接收方出現(xiàn)钱豁,該筆output將直接從UTXO中移除,后續(xù)不能被花費(fèi)疯汁,轉(zhuǎn)移的比特幣數(shù)量一般都為零牲尺。vout中沒有reqSigs和addresses這兩對鍵值。

論文【1】及Bitcoin Wiki對Transaction的描述信息中介紹了幾種交易類型的腳本形式(asm)幌蚊,例如:

# Pay-to-PubkeyHash(P2PKH)
scriptPubKey: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
scriptSig: <sig> <pubKey>

其中scriptPubKey是locking script, 保存在vouts里谤碳,scriptSig是發(fā)送方用于解鎖發(fā)送地址中比特幣的簽名信息(unlocking script),在非coinbase交易中的vin出現(xiàn):

vin=[{"txid": "xxx", 
      "vout": 0,
      "scriptSig": {"asm": "xxx",
                    "hex": "xxx"},
      "sequence": 4294967295},
      ...]

注意:非coinbase交易的vin沒有直接給出發(fā)送方地址信息溢豆,而是告訴我們該筆交易花費(fèi)的前序交易“txid”及“vout”蜒简,“vout”是某一筆花費(fèi)在該前序交易中的接收方排序,即前面分析的vout中的“n”對應(yīng)的值漩仙。通過這個(gè)信息需要再去查詢指定“txid”的第“vout”個(gè)接收方地址搓茬,才能獲得該筆交易的發(fā)送方地址。另外一個(gè)數(shù)據(jù)維度讯赏,sequence垮兑,是不經(jīng)常用到的一個(gè)序列號,用于更改帶時(shí)間鎖的交易漱挎,詳細(xì)可參考官方說明:locktime-and-sequence-number

原則上雀哨,節(jié)點(diǎn)驗(yàn)證程序會通過isStandard()及isStandardTx()兩個(gè)函數(shù)分別驗(yàn)證所有outputs和inputs是否采用標(biāo)準(zhǔn)交易形式磕谅。但一些礦工節(jié)點(diǎn)修改了程序私爷,導(dǎo)致區(qū)塊里也會打包一些非標(biāo)準(zhǔn)交易,但它們所占的比例很少(0.02%)膊夹。

非標(biāo)準(zhǔn)交易類型(Nonstandard Type):

  1. 疑似DDOS攻擊:例如Transaction: 2a0597e665ac3d1cabeede95cedf907934db7f639e477b3c77b242140d8cf728在scriptPubKey中寫入上百個(gè)OP_CHECKSIG(消耗驗(yàn)證節(jié)點(diǎn)的計(jì)算量)衬浑,該筆output可以被后續(xù)花費(fèi)。
  2. P2PKH NOP: 在P2PKH的script形式上末尾加了OP_NOP放刨,用于測試未來的某些新功能工秩,例如Transaction: db3f14e43fecc80eb3e0827cecce85b3499654694d12272bf91b1b2b8c33b5cb,該筆交易可以被后續(xù)花費(fèi)进统。
  3. P2PKH 0: script形式與P2PKH一樣助币,但是在public key hash的位置填寫的是0,由于0不是有效公鑰哈希螟碎,導(dǎo)致該筆output無法被后續(xù)花費(fèi)眉菱,也沒有接收方地址,轉(zhuǎn)移的金額相當(dāng)于銷毀了掉分。

總結(jié)

本文分析了JSON-bitcoinrpc的若干接口俭缓,

  1. 通過getblockhash()接口,可獲得指定height的區(qū)塊hash酥郭;
  2. 通過getblock()接口华坦,可獲得指定區(qū)塊hash的區(qū)塊數(shù)據(jù),設(shè)定第二個(gè)參數(shù)為2可獲得全量交易數(shù)據(jù)列表不从;
  3. 通過getrawtransaction()接口惜姐,可獲得單個(gè)指定txid的交易數(shù)據(jù);
  4. 通過getbestblockhash()接口消返,可獲得當(dāng)前最長鏈最后一個(gè)被確認(rèn)區(qū)塊的hash载弄。

另,下面代碼示例可實(shí)現(xiàn)批量獲取返回結(jié)果:

commands1 = [["getblockhash", height] for height in range(100)]
block_hashes = rpc_connection.batch_(commands1)
commands2 = [["getblock", h] for h in block_hashes]
blocks = rpc_connections.batch_(commands2)

對分析比特幣交易網(wǎng)絡(luò)有用的信息主要就是:

  1. 區(qū)塊相關(guān)的數(shù)據(jù)
  • hash(可作為區(qū)塊的唯一查詢標(biāo)識)
  • height(可作為區(qū)塊的唯一查詢標(biāo)識并用于排序)
  • time(時(shí)間戳)
  • nTx (當(dāng)前區(qū)塊包含的交易總數(shù))
  1. 交易相關(guān)的數(shù)據(jù)
  • txid
  • vin撵颊,判斷是否coinbase宇攻,引用的前序交易txid及排序號vout
  • vout, 接收方列表(每個(gè)接收方包括value, 排序號n, scriptPubKey中的type, reqSigs, addresses)
  • blockhash 交易所屬區(qū)塊的哈希
  1. 派生數(shù)據(jù)
  • 手續(xù)費(fèi),發(fā)送方總金額—接收方總金額的差值為支付給礦工的手續(xù)費(fèi)
  • 找零倡勇,推斷找零地址及找零余額
  • multi-input heuristic
  • 通過hash和txid是否一致判斷該交易是否采用隔離見證

由于數(shù)據(jù)量龐大逞刷,如果要存在數(shù)據(jù)庫中,下一步是設(shè)計(jì)數(shù)據(jù)倉庫結(jié)構(gòu)妻熊,以便能夠有效地查詢到所需數(shù)據(jù)夸浅。

(記于2019年12月31日 漠水云)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市扔役,隨后出現(xiàn)的幾起案子帆喇,更是在濱河造成了極大的恐慌,老刑警劉巖亿胸,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坯钦,死亡現(xiàn)場離奇詭異预皇,居然都是意外死亡痊土,警方通過查閱死者的電腦和手機(jī)嚎货,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來梅鹦,“玉大人突颊,你說我怎么就攤上這事鲁豪。” “怎么了律秃?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵爬橡,是天一觀的道長。 經(jīng)常有香客問我友绝,道長堤尾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任迁客,我火速辦了婚禮郭宝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掷漱。我一直安慰自己粘室,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布卜范。 她就那樣靜靜地躺著衔统,像睡著了一般。 火紅的嫁衣襯著肌膚如雪海雪。 梳的紋絲不亂的頭發(fā)上锦爵,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天,我揣著相機(jī)與錄音奥裸,去河邊找鬼险掀。 笑死,一個(gè)胖子當(dāng)著我的面吹牛湾宙,可吹牛的內(nèi)容都是我干的樟氢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼侠鳄,長吁一口氣:“原來是場噩夢啊……” “哼埠啃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起伟恶,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤碴开,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后博秫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叹螟,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鹃骂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年台盯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了罢绽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,992評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡静盅,死狀恐怖良价,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蒿叠,我是刑警寧澤明垢,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站市咽,受9級特大地震影響痊银,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜施绎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一溯革、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谷醉,春花似錦致稀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至遇八,卻和暖如春矛绘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背刃永。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工货矮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人揽碘。 一個(gè)月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓次屠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親雳刺。 傳聞我的和親對象是個(gè)殘疾皇子劫灶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評論 2 355