informalsystems / tendermint-rs

Client libraries for Tendermint/CometBFT in Rust!
Apache License 2.0
587 stars 213 forks source link

TM34 Events can't be Parsed when the Value is Binary Data #1400

Closed ryanrossiter closed 2 months ago

ryanrossiter commented 3 months ago

What went wrong?

When querying for tx/block results from a TM34 chain (i.e. events are base64-encoded), the parsing fails when the event data is binary and not utf8 because the deserialize_to_string conversion uses String.from_utf8 which asserts the data is valid utf8 here.

Steps to reproduce

Parse an event containing binary data formatted as base64, using the TM34 compatability mode. This event from the Canto chain as an example:

{
    "type": "block_bloom",
    "attributes": [
        {
            "key": "Ymxvb20=",
            "value": "ACAAABAAAAgAAAAAAAAAABIAAAIAABAAAAAAIgAAAQAEAAAAAAIAAIBAAAAAACAAAAQAgAAAAIACAAAEASAkiACAAIAAAAAgCAAADAAAACAAAAAAEAIAABQAABAAAACAAAAAAAAEAEAAQEAgABAAAAAAAAEACAAAAAAEEAAAAAAAAEAAAAQAAACAAAAAABAAAQAQAAAAAAAAAABABAAgAAIAAAAAAAAAQAAAAAAACAABBAQAAAAAAAKAAAAAAggIAQAAAgAAAAAAAAAEAAAAAAAAAAAAAAAAAAgAAAAAAAAAEQgAAAAAAAAAQAAAAAAAEAACAgAQAAABAAAAAAQAQA==",
            "index": true
        }
    ]
}

Definition of "done"

Parsing should not fail when the encoded data is binary. Perhaps it should leave any values which aren't utf8 as base64 strings.

romac commented 3 months ago

Thanks for bringing this to our attention!

Can you please post a minimal reproduction of the problem for us to take a look at?

romac commented 3 months ago

It seems indeed that we are wrongly modeling EventAttribute's key and value as String instead of Vec for Tendermint/CometBFT v0.34, whereas those are only required to be valid UTF-8 encoded strings since Tendermint/CometBFT v0.37.

penso commented 3 months ago

Yes indeed, this is also breaking on early osmosis blocks. I can't fetch block 1423377 (v0.34) because some EventAttribute have :

      {
        "type": "distribution",
        "attributes": [
          {
            "key": "Z2F1Z2VfaWQ=",
            "value": "MTQ1Mg==",
            "index": true
          },
          {
            "key": "cmVjZWl2ZXI=",
            "value": "V0RfatpWKg/BJHrErklu9FjLhBM=",
            "index": true
          },
          {
            "key": "YW1vdW50",
            "value": "Mzg2dW9zbW8=",
            "index": true
          }
        ]
      }

and V0RfatpWKg/BJHrErklu9FjLhBM= isn't base64 encoded UTF8.

romac commented 2 months ago

We'll fix this in v0.36, would gladly accept a PR if anyone has time to put one together otherwise I'll get to it next week together with the release.

penso commented 2 months ago

We'll fix this in v0.36, would gladly accept a PR if anyone has time to put one together otherwise I'll get to it next week together with the release.

How do you expect to fix this, use Vec<u8> only for v0.34 and String for later versions?

romac commented 2 months ago

Yes exactly!

penso commented 2 months ago

Yes exactly!

I'm not really familiar with tendermint and the code so I looked quickly out of curiosity since I need this to fetch early Osmosis blocks. Not sure how I'd get to do this in a small change.

penso commented 2 months ago

We'll fix this in v0.36, would gladly accept a PR if anyone has time to put one together otherwise I'll get to it next week together with the release.

Tried my luck, would love feedback. Never contributed to tendermint so not sure that's the right way to fix it.