LoginSignup
4
4

More than 5 years have passed since last update.

Blockchain 解析用ソフトウェア: BlockSci を使ってみる

Last updated at Posted at 2017-12-19

この記事は、ブロックチェーン Advent Calendar 2017 の 20 日目の記事です。

概要

BlockSci というのは、Blockchain 解析用のソフトウェアです。
Blockchain を Jupyter Notebook 使って解析したいな〜というときにか〜なり便利です。

注意

インメモリデータベースなので、メモリをかなり食います。AMI をもとに、EC2 にインスタンスをサクッと立ち上げるのが良いでしょう。
公式が公開している AMI を使うと、立ち上げて ssh トンネリングするだけで Jupyter Notebook が使える状態になります。メチャクチャ楽です。
だいたい 3.5 時間後にすべてのデータが読み込まれ、クエリの処理速度が最高速に達します。

導入

Readme にある最新の AMI を元に EC2 インスタンスを立ち上げます。
2017/12/19 現在では ami-7cf38706 が最新となっています。
メモリ領域が 60GB 以上あることが期待されており, r4.2xlarge が推奨されています。

r4.2xlarge は $0.532 / hour なので, スポットインスタンス使わず一ヶ月回すと $383.04 程度かかります。

自分もこの記事のために昨日から回していて、$10 が失われました。
立ち上がると, Jupyter Notebook も起きているので,

ssh -i .ssh/your_private_key.pem -N -L 8888:localhost:8888 ubuntu@your_url.amazonaws.com

したら localhost:8888 へ見に行くだけです。

利用例

事前準備

import blocksci
import matplotlib.pyplot as plt
import matplotlib.ticker
import collections
import pandas as pd
import numpy as np
%matplotlib notebook
# parser_data_directory should be set to the data-directory which the blocksci_parser output
chain = blocksci.Blockchain("/home/ubuntu/bitcoin/")

Class: Block

ref: https://citp.github.io/BlockSci/chain/block.html

# 最新の block を取得
recent_block = chain[len(chain) - 1]
# coinbase
recent_block.coinbase_tx
# hash: ハッシュ
print("hash is", recent_block.hash)
#  height: ブロック高さ
print("height is", recent_block.height)
# input_count: ブロックに含まれるトランザクションインプットの数
print("input count is", recent_block.input_count)
# input_value: ブロックに含まれるトランザクションインプットに含まれる satoshi の総数
print("input value is", recent_block.input_value)
#  inputs: ブロックに含まれるトランザクションインプットを取得
recent_block.inputs
#  net_address_type_value: Returns a set of the net change in the utxo pool after this block split up by address type
print("net_address_type_value is", recent_block.net_address_type_value)
# net_full_type_value(self: blocksci.blocksci_interface.Block)
print("net_full_type_value", recent_block.net_full_type_value)
# next_block: 次のブロック
recent_block.next_block
# nonce: nonce の数値
print("nonce is", recent_block.nonce)
# output_count: ブロックに含まれるトランザクションアウトプットの数
print("output count is", recent_block.output_count)
# output_value: ブロックに含まれるトランザクションアウトプットに含まれる satoshi の総数
print("output value is", recent_block.output_value)
# outsputs: ブロックに含まれるトランザクションアウトプットを取得
recent_block.outputs
# prev_block: 前のブロック
recent_block.prev_block
# size_bytes: ブロックサイズ
print("size bytes is", recent_block.size_bytes)
# time: タイム
print("time is", recent_block.time)
# timestamp: ブロックヘッダのタイムスタンプ
print("timestamp is", recent_block.timestamp)
# total_spent_of_ages: Returns a list of sum of all the outputs in the block that were spent within a certain of blocks, up to the max age given
print("total_spent_of_ages is", recent_block.total_spent_of_ages)
# txes: ブロックに含まれるトランザクションを取得
recent_block.txes
# version: ブロックヘッダのプロトコルバージョン
print("version is", recent_block.version)
hash is 0000000000000000006271a8c189b9591ad06a369e29d24dbe25e6a1819d6cee
height is 498919
input count is 4913
input value is 1290872675640
net_address_type_value is <bound method PyCapsule.net_address_type_value of Block(numTxes=3031, height=498919, header_hash=0000000000000000006271a8c189b9591ad06a369e29d24dbe25e6a1819d6cee, version=536870912, timestamp=1513094055, bits=402698477, nonce=231235938)>
net_full_type_value <bound method PyCapsule.net_full_type_value of Block(numTxes=3031, height=498919, header_hash=0000000000000000006271a8c189b9591ad06a369e29d24dbe25e6a1819d6cee, version=536870912, timestamp=1513094055, bits=402698477, nonce=231235938)>
nonce is 231235938
output count is 6720
output value is 1292122675640
size bytes is 1050481
time is 2017-12-12 15:54:15
timestamp is 1513094055
total_spent_of_ages is <bound method PyCapsule.total_spent_of_ages of Block(numTxes=3031, height=498919, header_hash=0000000000000000006271a8c189b9591ad06a369e29d24dbe25e6a1819d6cee, version=536870912, timestamp=1513094055, bits=402698477, nonce=231235938)>
version is 536870912

CurrencyConverter

converter = blocksci.CurrencyConverter()
converter.satoshi_to_currency(100, recent_block.time.date())
0.0171781025

サンプル

手数料のヒストグラム

USD_JPY_RATE = 112
fees = [converter.satoshi_to_currency(fee, recent_block.time) * USD_JPY_RATE for fee in recent_block.txes.fee]
plt.hist(fees, bins=20, range=(0, 6000))
(array([   6.,    8.,   20.,  217.,  870.,  897.,  464.,  126.,   22.,
         137.,   39.,   21.,   54.,   11.,   12.,   21.,   18.,   14.,
          10.,    4.]),
 array([    0.,   300.,   600.,   900.,  1200.,  1500.,  1800.,  2100.,
         2400.,  2700.,  3000.,  3300.,  3600.,  3900.,  4200.,  4500.,
         4800.,  5100.,  5400.,  5700.,  6000.]),
 <a list of 20 Patch objects>)

output_9_1.png

トランザクションから手数料などを取り出してみる

all_tx = recent_block.txes.all
sample_tx = all_tx[1]
# https://blockchain.info/ja/tx/4fe8cca3318ac086eaf4dcb3958dbd1db324b446591fdb03dbec1342e664570c
print(sample_tx.hash)
fee = sample_tx.fee
input_value = sum(sample_tx.inputs.value)
output_value = sum(sample_tx.outputs.value)
print(fee, input_value, output_value)
print(input_value - output_value == fee)
converter.satoshi_to_currency(fee, recent_block.time.date())
4fe8cca3318ac086eaf4dcb3958dbd1db324b446591fdb03dbec1342e664570c
700000 832822188 832122188
True





120.2467175

最大の手数料を探す

tx = sorted(recent_block.txes.all, key=lambda tx: - tx.fee)[0]
tx.fee
10000000
# それぞれのブロックの最大の手数料を持つ TX のリスト
txes = [sorted(block.txes.all, key=lambda tx: - tx.fee)[0] for block in chain]
fees = [tx.fee for tx in txes]
df = pd.DataFrame({"Fees":fees})
ax = df.plot(legend=False)
ax.set_ylim(ymin=0)
plt.tight_layout()

output_15_0.png

# 最大の手数料を持つ TX
tx = sorted(txes, key=lambda tx: - tx.fee)[0]
print("Maximum fee is %s JPY" % (converter.satoshi_to_currency(tx.fee, recent_block.time) * USD_JPY_RATE))
print("hash is", tx.hash)
print("time is", tx.block.time)
Maximum fee is 560332195.6279321 JPY
hash is cc455ae816e6cdafdb58d54e35d4f46d860047458eacf1c7405dc634631c570d
time is 2016-04-26 14:15:22

I smell a "Where did my money go?" moment : Bitcoin

まあこんな感じで遊べるので, 楽しい。$0.532/hour 失いながら遊んでいきましょう。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4