今回は、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が実装されなかったと思われる。
- 古いstate情報もreorgを考慮して残しておく必要がある。
- 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