NEMの取引履歴ネットワークから取引所アドレスを抽出する

#経緯
<img width="700" alt="スクリーンショット 2018-12-16 0.18.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/242744/b5c8d925-6850-5b8a-2fca-d2b3fe1c0d33.png">

半年ほど前に[Nem Network Neon] (https://nemneon-70055.firebaseapp.com/)というNEMの取引履歴からアドレスのつながりを可視化するアプリを作りました。

ネットワーク分析の手法を使うことで、このアプリから出力される取引履歴のなかから取引所のアドレスを見つけてみます。

(結論からいうと、見つかります)

# 取引履歴を取得
https://nemneon-70055.firebaseapp.com/ のテキストボックスに適当なアドレスを入れて、繋がりの次数を**4**、1ノードに対して取得するトランザクションを**10**にしてSearchします。
これにより、中心となるアドレスから4次のつながりまで、1アドレスあたり10件を最大値として探索します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242744/ec37f76c-cdeb-5cec-20e3-f2eaaa4cc69f.png)

最大で10^4個のアドレスが見つかるはずですが、重複や取引数が少ない場合があるので1,000~10,000個のアドレスが探索できると思います。

すべてのサーチには時間がかかってしまうので、数分くらいで打ち切って「グラフを表示」を押して表示に移ります。

<img width="1440" alt="スクリーンショット 2018-12-15 20.59.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/242744/5d7c24b1-64da-3635-cb66-5b9be1944639.png">

とんでもない数のグラフが出てきてブラウザもびっくり。**動作が重くなります。**
グラフは重すぎて見れないと思いますので、「データをテキスト表示」にいって取引ログだけ取得します*。

<img width="939" alt="スクリーンショット 2018-12-15 23.47.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/242744/5ebaba7a-2d32-081f-034b-0ea9e1d383d5.png">


# 集めたデータ
**約2600のアドレスと5200のトランザクション**が集まりました。
NEMのユーザー人口を正確に知っているわけではないですが、サンプルとしては悪くない割合になってそうです。





# NetworkXで可視化
pythonのpandasとnetworkxを用いて解析を行います。
先ほど入手したデータを以下のような形式のCSVに変換し、transaction.csvとして保存します。


<img width="808" alt="スクリーンショット 2018-12-15 23.46.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/242744/3340a794-cfab-d06d-de73-1c15aae51148.png">


それをvectorに変換しnetworkxのGraphインスタンスに渡してあげます。
以下のようなコードでできます。

```notworkx.py
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
from community import community_louvain

plt.figure(figsize = (10, 10))
df_ft = pd.read_csv("transaction.csv")

vector = {}
for i in pd.concat([df_ft.iloc[:,0],df_ft.iloc[:,1]]).unique():
    vector[i] = []

for i in range(len(df_ft)):
    vector[df_ft.iloc[i,0]].append(df_ft.iloc[i,1])

G = nx.Graph(vector)

nx.draw_networkx(G,with_labels=False)
plt.show()

```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242744/e4ccbb9e-f490-a324-805b-a0f6deb7628a.png)


# 代表的な特徴量
networkxのメソッドを使って代表的な特徴量を求めると以下のようになりました。
[特徴量について](https://qiita.com/maatumoDev/items/ab6a78390cfb7a8cc068)


平均次数 : 3.68
平均経路長 : 4.48
クラスタ係数 : 0.00508
次数分布 : 下図
<img width="300" alt="スクリーンショット 2018-12-15 23.27.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/242744/c65ccdbf-39d2-5954-5376-5253a1551958.png">

クラスタ係数がかなり低い値を取っています。**小規模コミュニティ内で活発に送金しあうみたいな関係はまだ少ないのかな？**


## 取引所のアカウントを特定する
2600あるアドレスの中で、取引所のアドレスが抽出できないかを試します。
取引所はネットワークにおけるHubとなっていると考えられるので、媒介中心性という指標によってスコア付けします。

要は、**離れたノード同士を繋ぐ近道のようになっているアカウントに高いスコアをつけます。**

```
nx.betweenness_centrality(G)
```

によって、媒介中心性を計算し、ランキングを作成すると以下のようになりました。

```
NBGFLNRGN7QNSMDJ5XRJTLPJS6AGRKUAYTYXFUCK: 0.2162768344148873
ND2JRPQIWXHKAA26INVGA7SREEUMX5QAI6VU7HNR: 0.08638790971640656
NDTJM4XDZBNI5Z2YA7NGYD2VYDQSADFYIKQENVWE: 0.07095099671831129
NBQ73BYLVGMO7L2WFG2VVOJHOBWWJKW7D3V7UE4E: 0.06315006280213961
NAGJG3QFWYZ37LMI7IQPSGQNYADGSJZGJRD2DIYA: 0.05689201429017033
NB7GV3ELFTJ3OFA35N6RVVE5NOFPESN4CI3MM2EJ: 0.05086532189133895
NBZMQO7ZPBYNBDUR7F75MAKA2S3DHDCIFG775N3D: 0.048117151006199364
NDBRUFE7R5OANEDE43VCTMUVRHTI6XZ7TQFVNTMU: 0.04690431473665636
NCR2CQE6AI3DIRHPHEPBSVDBOQFSHXFSQF4NIUAH: 0.041245137408139836

...
```

上位5つのアドレス調べてみると、どうやら

1 怪しいアカウント? (https://forum.nem.io/t/unwanted-transaction/19513)
2 **Bittrex**
3 不明
4 **Cryptopia**
5 **Zaif**

となっています。
媒介中心性という特徴だけでも、**大手取引所や香ばしいアドレスを見つけられる...！**

#さいごに
ざっと集めた取引履歴からネットワークを作って、特徴を分析するだけで取引所が抽出できました。
さらに多くの取引履歴や特徴量を使うことで、面白い解析ができるかもしれません。

#参考
https://qiita.com/golang/items/dcc3eadea372b016eea6
Nem Libraryの使い方を@golangに教えてもらいました。

https://qiita.com/Hiroyuki1993/items/ac3ad3029eba8d4b6eb6
Networkx について

※注・ネットワーク分析の文脈では、今回取得した取引ログはEgocentric Networkの重ね合わせなので、解析対象として正確ではない気がします。ただ今回はそこまで深いこと考えずに単に多くのノードを集める目的で使いました。