Open preston-evans98 opened 1 year ago
Just to be clear, you're using tendermint-rs v0.27.0, right? If so, have you tried the latest release of tendermint-rs? (v0.31.1)
Asking because we don't have capacity to support older releases of tendermint-rs at present.
Makes sense. I just tested with v0.31.1
and the issue is still present.
@thanethomson It looks like tendermint::block::Id
is the culprit here. You can easily reproduce the failure using the same HEADER_JSON
as above:
#[test]
fn test_tm_block_id_serde_roundtrip() {
let header: tendermint::block::Header = serde_json::from_str(HEADER_JSON).unwrap();
let last_block_id: tendermint::block::Id = header.last_block_id.unwrap();
let serialized = postcard::to_stdvec(&last_block_id).unwrap();
let _deserialized: tendermint::block::Id = postcard::from_bytes(&serialized).unwrap();
}
I think the serde trait impls on all of those types are designed for serializing/deserializing JSON, not arbitrary other formats.
Protobufs are the preferred binary encoding.
I think the serde trait impls on all of those types are designed for serializing/deserializing JSON, not arbitrary other formats.
Yeah, that seems to be the case. I know that serialization in this package has always been a bit tricky due to compatibility requirements. Just documenting the restriction is probably sufficient for now.
Will try to put up a PR to fix the documentation and close this issue later. @thanethomson @romac, any thoughts on where the most appropriate place for that documentation would be?
As an aside, it seems like it should be relatively straightforward to use the serde::serializer::is_human_readable
method to do some special-casing for JSON. Then serialization might still be broken for non-JSON human-readable types, but binary formats would work as expected - which I think would address most use cases that want serde anyway. Not a priority for now, just leaving this here in case it's useful later.
@preston-evans98 but why not use Protobuf as a binary serialization? It's the canonical binary format for these types
@tarcieri TBC my use case is currently workable without serde, so I'm fine with just documenting the lack of support and closing out the issue.
That being said, there are a few reasons why someone might want to use serde over protobuf. Performance is one - a format like bincode
or postcard
should be faster to serialize/deserialize in theory (and that's born out in all of the benchmarks I've seen). So if you're storing/retrieving a large volume of this data in a DB, you probably want one of them all else being equal.
Another reason is library support. Lots and lots of packages are compatible with serde and have blanket implementations for their traits in terms of serde. (In fact, that's what prompted this issue - i wanted to use a library and it had default support for serde - so I just used it. But because of the bug, data was getting silently garbled in-flight - so I had to hand write some logic use protobufs instead).
The final reason is just familiarity. Pretty much every Rust programmer has used the Serde APIs, and IME prost is a lot less widely know.
A proliferation of binary formats harms interoperability. It already exists with Amino and Protobuf
What went wrong?
An attempt to serialize and then deserialize a
tendermint::block::Header
using a binary data format (postcard
) returned an error:Err(DeserializeBadOption)
.This error is not a bug in
postcard
- in my testing also occurs when attempting roundtrip serialization with other binary data formats.Steps to reproduce
Attempt roundtrip serialization of a
tendermint::block::Header
with a suitable (non-JSON) data format. The following test case usestendermint = "0.27"
and,serde_json = "1"
, andpostcard = { version = "1", features = ["use-std"]}
.The provided test will fail with the following output:
Definition of "done"
Either roundtrip serialization succeeds using binary data formats, or documentation is added explaining that serialization to/from formats other than json is not supported.