アルゴリズムとかオーダーとか

仕事で勉強したことなどをまとめてます

go-ethereumのpruningを試してみた

今回は、go-ethereumのv1.10から追加されたコマンドである、`go-ethereum snapshot prune-state`を試してみたのでその結果を共有する記事となる。
このコマンドは、go-ethereumのfull nodeを維持すると溜まっていってしまうstate trieのゴミデータを削除(枝切り)するためのコマンドである。つまり、言い換えるとgo-ethereumで肥大化していくストレージの容量を削減することができる。

より詳細な情報については公式ブログを参照。
blog.ethereum.org

state trieのゴミデータ

EthereumではAccountのstate情報をMerkle Patricia Trieというデータ構造で保有しており、このデータをLevelDBに保存している。
Merkle Patricia Trieは16分木であり、このツリーはAccountのaddressをもとに構成されている。また、各branch nodeはaddressを元にツリー構造となっており、16個の(つまり0〜Fまでの)次のnodeへのキー(=hash値)を保有している。branch nodeをAccountのaddressに従って辿っていくと、最終的にstate情報が保存さたleaf nodeに到達する。
そのため、Accountのstate情報が変更されると、leaf nodeのキー(=hash値)が変化し、その影響でrootからleafに至るまでの経路上のbranch nodeの保有する値が全て変化する。
この時、go-ethereumでは変化したbranch, leaf nodeに対して、以前の情報を削除せずに保有し続けている。これがいわゆるstate trieのゴミデータである。

Merkle Patricia Trieの詳細については以下の動画を参考にして欲しい。
goblockchain.network

今までpruningが実装されなかった理由

これは推察になるが、以下の理由でgo-ethereumではv1.10までpruningが実装されなかったと思われる。

  1. 古いstate情報もreorgを考慮して残しておく必要がある。
  2. fast syncし直すことで、pruningの代わりになっていたため。

特に1. の理由が大きいと思われる。reorgを考慮すると少し古いstate情報もすぐに消すことはできない。また、十分に古くなった時に消すようにするのであれば、state情報にblock番号を付与して管理する必要が出てくるため、結果的により多くのstorageを消費してしまう可能性がある。

v1.10からpruningが実装された理由

v1.10では新たにsnap syncという高速同期の仕組みが導入された。また、snap syncのためにstateのsnapshotを新たに保有するようになった。
snap syncについては以下のブログを参照。
techmedia-think.hatenablog.com


このsnapshotはstate trieのleaf情報のみを集めたものであり、このsnapshotからstateのMerkle Patricia Trieが再構築可能なものとなっている。
つまりは、snap syncの実装に伴い、不要なデータを削除したMerkle Patrica Trieを再構築可能となったため、pruningの機能も追加されたと思われる。

前述した通り、fast syncやsnap syncをやり直すことでpruningの代わりにはなるが、これらの同期がどの程度の時間で完了するかは、接続したremote peerに依存してしまう。
そのため、ローカルにある情報から再構築できるのであればそれに越したことはないということだろう。

実際に試してみた

さて、前置きが長くなったが、ここから`geth snapshot prune-state`を試した結果を掲載する。

環境

AWS EC2 t3.xlarge + EBS gp2 汎用SSD 1.5 TB(ext4)

mainnetをfull syncでおおよそ12,760,000ブロック程度まで同期完了している状態。

実行前情報

geth db inspectコマンドの結果

+-----------------+--------------------+------------+------------+
|    DATABASE     |      CATEGORY      |    SIZE    |   ITEMS    |
+-----------------+--------------------+------------+------------+
| Key-Value store | Headers            | 49.44 MiB  |      90002 |
| Key-Value store | Bodies             | 4.51 GiB   |      90002 |
| Key-Value store | Receipt lists      | 4.87 GiB   |      90002 |
| Key-Value store | Difficulties       | 15.17 MiB  |     139283 |
| Key-Value store | Block number->hash | 14.19 MiB  |     139447 |
| Key-Value store | Block hash->number | 499.46 MiB |   12773681 |
| Key-Value store | Transaction index  | 14.75 GiB  |  439866107 |
| Key-Value store | Bloombit index     | 2.16 GiB   |    6388783 |
| Key-Value store | Contract codes     | 2.18 GiB   |     437158 |
| Key-Value store | Trie nodes         | 677.64 GiB | 3230441862 |
| Key-Value store | Trie preimages     | 547.13 KiB |       8893 |
| Key-Value store | Account snapshot   | 6.42 GiB   |  140457506 |
| Key-Value store | Storage snapshot   | 33.36 GiB  |  466248131 |
| Key-Value store | Clique snapshots   | 0.00 B     |          0 |
| Key-Value store | Singleton metadata | 6.30 MiB   |          9 |
| Key-Value store | Shutdown metadata  | 24.00 B    |          1 |
| Ancient store   | Headers            | 5.52 GiB   |   12683680 |
| Ancient store   | Bodies             | 146.73 GiB |   12683680 |
| Ancient store   | Receipt lists      | 72.77 GiB  |   12683680 |
| Ancient store   | Difficulties       | 198.64 MiB |   12683680 |
| Ancient store   | Block number->hash | 459.65 MiB |   12683680 |
| Light client    | CHT trie nodes     | 0.00 B     |          0 |
| Light client    | Bloom trie nodes   | 0.00 B     |          0 |
+-----------------+--------------------+------------+------------+
|                         TOTAL        | 972.13 GIB |            |
+-----------------+--------------------+------------+------------+

duコマンドの結果

16	/data/lost+found
6208	/data/ethereum/geth_full/geth/nodes
236626328	/data/ethereum/geth_full/geth/chaindata/ancient
1104669620	/data/ethereum/geth_full/geth/chaindata
212368	/data/ethereum/geth_full/geth/ethash
1106321404	/data/ethereum/geth_full/geth
4	/data/ethereum/geth_full/keystore
1106321416	/data/ethereum/geth_full
1107305528	/data/ethereum
1107305548	/data

実行後情報

geth db inspectコマンドの結果

+-----------------+--------------------+------------+-----------+
|    DATABASE     |      CATEGORY      |    SIZE    |   ITEMS   |
+-----------------+--------------------+------------+-----------+
| Key-Value store | Headers            | 49.44 MiB  |     90002 |
| Key-Value store | Bodies             | 4.51 GiB   |     90002 |
| Key-Value store | Receipt lists      | 4.87 GiB   |     90002 |
| Key-Value store | Difficulties       | 5.83 MiB   |    101712 |
| Key-Value store | Block number->hash | 4.88 MiB   |    101807 |
| Key-Value store | Block hash->number | 499.46 MiB |  12773681 |
| Key-Value store | Transaction index  | 14.75 GiB  | 439866107 |
| Key-Value store | Bloombit index     | 2.16 GiB   |   6388783 |
| Key-Value store | Contract codes     | 2.15 GiB   |    412436 |
| Key-Value store | Trie nodes         | 82.47 GiB  | 774362254 |
| Key-Value store | Trie preimages     | 547.13 KiB |      8893 |
| Key-Value store | Account snapshot   | 6.42 GiB   | 140457576 |
| Key-Value store | Storage snapshot   | 33.36 GiB  | 466249712 |
| Key-Value store | Clique snapshots   | 0.00 B     |         0 |
| Key-Value store | Singleton metadata | 308.00 B   |         9 |
| Key-Value store | Shutdown metadata  | 24.00 B    |         1 |
| Ancient store   | Headers            | 5.52 GiB   |  12683680 |
| Ancient store   | Bodies             | 146.73 GiB |  12683680 |
| Ancient store   | Receipt lists      | 72.77 GiB  |  12683680 |
| Ancient store   | Difficulties       | 198.64 MiB |  12683680 |
| Ancient store   | Block number->hash | 459.65 MiB |  12683680 |
| Light client    | CHT trie nodes     | 0.00 B     |         0 |
| Light client    | Bloom trie nodes   | 0.00 B     |         0 |
+-----------------+--------------------+------------+-----------+
|                         TOTAL        | 376.90 GIB |           |
+-----------------+--------------------+------------+-----------+

duコマンドの結果

16	/data/lost+found
6208	/data/ethereum/geth_full/geth/nodes
236626328	/data/ethereum/geth_full/geth/chaindata/ancient
387859604	/data/ethereum/geth_full/geth/chaindata
212368	/data/ethereum/geth_full/geth/ethash
388078188	/data/ethereum/geth_full/geth
4	/data/ethereum/geth_full/keystore
388078200	/data/ethereum/geth_full
389062312	/data/ethereum
389062332	/data

実行時間

INFO [07-23|02:16:09.043] State pruning successful pruned=595.22GiB elapsed=7h50m56.799s