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