Skip to content

Commit

Permalink
Add new dialect for v0.38 in order to fix changes in misbehaviour evi…
Browse files Browse the repository at this point in the history
…dence serialization
  • Loading branch information
romac committed Sep 17, 2024
1 parent 14fd628 commit 4545671
Show file tree
Hide file tree
Showing 29 changed files with 774 additions and 84 deletions.
2 changes: 1 addition & 1 deletion proto/src/prost/v0_34/tendermint.abci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ pub struct ResponseCheckTx {
#[prost(int64, tag = "10")]
pub priority: i64,
/// mempool_error is set by CometBFT.
/// ABCI applications creating a ResponseCheckTX should not set mempool_error.
/// ABCI applictions creating a ResponseCheckTX should not set mempool_error.
#[prost(string, tag = "11")]
pub mempool_error: ::prost::alloc::string::String,
}
Expand Down
2 changes: 1 addition & 1 deletion proto/src/prost/v0_37/tendermint.abci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ pub struct ResponseCheckTx {
#[prost(int64, tag = "10")]
pub priority: i64,
/// mempool_error is set by CometBFT.
/// ABCI applications creating a ResponseCheckTX should not set mempool_error.
/// ABCI applictions creating a ResponseCheckTX should not set mempool_error.
#[prost(string, tag = "11")]
pub mempool_error: ::prost::alloc::string::String,
}
Expand Down
2 changes: 1 addition & 1 deletion proto/src/prost/v0_38/tendermint.abci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ pub struct ResponseFinalizeBlock {
#[prost(message, repeated, tag = "1")]
pub events: ::prost::alloc::vec::Vec<Event>,
/// the result of executing each transaction including the events
/// the particular transaction emitted. This should match the order
/// the particular transction emitted. This should match the order
/// of the transactions delivered in the block itself
#[prost(message, repeated, tag = "2")]
pub tx_results: ::prost::alloc::vec::Vec<ExecTxResult>,
Expand Down
9 changes: 5 additions & 4 deletions proto/src/prost/v0_38/tendermint.types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,13 @@ pub struct Vote {
/// Vote extension provided by the application. Only valid for precommit
/// messages.
#[prost(bytes = "vec", tag = "9")]
#[serde(with = "crate::serializers::nullable")]
pub extension: ::prost::alloc::vec::Vec<u8>,
/// Vote extension signature by the validator if they participated in
/// consensus for the associated block.
/// Only valid for precommit messages.
#[prost(bytes = "vec", tag = "10")]
#[serde(with = "crate::serializers::nullable")]
pub extension_signature: ::prost::alloc::vec::Vec<u8>,
}
/// Commit contains the evidence that a block was committed by a set of validators.
Expand Down Expand Up @@ -418,18 +420,17 @@ pub struct DuplicateVoteEvidence {
#[prost(message, optional, tag = "2")]
pub vote_b: ::core::option::Option<Vote>,
#[prost(int64, tag = "3")]
#[serde(rename = "TotalVotingPower", with = "crate::serializers::from_str")]
#[serde(alias = "TotalVotingPower", with = "crate::serializers::from_str")]
pub total_voting_power: i64,
#[prost(int64, tag = "4")]
#[serde(rename = "ValidatorPower", with = "crate::serializers::from_str")]
#[serde(alias = "ValidatorPower", with = "crate::serializers::from_str")]
pub validator_power: i64,
#[prost(message, optional, tag = "5")]
#[serde(rename = "Timestamp")]
#[serde(alias = "Timestamp")]
pub timestamp: ::core::option::Option<crate::google::protobuf::Timestamp>,
}
/// LightClientAttackEvidence contains evidence of a set of validators attempting to mislead a light client.
#[derive(::serde::Deserialize, ::serde::Serialize)]
#[serde(rename_all = "PascalCase")]
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct LightClientAttackEvidence {
Expand Down
2 changes: 1 addition & 1 deletion proto/src/tendermint/v0_34.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,5 @@ pub mod version {

pub mod meta {
pub const REPOSITORY: &str = "https://github.com/cometbft/cometbft";
pub const COMMITISH: &str = "v0.34.29";
pub const COMMITISH: &str = "v0.34.35";
}
2 changes: 1 addition & 1 deletion proto/src/tendermint/v0_37.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,5 @@ pub mod version {

pub mod meta {
pub const REPOSITORY: &str = "https://github.com/cometbft/cometbft";
pub const COMMITISH: &str = "v0.37.2";
pub const COMMITISH: &str = "v0.37.11";
}
2 changes: 1 addition & 1 deletion proto/src/tendermint/v0_38.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,5 @@ pub mod version {

pub mod meta {
pub const REPOSITORY: &str = "https://github.com/cometbft/cometbft";
pub const COMMITISH: &str = "v0.38.0";
pub const COMMITISH: &str = "v0.38.12";
}
15 changes: 10 additions & 5 deletions rpc/src/client/compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ pub enum CompatMode {
V0_34,
/// Use version 0.37 of the protocol.
V0_37,
/// Use version 0.38 of the protocol.
V0_38,
// NOTE: When adding a newer version, do not forget to update:
// - CompatMode::latest()
// - CompatMode::from_version()
Expand All @@ -34,7 +36,7 @@ impl Default for CompatMode {
impl CompatMode {
/// The latest supported version, selected by default.
pub const fn latest() -> Self {
Self::V0_37
Self::V0_38
}

/// Parse the Tendermint version string to determine
Expand All @@ -58,7 +60,7 @@ impl CompatMode {
match (version.major, version.minor) {
(0, 34) => Ok(CompatMode::V0_34),
(0, 37) => Ok(CompatMode::V0_37),
(0, 38) => Ok(CompatMode::V0_37),
(0, 38) => Ok(CompatMode::V0_38),
_ => Err(Error::unsupported_tendermint_version(version.to_string())),
}
}
Expand All @@ -69,6 +71,7 @@ impl fmt::Display for CompatMode {
match self {
CompatMode::V0_34 => f.write_str("v0.34"),
CompatMode::V0_37 => f.write_str("v0.37"),
CompatMode::V0_38 => f.write_str("v0.38"),
}
}
}
Expand All @@ -77,12 +80,13 @@ impl FromStr for CompatMode {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
const VALID_COMPAT_MODES: &str = "v0.34, v0.37";
const VALID_COMPAT_MODES: &str = "v0.34, v0.37, v0.38";

// Trim leading 'v', if present
match s.trim_start_matches('v') {
"0.34" => Ok(CompatMode::V0_34),
"0.37" => Ok(CompatMode::V0_37),
"0.38" => Ok(CompatMode::V0_38),
_ => Err(Error::invalid_compat_mode(
s.to_string(),
VALID_COMPAT_MODES,
Expand Down Expand Up @@ -139,7 +143,7 @@ mod tests {
);
assert_eq!(
CompatMode::from_version(parse_version("v0.38.0")).unwrap(),
CompatMode::V0_37
CompatMode::V0_38
);
let res = CompatMode::from_version(parse_version("v0.39.0"));
assert!(res.is_err());
Expand All @@ -153,10 +157,11 @@ mod tests {
fn test_from_str() {
assert_eq!("0.34".parse::<CompatMode>().unwrap(), CompatMode::V0_34);
assert_eq!("0.37".parse::<CompatMode>().unwrap(), CompatMode::V0_37);
assert_eq!("0.38".parse::<CompatMode>().unwrap(), CompatMode::V0_38);

let res = "0.33".parse::<CompatMode>();
assert!(res.is_err());
let res = "0.38".parse::<CompatMode>();
let res = "0.39".parse::<CompatMode>();
assert!(res.is_err());
let res = "foobar".parse::<CompatMode>();
assert!(res.is_err());
Expand Down
5 changes: 5 additions & 0 deletions rpc/src/client/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ macro_rules! perform_with_compat {
($self:expr, $request:expr) => {{
let request = $request;
match $self.compat {
CompatMode::V0_38 => {
$self
.perform_with_dialect(request, crate::dialect::v0_38::Dialect)
.await
},
CompatMode::V0_37 => {
$self
.perform_with_dialect(request, crate::dialect::v0_37::Dialect)
Expand Down
63 changes: 46 additions & 17 deletions rpc/src/client/transport/http.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
//! HTTP-based transport for Tendermint RPC Client.
use core::str::FromStr;
use core::time::Duration;

use async_trait::async_trait;
use reqwest::{header, Proxy};
use std::time::Duration;

use tendermint::{block::Height, evidence::Evidence, Hash};
use tendermint_config::net;

use super::auth;
use crate::client::{Client, CompatMode};
use crate::dialect::{v0_34, v0_37, v0_38, Dialect, LatestDialect};
use crate::endpoint;
use crate::prelude::*;
use crate::{
client::{Client, CompatMode},
dialect::{v0_34, Dialect, LatestDialect},
endpoint,
query::Query,
request::RequestMessage,
response::Response,
Error, Order, Scheme, SimpleRequest, Url,
};
use crate::query::Query;
use crate::request::RequestMessage;
use crate::response::Response;
use crate::{Error, Order, Scheme, SimpleRequest, Url};

use super::auth;

const USER_AGENT: &str = concat!("tendermint.rs/", env!("CARGO_PKG_VERSION"));

Expand Down Expand Up @@ -275,7 +274,14 @@ impl Client for HttpClient {
{
let height = height.into();
match self.compat {
CompatMode::V0_37 => self.perform(endpoint::header::Request::new(height)).await,
CompatMode::V0_38 => {
self.perform_with_dialect(endpoint::header::Request::new(height), v0_38::Dialect)
.await
},
CompatMode::V0_37 => {
self.perform_with_dialect(endpoint::header::Request::new(height), v0_37::Dialect)
.await
},
CompatMode::V0_34 => {
// Back-fill with a request to /block endpoint and
// taking just the header from the response.
Expand All @@ -292,9 +298,19 @@ impl Client for HttpClient {
hash: Hash,
) -> Result<endpoint::header_by_hash::Response, Error> {
match self.compat {
CompatMode::V0_38 => {
self.perform_with_dialect(
endpoint::header_by_hash::Request::new(hash),
v0_38::Dialect,
)
.await
},
CompatMode::V0_37 => {
self.perform(endpoint::header_by_hash::Request::new(hash))
.await
self.perform_with_dialect(
endpoint::header_by_hash::Request::new(hash),
v0_37::Dialect,
)
.await
},
CompatMode::V0_34 => {
// Back-fill with a request to /block_by_hash endpoint and
Expand All @@ -311,11 +327,24 @@ impl Client for HttpClient {
}

/// `/broadcast_evidence`: broadcast an evidence.
async fn broadcast_evidence(&self, e: Evidence) -> Result<endpoint::evidence::Response, Error> {
async fn broadcast_evidence(
&self,
evidence: Evidence,
) -> Result<endpoint::evidence::Response, Error> {
match self.compat {
CompatMode::V0_37 => self.perform(endpoint::evidence::Request::new(e)).await,
CompatMode::V0_38 => {
let request = endpoint::evidence::Request::new(evidence);
self.perform_with_dialect(request, crate::dialect::v0_38::Dialect)
.await
},
CompatMode::V0_37 => {
let request = endpoint::evidence::Request::new(evidence);
self.perform_with_dialect(request, crate::dialect::v0_37::Dialect)
.await
},
CompatMode::V0_34 => {
self.perform_with_dialect(endpoint::evidence::Request::new(e), v0_34::Dialect)
let request = endpoint::evidence::Request::new(evidence);
self.perform_with_dialect(request, crate::dialect::v0_34::Dialect)
.await
},
}
Expand Down
4 changes: 2 additions & 2 deletions rpc/src/client/transport/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use alloc::collections::BTreeMap as HashMap;

use async_trait::async_trait;

use crate::dialect::{v0_37, Dialect};
use crate::dialect::{v0_38, Dialect};
use crate::{
client::{
subscription::SubscriptionTx,
Expand Down Expand Up @@ -65,7 +65,7 @@ pub struct MockClient<M: MockRequestMatcher> {
impl<M: MockRequestMatcher> Client for MockClient<M> {
async fn perform<R>(&self, request: R) -> Result<R::Output, Error>
where
R: SimpleRequest<v0_37::Dialect>,
R: SimpleRequest<v0_38::Dialect>,
{
self.matcher
.response_for(request)
Expand Down
7 changes: 7 additions & 0 deletions rpc/src/client/transport/websocket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ impl Client for WebSocketClient {
{
let height = height.into();
match self.compat {
CompatMode::V0_38 => self.perform(endpoint::header::Request::new(height)).await,
CompatMode::V0_37 => self.perform(endpoint::header::Request::new(height)).await,
CompatMode::V0_34 => {
// Back-fill with a request to /block endpoint and
Expand All @@ -268,6 +269,10 @@ impl Client for WebSocketClient {
hash: Hash,
) -> Result<endpoint::header_by_hash::Response, Error> {
match self.compat {
CompatMode::V0_38 => {
self.perform(endpoint::header_by_hash::Request::new(hash))
.await
},
CompatMode::V0_37 => {
self.perform(endpoint::header_by_hash::Request::new(hash))
.await
Expand Down Expand Up @@ -885,9 +890,11 @@ impl WebSocketClientDriver {

async fn handle_text_msg(&mut self, msg: String) -> Result<(), Error> {
let parse_res = match self.compat {
CompatMode::V0_38 => event::v0_38::DeEvent::from_string(&msg).map(Into::into),
CompatMode::V0_37 => event::v0_37::DeEvent::from_string(&msg).map(Into::into),
CompatMode::V0_34 => event::v0_34::DeEvent::from_string(&msg).map(Into::into),
};

if let Ok(ev) = parse_res {
debug!("JSON-RPC event: {}", msg);
self.publish_event(ev).await;
Expand Down
4 changes: 3 additions & 1 deletion rpc/src/dialect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
pub mod v0_34;
pub mod v0_37;
pub use v0_37::Dialect as LatestDialect;
pub mod v0_38;
pub use v0_38::Dialect as LatestDialect;

mod begin_block;
mod check_tx;
Expand All @@ -29,4 +30,5 @@ mod sealed {

impl Sealed for super::v0_34::Dialect {}
impl Sealed for super::v0_37::Dialect {}
impl Sealed for super::v0_38::Dialect {}
}
6 changes: 6 additions & 0 deletions rpc/src/dialect/v0_37.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ impl From<evidence::Evidence> for Evidence {
Self(evidence)
}
}

impl From<Evidence> for evidence::Evidence {
fn from(evidence: Evidence) -> Self {
evidence.0
}
}
41 changes: 41 additions & 0 deletions rpc/src/dialect/v0_38.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use tendermint::evidence;
use tendermint_proto::v0_38 as raw;

use crate::prelude::*;
use serde::{Deserialize, Serialize};

/// The Event serialization in the latest RPC dialect is the canonical
/// serialization for the ABCI domain type.
pub use tendermint::abci::Event;

#[derive(Default, Clone)]
pub struct Dialect;

impl crate::dialect::Dialect for Dialect {
type Event = Event;
type Evidence = Evidence;
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(into = "raw::types::Evidence", try_from = "raw::types::Evidence")]
pub struct Evidence(evidence::Evidence);

impl From<Evidence> for raw::types::Evidence {
fn from(evidence: Evidence) -> Self {
evidence.0.into()
}
}

impl TryFrom<raw::types::Evidence> for Evidence {
type Error = <evidence::Evidence as TryFrom<raw::types::Evidence>>::Error;

fn try_from(value: raw::types::Evidence) -> Result<Self, Self::Error> {
Ok(Self(evidence::Evidence::try_from(value)?))
}
}

impl From<evidence::Evidence> for Evidence {
fn from(evidence: evidence::Evidence) -> Self {
Self(evidence)
}
}
Loading

0 comments on commit 4545671

Please sign in to comment.