github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/iavl/cmd/iaviewer/README.md (about) 1 # IaViewer 2 3 `iaviewer` is a utility to inspect the contents of a persisted iavl tree, given (a copy of) the leveldb store. 4 This can be quite useful for debugging, especially when you find odd errors, or non-deterministic behavior. 5 Below is a brief introduction to the tool. 6 7 ## Installation 8 9 Once this is merged into the offical repo, master, you should be able to do: 10 11 ```shell 12 go get github.com/tendermint/iavl 13 cd ${GOPATH}/src/github.com/tendermint/iavl 14 make install 15 ``` 16 17 ## Using the tool 18 19 First make sure it is properly installed and you have `${GOPATH}/bin` in your `PATH`. 20 Typing `iaviewer` should run and print out a usage message. 21 22 ### Sample databases 23 24 Once you understand the tool, you will most likely want to run it on captures from your 25 own abci app (built on cosmos-sdk or weave), but as a tutorial, you can try to use some 26 captures from an actual bug I found in my code... Same data, different hash. 27 28 ```shell 29 mkdir ./testdata 30 cd ./testdata 31 curl -L https://github.com/iov-one/iavl/files/2860877/bns-a.db.zip > bns-a.db.zip 32 unzip bns-a.db.zip 33 curl -L https://github.com/iov-one/iavl/files/2860878/bns-b.db.zip > bns-b.db.zip 34 unzip bns-b.db.zip 35 ``` 36 37 Now, if you run `ls -l`, you should see two directories... `bns-a.db` and `bns-b.db` 38 39 ### Inspecting available versions 40 41 ```shell 42 iaviewer versions ./bns-a.db 43 ``` 44 45 This should print out a list of 20 versions of the code. Note the the iavl tree will persist multiple 46 historical versions, which is a great aid in forensic queries (thanks Tendermint team!). For the rest 47 of the cases, we will consider only the last two versions, 190257 (last one where they match) and 190258 48 (where they are different). 49 50 ### Checking keys and app hash 51 52 First run these two and take a quick a look at the output: 53 54 ```shell 55 iaviewer data ./bns-a.db 56 iaviewer data ./bns-a.db 190257 57 ``` 58 59 Notice you see the different heights and there is a change in size and app hash. 60 That's what happens when we process a transaction. Let's go further and use 61 the handy tool `diff` to compare two states. 62 63 ```shell 64 iaviewer data ./bns-a.db 190257 > a-last.data 65 iaviewer data ./bns-b.db 190257 > b-last.data 66 67 diff a-last.data b-last.data 68 ``` 69 70 Same, same :) 71 But if we take the current version... 72 73 ```shell 74 iaviewer data ./bns-a.db 190258 > a-cur.data 75 iaviewer data ./bns-b.db 190258 > b-cur.data 76 77 diff a-cur.data b-cur.data 78 ``` 79 80 Hmmm... everything is the same, except the hash. Odd... 81 So odd that I [wrote an article about it](https://medium.com/@ethan.frey/tracking-down-a-tendermint-consensus-failure-77f6ff414406) 82 83 And finally, if we want to inspect which keys were modified in the last block: 84 85 ```shell 86 diff a-cur.data a-last.data 87 ``` 88 89 You should see 6 writes.. the `_i.usernft_*` are the secondary indexes on the username nft. 90 `sigs.*` is setting the nonce (if this were an update, you would see a previous value). 91 And `usrnft:*` is creating the actual username nft. 92 93 ### Checking the tree shape 94 95 So, remember above, when we found that the current state of a and b have the same data 96 but different hashes. This must be due to the shape of the iavl tree. 97 To confirm that, and possibly get more insights, there is another command. 98 99 ```shell 100 iaviewer shape ./bns-a.db 190258 > a-cur.shape 101 iaviewer shape ./bns-b.db 190258 > b-cur.shape 102 diff a-cur.shape b-cur.shape 103 ``` 104 105 Yup, that is quite some difference. You can also look at the tree as a whole. 106 So, stretch your terminal nice and wide, and... 107 108 ```shell 109 less a-cur.shape 110 ``` 111 112 It has `-5 ` for an inner node of depth 5, and `*6 ` for a leaf node (data) of depth 6. 113 Indentation also suggests the shape of the tree. 114 115 Note, if anyone wants to improve the visualization, that would be awesome. 116 I have no idea how to do this well, but at least text output makes some 117 sense and is diff-able.