Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-built tendermint-proto with serialization annotations #639

Merged
merged 47 commits into from
Nov 6, 2020

Conversation

greg-szabo
Copy link
Member

@greg-szabo greg-szabo commented Oct 14, 2020

Closes #634.

This is a research for #638 that adds Serialization support for protobuf structs.

  • Referenced an issue explaining the need for the change
  • Updated all relevant documentation in docs
  • Updated all code comments where relevant
  • Wrote tests
  • Updated CHANGELOG.md

@greg-szabo
Copy link
Member Author

All right, I think this research is a success. In this PR you can see the following:

  • JSON serializers are moved into the tendermint-proto crate (proto/src/serializers.rs copied from tendermint) and hidden from the outside (serialization is a similar problem as protobuf encoding: noone cares, it just needs to work)
  • protobuf types are annotated so all of them can be JSON serialized (
    (".", "#[derive(::serde::Deserialize, ::serde::Serialize)]"), /* All types should be
    )
  • custom serialization annotations are implemented in the proto-compiler crate in an easily expandable way (
    static CUSTOM_FIELD_ATTRIBUTES: &[(&str, &str)] = &[
    ) This is useful for fields that use some weird rule for serialization, for example serializing integers as strings.
  • Finally, an example re-implementation of the AbciInfo type with the new serialization annotation (and as a domaintype on the side) shows how serialization is much less of a deal (
    #[serde(default, try_from = "ResponseInfo", into = "ResponseInfo")]
    ) This is implemented in a compact way in a test, so it can be compared with the old implementation. Obviously, these will go into the respective files, instead of tests.

If I get a "hey this works" from the team, I'll start revamping other types too, focusing on the types listed in #638 for IBC.

@greg-szabo greg-szabo added this to the v0.17.0 milestone Oct 21, 2020
@greg-szabo greg-szabo marked this pull request as ready for review October 22, 2020 06:17
@greg-szabo greg-szabo mentioned this pull request Oct 23, 2020
5 tasks
@greg-szabo
Copy link
Member Author

I gave up on trying to organize JSON serialization for now. I've implemented a bunch of extra domain type conversions and moved a lot of the serialization into tendermint-proto, but we'll have to get back and do more structued thinking about JSON serialization.

I need to fix the light-client test failures and I'll implement the last domaintype conversion for Anca and wrap it up for review.

@greg-szabo
Copy link
Member Author

The last test that fails is the model-based single-step tests. There were a few changes in the JSON encoding that doesn't seem to be in testgen. The most prominent one is that the "parts" field was renamed to "part_set_header" both in Go and in this branch in Rust but testgen still seem to generate "parts".

I've added time serialization annotation to some of the testgen tests where I saw it's having a hard time deserializing.

Validator sets now contain a new "total_voting_power" field, but I think testgen doesn't generate that either.

I also found error messages missing "description" and "model" fields in the testgen structs but I don't know exactly what's missing there.

I'll need @andrey-kuprianov 's help to fix the remaining issues.

@codecov-io
Copy link

codecov-io commented Oct 25, 2020

Codecov Report

Merging #639 into master will decrease coverage by 6.3%.
The diff coverage is 48.8%.

Impacted file tree graph

@@           Coverage Diff            @@
##           master    #639     +/-   ##
========================================
- Coverage    45.2%   38.9%   -6.4%     
========================================
  Files         175     184      +9     
  Lines       12113   12800    +687     
  Branches     2724    2929    +205     
========================================
- Hits         5480    4984    -496     
- Misses       6350    7572   +1222     
+ Partials      283     244     -39     
Impacted Files Coverage Δ
light-client/src/builder/light_client.rs 0.0% <0.0%> (ø)
light-client/src/components/io.rs 0.0% <0.0%> (ø)
light-client/src/predicates/errors.rs 19.0% <ø> (-33.4%) ⬇️
light-client/src/supervisor.rs 28.6% <0.0%> (ø)
light-client/src/tests.rs 47.4% <ø> (-16.6%) ⬇️
light-client/src/types.rs 28.4% <0.0%> (-4.3%) ⬇️
light-client/tests/model_based.rs 0.2% <0.0%> (-83.6%) ⬇️
light-node/src/rpc.rs 53.5% <ø> (ø)
proto-compiler/src/constants.rs 0.0% <0.0%> (ø)
proto/src/lib.rs 100.0% <ø> (ø)
... and 114 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e5484f5...5f8fe33. Read the comment docs.

thanethomson and others added 5 commits October 26, 2020 11:14
Right now we need to allow for compatibility with the latest version of
Tendermint, as well as v0.34.0-rc5. Between these versions, the `parts`
field was renamed to `part_set_header` in the JSON serialization. We
need to support both field names deserializing into the same data
structures.

Signed-off-by: Thane Thomson <connect@thanethomson.com>
I've added some changes that Anca made and have tweaked a few tests to
get them to pass (the serialization was breaking, so I fixed the
fixtures).

Signed-off-by: Thane Thomson <connect@thanethomson.com>
Signed-off-by: Thane Thomson <connect@thanethomson.com>
Signed-off-by: Thane Thomson <connect@thanethomson.com>
Signed-off-by: Thane Thomson <connect@thanethomson.com>
@ancazamfir
Copy link
Contributor

Can we specify the revision to a commit hash in the proto-compiler?. Current ref used by gaia and go relayer stargate-4 release is:
github.com/tendermint/tendermint v0.34.0-rc4.0.20201005135527-d7d0ffea13c6

@ancazamfir
Copy link
Contributor

Missed this one:
We have some Merkle related structs here:

pub struct ProofOp {
#[prost(string, tag="1")]
pub r#type: std::string::String,
#[prost(bytes, tag="2")]
pub key: std::vec::Vec<u8>,
#[prost(bytes, tag="3")]
pub data: std::vec::Vec<u8>,
}
/// ProofOps is Merkle proof defined by the list of ProofOps
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProofOps {
#[prost(message, repeated, tag="1")]
pub ops: ::std::vec::Vec<ProofOp>,
}

And similar here:
pub struct Proof {
/// The list of ProofOps
pub ops: Vec<ProofOp>,
}
/// ProofOp defines an operation used for calculating Merkle root
/// The data could be arbitrary format, providing necessary data
/// for example neighbouring node hash
/// <https://github.com/tendermint/tendermint/blob/c8483531d8e756f7fbb812db1dd16d841cdf298a/crypto/merkle/merkle.proto#L19>
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct ProofOp {
/// Type of the ProofOp
#[serde(alias = "type")]
pub field_type: String,
/// Key of the ProofOp
#[serde(default, with = "serializers::bytes::base64string")]
pub key: Vec<u8>,
/// Actual data
#[serde(default, with = "serializers::bytes::base64string")]
pub data: Vec<u8>,
}

Could tendermint use the proto ones? Or impl the domain types?
IBC gets the domain types from abci queries and needs to serialize into the protobuf ones.

ancazamfir and others added 11 commits November 3, 2020 16:40
Signed-off-by: Thane Thomson <connect@thanethomson.com>
Signed-off-by: Thane Thomson <connect@thanethomson.com>
…sts)

This pulls in the latest changes from master, but ignores the
single-step tests because I think we need to regenerate them.

Signed-off-by: Thane Thomson <connect@thanethomson.com>
Signed-off-by: Thane Thomson <connect@thanethomson.com>
Signed-off-by: Thane Thomson <connect@thanethomson.com>
Signed-off-by: Thane Thomson <connect@thanethomson.com>
Signed-off-by: Thane Thomson <connect@thanethomson.com>
Signed-off-by: Thane Thomson <connect@thanethomson.com>
Copy link
Member

@thanethomson thanethomson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, a lot of work and thought and deliberation have gone into this PR and what the next steps from here should be. We're not yet where we need to be yet for v0.17.0, but I think it's important to at least push out a v0.17.0-rc2 release with the disclaimer that some more data structure changes are coming in v0.17.0-rc3. At the very least, rc2 will cater to IBC's immediate needs. Other consumers may want to wait until rc3 to upgrade.

The main thing that'd be good to fix right now before the v0.17.0-rc2 release is to get the Light Client's model-based single-step tests working with the new data structures introduced in this PR. cc @Shivani912 and @andrey-kuprianov

I'm keeping this branch around for a bit until IBC can base off of v0.17.0-rc2 (or master).

@thanethomson thanethomson merged commit 4cbf727 into master Nov 6, 2020
@thanethomson thanethomson deleted the greg/research-json branch November 6, 2020 23:10
@thanethomson thanethomson restored the greg/research-json branch November 6, 2020 23:10
@adizere
Copy link
Member

adizere commented Nov 12, 2020

FYI -- ibc-rs master no longer depends on branch greg/research-json, so it should be safe to delete from that perspective!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Domain Type implementations needed by IBC
5 participants