像比特幣、以太坊這樣的區(qū)塊鏈中包含了大量的數(shù)據(jù),可以幫助 我們洞察區(qū)塊鏈生態(tài)系統(tǒng)中用戶、企業(yè)和礦工的行為模式等重要信息。 BlockSci是一個C++開發(fā)的高性能的區(qū)塊鏈數(shù)據(jù)分析框架,可以幫助 我們快速進行對比特幣等區(qū)塊鏈的數(shù)據(jù)分析工作。本教程將介紹 BlockSci區(qū)塊鏈數(shù)據(jù)分析框架的安裝方法,并講解如何利用BlockSci 框架進行區(qū)塊鏈數(shù)據(jù)分析。
1、安裝BlockSci框架
BlockSci的主要開發(fā)語言是C++,本地編譯需要GCC 7.2+和CLang 5+。 官方文檔僅提供了Ubuntu 16.04和mac OS10.13下的本地安裝方法, 其他系統(tǒng)可以嘗試本地安裝或使用官方提供的AWS EC2鏡像。
2、BlockSci框架概述
BlockSci包含兩個主要的組件:解析器和分析庫。解析器用來解析 區(qū)塊鏈數(shù)據(jù)并轉(zhuǎn)換為便于執(zhí)行分析任務(wù)的BlockSci數(shù)據(jù)格式。分析庫 則用來編寫數(shù)據(jù)分析任務(wù)。

BlockSci的運行需要大量內(nèi)存,推薦使用64GB內(nèi)存,32GB雖然也可以用 但性能下降非常明顯。
3、BlockSci解析器 / Parser
BlockSci的解析器支持兩種處理原始區(qū)塊鏈數(shù)據(jù)的機制:磁盤模式和RPC模式。
磁盤模式是處理比特幣 區(qū)塊數(shù)據(jù)的推薦模式,它可以直接讀取并解析磁盤上的 比特幣區(qū)塊數(shù)據(jù)文件,因此速度要快得多。但是這也意味著磁盤模式不能 支持更多的區(qū)塊鏈,因為不同的區(qū)塊鏈的磁盤數(shù)據(jù)文件格式不同。
使用以下命令以磁盤模式解析比特幣區(qū)塊數(shù)據(jù):
blocksci_parser --output-directory bitcoin-data update disk --coin-directory .bitcoin
參數(shù)說明:
- –output-directory:解析結(jié)果輸出目錄
- –coin-directory:bitcoin core數(shù)據(jù)目錄
RPC模式使用數(shù)據(jù)加密貨幣區(qū)塊鏈節(jié)點的RPC接口來提取數(shù)據(jù),而RPC接口是 大多數(shù)(山寨幣)區(qū)塊鏈都支持的與比特幣類似的二次開發(fā)接口(雖然優(yōu)勢也有一些差異), 因此在比特幣之外的區(qū)塊鏈數(shù)據(jù)解析,BlockSci通常采用RPC模式, 例如對于Zcash和Namecoin。
要使用RPC模式的BlockSci解析器,需要一個區(qū)塊鏈全節(jié)點并且啟用txindex選項。 命令格式如下:
blocksci_parser --output-directory bitcoin-data update rpc --username [user] --password [pass] --address [ip] --port [port]
參數(shù)說明:
- –output-directory:解析結(jié)果輸出目錄
- –username:RPC API用戶名
- –password:RPC API用戶密碼
- –address:RPC API監(jiān)聽地址
- –port:RPC API監(jiān)聽端口
4、BlockSci分析庫 / Analysis Library
一旦利用解析器提取了區(qū)塊鏈數(shù)據(jù),就可以利用BlockSci的分析庫來執(zhí)行數(shù)據(jù)分析 任務(wù)了。BlockSci目前支持兩種語言來開發(fā)區(qū)塊鏈數(shù)據(jù)分析應(yīng)用:C++和Python。
要使用C++版本的BlockSci分析庫,需要添加必要的BlockSci頭文件并鏈接BlockSci 動態(tài)庫。然后就可以利用解析器輸出目錄里的數(shù)據(jù)進行分析了,例如下面的代碼:
#include <blocksci/blocksci.hpp> int main(int argc, const char * argv[]) { blocksci::Blockchain chain{"file_path_to_output-directory"}; }
BlockSci目前僅支持Python 3,使用方法很簡單:導(dǎo)入BlockSci庫,然后利用 解析器輸出目錄的數(shù)據(jù)構(gòu)建Blockchain對象:
import blocksci chain = blocksci.Blockchain("file_path_to_parser_output-directory")
5、BlockSci區(qū)塊鏈數(shù)據(jù)分析示例
這一部分我們使用Python版本的BlockSci來介紹如何進行比特幣區(qū)塊鏈的數(shù)據(jù) 分析。
首先導(dǎo)入必要的庫并利用解析器輸出數(shù)據(jù)構(gòu)建BlockSci的Blockchain對象:
import blocksci import matplotlib.pyplot as plt import matplotlib.ticker import collections import pandas as pd import numpy as np chain = blocksci.Blockchain('your_parser_data_directory')
5.1 比特幣地址類型使用情況分類統(tǒng)計
使用BlockSci的區(qū)塊鏈對象的map_blocks()方法統(tǒng)計不同類型的地址 在每年的使用量:
net_coins_per_block = chain.map_blocks(lambda block: block.net_address_type_value()) df = pd.DataFrame(net_coins_per_block).fillna(0).cumsum()/1e8 df = chain.heights_to_dates(df) df = df.rename(columns={t:str(t) for t in df.columns}) ax = df.resample("W").mean().plot() ax.set_ylim(ymin=0)
顯示結(jié)果如下:

可以看到P2PKH地址的使用從2017年中開始減少,而P2SH地址的 使用同期則開始增加 —— 這應(yīng)該對應(yīng)著各種錢包對隔離見證地址支持 的增加。
5.2 比特幣單區(qū)塊交易手續(xù)費率可視化分析
下面的代碼使用BlockSci的區(qū)塊鏈對象的[]操作符提取 比特幣465100#區(qū)塊內(nèi)各交易的手續(xù)費率并進行可視化分析:
example_block_height = 465100 df = pd.DataFrame(chain[example_block_height].txes.fee_per_byte(), columns=["Satoshis per byte"]) ax = df.reset_index().plot.scatter(x="index", y="Satoshis per byte") ax.set_ylim(0) ax.set_xlim(0) plt.show()
顯示結(jié)果如下:

可以看到該區(qū)塊內(nèi)絕大多數(shù)交易的手續(xù)費率設(shè)置在500SAT/BYTE以內(nèi)。
5.3 比特幣二層協(xié)議使用情況可視化分析
在比特幣交易內(nèi)可以嵌入二層協(xié)議以實現(xiàn)對其他應(yīng)用的支持,例如omni layer 的usdt代幣就是最常見的一種比特幣二層協(xié)議應(yīng)用。下面的代碼 使用BlockSci的區(qū)塊鏈對象的blocks.txes屬性提取在交易輸出中 包含OP_RETURN腳本的交易,并顯示二層協(xié)議的使用情況,可以非常清楚的看到, Omni layer到目前已經(jīng)是二層協(xié)議的最大用戶:
txes = chain.blocks.txes.including_output_of_type(blocksci.address_type.nulldata).all labels = [(tx.block.time, blocksci.label_Application(tx)) for tx in txes] df = pd.DataFrame(labels, columns=["date", "label"]) df = df.reset_index().groupby(["date", "label"]).count().unstack(level=-1).fillna(0) df.columns = df.columns.droplevel() important_columns = list(df[df.index > pd.to_datetime("1-1-2016")].sum().sort_values()[-10:].index) important_columns = [x for x in important_columns if "Address" not in x] ax = df[df.index > pd.to_datetime("1-1-2016")].cumsum().resample("w").mean()[important_columns].plot() ax.set_ylim(0) plt.tight_layout()
顯示結(jié)果如下:

5.4 比特幣2017年各月平均交易手續(xù)費可視化分析
下面的代碼統(tǒng)計年度平均手續(xù)費并將手續(xù)費換算為美元,注意 其中利用了BlockSci分析庫中的CurrencyConverter進行匯率換算:
converter = blocksci.CurrencyConverter() blocks = chain.range('2017') times = blocks.time df = pd.DataFrame({"Fee":fees}, index=times) df = converter.satoshi_to_currency_df(df, chain) ax = df.resample("d").mean().plot(legend=False) ax.set_ylim(ymin=0) plt.tight_layout()
顯示結(jié)果如下:

可以看到在2017年底比特幣手續(xù)費激增。
5.5 比特幣大額手續(xù)費交易可視化分析
下面的代碼分析并可視化歷年來手續(xù)費超過1000美元的比特幣交易:
high_fee_txes = chain.cpp.filter_tx("fee(tx) > 10000000", 0, len(chain)) converter = blocksci.CurrencyConverter() df = pd.DataFrame([(tx.block.height, tx.fee) for tx in high_fee_txes], columns=["height", "fee"]) df.index = df["height"] df["fee"] = df.apply(lambda x: converter.satoshi_to_currency(x["fee"], chain[x["height"]].time), axis=1) df = df[df["fee"] > 1000] df = chain.heights_to_dates(df) fig, ax = plt.subplots() ax.plot_date(df.index, df["fee"], fmt="x") ax.set_yscale("log") formatter = matplotlib.ticker.ScalarFormatter(useoffset=False) formatter.set_scientific(False) ax.yaxis.set_major_formatter(formatter) plt.tight_layout()
顯示結(jié)果如下:

2017年超過1000美元手續(xù)費的交易激增,從一個側(cè)面說明了這一年 涌入了大量數(shù)字加密貨幣的新手。
匯智網(wǎng)原創(chuàng),轉(zhuǎn)載請標(biāo)明出處:http://blog.hubwiz.com/2019/11/25/blocksci-tutorial/