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

Protobuf bytes field incorrectly parsed as String when generating gRPC code with tonic_build #1889

Closed
starcorn2020 opened this issue Aug 24, 2024 · 1 comment

Comments

@starcorn2020
Copy link

starcorn2020 commented Aug 24, 2024

Bug Report

Version

➜ proto_tools cargo tree | grep tonic
├── tonic v0.12.1
└── tonic-build v0.12.1

Platform

Linux ip-xxxxxxxxx-aws #61~20.04.1-Ubuntu SMP Wed Mar 13 17:40:41 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

Description

Encountered Issue: bytes field generated as String

// Header defines the structure of a block header.
message Header {
// basic block info
tendermint.version.Consensus version = 1 [(gogoproto.nullable) = false];
string chain_id = 2 [(gogoproto.customname) = "ChainID"];
int64 height = 3;
google.protobuf.Timestamp time = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];

// prev block info
BlockID last_block_id = 5 [(gogoproto.nullable) = false];

// hashes of block data
bytes last_commit_hash = 6; // commit from validators from the last block
bytes data_hash = 7; // transactions

// hashes from the app output from the prev block
bytes validators_hash = 8; // validators for the current block
bytes next_validators_hash = 9; // validators for the next block
bytes consensus_hash = 10; // consensus params for current block
bytes app_hash = 11; // state after txs from the previous block
bytes last_results_hash = 12; // root hash of all results from the txs from the previous block

// consensus info
bytes evidence_hash = 13; // evidence included in the block
bytes proposer_address = 14; // original proposer of the block
}

And the generated code is as follows:

#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Header {
/// basic block info
#[prost(message, optional, tag = "1")]
pub version: ::core::option::Optionsuper::super::super::super::tendermint::version::Consensus,
#[prost(string, tag = "2")]
pub chain_id: ::prost::alloc::string::String,
#[prost(int64, tag = "3")]
pub height: i64,
#[prost(message, optional, tag = "4")]
pub time: ::core::option::Option<::prost_types::Timestamp>,
/// prev block info
#[prost(message, optional, tag = "5")]
pub last_block_id:
::core::option::Optionsuper::super::super::super::tendermint::types::BlockId,
/// hashes of block data
///
/// commit from validators from the last block
#[prost(bytes = "vec", tag = "6")]
pub last_commit_hash: ::prost::alloc::vec::Vec,
/// transactions
#[prost(bytes = "vec", tag = "7")]
pub data_hash: ::prost::alloc::vec::Vec,
/// hashes from the app output from the prev block
///
/// validators for the current block
#[prost(bytes = "vec", tag = "8")]
pub validators_hash: ::prost::alloc::vec::Vec,
/// validators for the next block
#[prost(bytes = "vec", tag = "9")]
pub next_validators_hash: ::prost::alloc::vec::Vec,
/// consensus params for current block
#[prost(bytes = "vec", tag = "10")]
pub consensus_hash: ::prost::alloc::vec::Vec,
/// state after txs from the previous block
#[prost(bytes = "vec", tag = "11")]
pub app_hash: ::prost::alloc::vec::Vec,
/// root hash of all results from the txs from the previous block
#[prost(bytes = "vec", tag = "12")]
pub last_results_hash: ::prost::alloc::vec::Vec,
/// consensus info
///
/// evidence included in the block
#[prost(bytes = "vec", tag = "13")]
pub evidence_hash: ::prost::alloc::vec::Vec,
/// proposer_address is the original block proposer address, formatted as a Bech32 string.
/// In Tendermint, this type is bytes, but in the SDK, we convert it to a Bech32 string
/// for better UX.
///
/// original proposer of the block
#[prost(string, tag = "14")]
pub proposer_address: ::prost::alloc::string::String,
}

As you can see, proposer_address is generated as a String instead of the original bytes type defined in the Proto. In practice, I encountered this issue where it seems like the gRPC message field should be bytes, but tonic is unable to correctly parse it as bytes.

"message": "Failed to get latest block: Status { code: Internal, message: "failed to decode Protobuf message: Header.proposer_address: Block.header: GetLatestBlockResponse.block: invalid string value: data is not UTF-8 encoded", metadata: MetadataMap { headers: {"date": "Sat, 24 Aug 2024 02:53:52 GMT", "content-type": "application/grpc", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "x-cosmos-block-height": "23542656", "x-envoy-upstream-service-time": "479", "cf-cache-status": "DYNAMIC", "x-content-type-options": "nosniff", "server": "cloudflare", "cf-ray": "8b800dec6f9de011-NRT", "alt-svc": "h3=\":443\"; ma=86400"} }, source: None }"

@starcorn2020
Copy link
Author

I found that it was caused by incorrect compilation settings. Closing the issue.

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

No branches or pull requests

1 participant