4.8 KiB
iavlread - extract data from the state of a Cosmos SDK blockchain
This is a simple tool read state data from the snapshot of a [Cosmos SDK] block chain. The state is stored in the application.db leveldb database, in the form of an [IAVL tree]. This tool walks the IAVL tree to get values from the state, at a desired block height.
Installation
It's really just two Python files. iavlread is the CLI tool, and iavltree.py is the library which actually handles the data structure. It can also be used as a package in Python code (store.ipynb shows a few examples). To use iavlread, it's easiest to just clone this repository and make a symlink to iavlread from $HOME/bin or other directory which in $PATH.
Usage
I'm just going to show a couple of examples on a snapshot of the [Allora] testnet, as it can be downloaded e.g. here. That's what I've been using this for, although I'd assume it works the same for other CosmosSDK blockchains.
We assume that we're inside the snapshot, so the application db is at the path data/application.db from the current working directory. Otherwise, it can be specified with using -d path_to_database.
To get the maximum/minimum block height contained in the snapshot
$ iavlread max_height s/k:emissions/
5224814
$ iavlread min_height s/k:emissions/
5221360
Here s/k:emissions/ is the prefix for a specific IAVL tree, the one corresponding to the emissions module. Other prefixes are s/k:mint/, s/k:bank/, s/k:staking/, s/k:acc/. They should generally produce the same min/max height, but that is not guaranteed.
To count the items in a keeper, use the count subcommand:
$ iavlread count s/k:emissions/
19070982
We can also count only the items with a specific key (i.e. one item of the keeper).
$ iavlread count s/k:emissions/ 62
9714538
Here 62 corresponds to the latestOneOutInfererInfererNetworkRegrets field, which has type Map[Triple[uint64, string, string], TimestampedValue]. So the keys for the individual item in the map are quadruples consisting of 62, an integer, and two strings.
To iterate through all items whose key starts with 62, use the iterate command:
$ iavlread -kQss -vpb,2=float iterate s/k:emissions/ 62 | head -n5
([62, 1, 'allo1004k7wqa4spns0wlct6mvxnmfysae07w2p75xc', 'allo1004k7wqa4spns0wlct6mvxnmfysae07w2p75xc'], [(1, 1655577), (2, -2.538390795862665)])
([62, 1, 'allo1004k7wqa4spns0wlct6mvxnmfysae07w2p75xc', 'allo123s56yuz7dkyh54gs7gstulrfzwj3d6ucwlwk2'], [(1, 1655577), (2, -2.9735713547935196)])
([62, 1, 'allo1004k7wqa4spns0wlct6mvxnmfysae07w2p75xc', 'allo136dfvvuhazgyqyls2f68qzr5l3p07uhnk9mmk0'], [(1, 1655577), (2, -2.4482888033843784)])
([62, 1, 'allo1004k7wqa4spns0wlct6mvxnmfysae07w2p75xc', 'allo15fvg8gk63u8ydf3znaaxrrukgwulezjz4azf68'], [(1, 1655577), (2, -2.4736050386063284)])
([62, 1, 'allo1004k7wqa4spns0wlct6mvxnmfysae07w2p75xc', 'allo16k9af4uu7vpm5hy68t6u62jylc5frv747mz5lw'], [(1, 1655577), (2, -2.4686292734004254)])
The option -kQss specifies the key format (a 64 bit integer Q followed by two strings s; see below). And -vpb,2=float specifies the value format: a protocol buffer whose field number 2 is a float.
If we want to restrict to keys which start with 62 and 60 (i.e. get one-out regrets for topic 60 only)
$ iavlread -kQss count s/k:emissions/ 62 60 | head -n5
10650
$ iavlread -kQss -vpb,2=float iterate s/k:emissions/ 62 60 | head -n5
([62, 60, 'allo107zfy4xrp5plt0jmutaj9feer02v6r30amku78', 'allo107zfy4xrp5plt0jmutaj9feer02v6r30amku78'], [(1, 5070658), (2, 0.004613475335253211)])
([62, 60, 'allo107zfy4xrp5plt0jmutaj9feer02v6r30amku78', 'allo10q5h8afpwjh5x3vazxzwwkxfhpzfys9wxxw3q8'], [(1, 4785658), (2, 0.18922985130794248)])
([62, 60, 'allo107zfy4xrp5plt0jmutaj9feer02v6r30amku78', 'allo10vgaxk57dkk0fd255r3gxn5quwzxaqq95m2cz2'], [(1, 4837018), (2, 0.6616848257922094)])
([62, 60, 'allo107zfy4xrp5plt0jmutaj9feer02v6r30amku78', 'allo10w45atfjsh9q6vsk7mx74xh0pvuf8r42vnmt5p'], [(1, 4802038), (2, 0.010614832362991345)])
([62, 60, 'allo107zfy4xrp5plt0jmutaj9feer02v6r30amku78', 'allo12hnfamvwumkfm6dnc42rt8q3yevyqpuzkdtwat'], [(1, 4471438), (2, 0.2668976650081499)])
Or if we know the full key, we can use get instead of iterate. E.g. to get a balance from the bank module:
$ iavlread -kbs -vint get s/k:bank/ 2 570DD38DC5BAF3112A7C83A420ED399A8E59C5FC uallo
350
We can also get the value for at a different block height (by default, the max block height is used):
$ iavlread -H 5221360 -kbs -vint get s/k:bank/ 2 570DD38DC5BAF3112A7C83A420ED399A8E59C5FC uallo
10
Or we can get all past updates to the value (that are contained in the snapshot):
$ iavlread -kbs -vint history s/k:bank/ 2 570DD38DC5BAF3112A7C83A420ED399A8E59C5FC uallo
5224814 150
5224813 30
5224812 60