From 3fa00dccea9b00d1e444d968692ca45acdd1bec7 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 15 Nov 2021 16:20:23 -0800 Subject: [PATCH 01/20] tendermint: add From for Error --- tendermint/src/error.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tendermint/src/error.rs b/tendermint/src/error.rs index 85cdfd7a7..e3506dd67 100644 --- a/tendermint/src/error.rs +++ b/tendermint/src/error.rs @@ -195,3 +195,9 @@ define_error! { |_| { "trust threshold too small (must be >= 1/3)" }, } } + +impl From for Error { + fn from(_never: core::convert::Infallible) -> Error { + unreachable!("Infallible can never be constructed") + } +} From 69f00821ef6541720940ac4a290117d1c064aaad Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 28 Jul 2021 15:35:58 -0700 Subject: [PATCH 02/20] Use hex for AppHash Debug formatting --- tendermint/src/hash.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tendermint/src/hash.rs b/tendermint/src/hash.rs index 237e640d4..b00271bb9 100644 --- a/tendermint/src/hash.rs +++ b/tendermint/src/hash.rs @@ -233,7 +233,11 @@ impl AsRef<[u8]> for AppHash { impl Debug for AppHash { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "hash::AppHash({:?})", self.0) + write!( + f, + "AppHash({})", + Hex::upper_case().encode_to_string(&self.0).unwrap() + ) } } From c43a78ec1b50859337ddbb17788f8ca3c1d5bf24 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Thu, 28 Oct 2021 15:29:28 -0700 Subject: [PATCH 03/20] Regenerate protobuf types using tools/proto-compiler. --- proto/src/prost/tendermint.crypto.rs | 42 +++++----- proto/src/prost/tendermint.p2p.rs | 46 +++++------ proto/src/prost/tendermint.types.rs | 112 +++++++++++++-------------- proto/src/tendermint.rs | 64 +++++++-------- 4 files changed, 132 insertions(+), 132 deletions(-) diff --git a/proto/src/prost/tendermint.crypto.rs b/proto/src/prost/tendermint.crypto.rs index 4b47ef593..0fac07973 100644 --- a/proto/src/prost/tendermint.crypto.rs +++ b/proto/src/prost/tendermint.crypto.rs @@ -1,24 +1,3 @@ -/// PublicKey defines the keys available for use with Tendermint Validators -#[derive(::serde::Deserialize, ::serde::Serialize)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PublicKey { - #[prost(oneof="public_key::Sum", tags="1, 2")] - pub sum: ::core::option::Option, -} -/// Nested message and enum types in `PublicKey`. -pub mod public_key { - #[derive(::serde::Deserialize, ::serde::Serialize)] - #[serde(tag = "type", content = "value")] - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Sum { - #[prost(bytes, tag="1")] - #[serde(rename = "tendermint/PubKeyEd25519", with = "crate::serializers::bytes::base64string")] - Ed25519(::prost::alloc::vec::Vec), - #[prost(bytes, tag="2")] - #[serde(rename = "tendermint/PubKeySecp256k1", with = "crate::serializers::bytes::base64string")] - Secp256k1(::prost::alloc::vec::Vec), - } -} #[derive(::serde::Deserialize, ::serde::Serialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Proof { @@ -71,3 +50,24 @@ pub struct ProofOps { #[prost(message, repeated, tag="1")] pub ops: ::prost::alloc::vec::Vec, } +/// PublicKey defines the keys available for use with Tendermint Validators +#[derive(::serde::Deserialize, ::serde::Serialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PublicKey { + #[prost(oneof="public_key::Sum", tags="1, 2")] + pub sum: ::core::option::Option, +} +/// Nested message and enum types in `PublicKey`. +pub mod public_key { + #[derive(::serde::Deserialize, ::serde::Serialize)] + #[serde(tag = "type", content = "value")] + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Sum { + #[prost(bytes, tag="1")] + #[serde(rename = "tendermint/PubKeyEd25519", with = "crate::serializers::bytes::base64string")] + Ed25519(::prost::alloc::vec::Vec), + #[prost(bytes, tag="2")] + #[serde(rename = "tendermint/PubKeySecp256k1", with = "crate::serializers::bytes::base64string")] + Secp256k1(::prost::alloc::vec::Vec), + } +} diff --git a/proto/src/prost/tendermint.p2p.rs b/proto/src/prost/tendermint.p2p.rs index 8ed7b702f..4dc33809c 100644 --- a/proto/src/prost/tendermint.p2p.rs +++ b/proto/src/prost/tendermint.p2p.rs @@ -43,29 +43,6 @@ pub struct DefaultNodeInfoOther { pub rpc_address: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] -pub struct PexRequest { -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PexAddrs { - #[prost(message, repeated, tag="1")] - pub addrs: ::prost::alloc::vec::Vec, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Message { - #[prost(oneof="message::Sum", tags="1, 2")] - pub sum: ::core::option::Option, -} -/// Nested message and enum types in `Message`. -pub mod message { - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Sum { - #[prost(message, tag="1")] - PexRequest(super::PexRequest), - #[prost(message, tag="2")] - PexAddrs(super::PexAddrs), - } -} -#[derive(Clone, PartialEq, ::prost::Message)] pub struct PacketPing { } #[derive(Clone, PartialEq, ::prost::Message)] @@ -104,3 +81,26 @@ pub struct AuthSigMessage { #[prost(bytes="vec", tag="2")] pub sig: ::prost::alloc::vec::Vec, } +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PexRequest { +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PexAddrs { + #[prost(message, repeated, tag="1")] + pub addrs: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Message { + #[prost(oneof="message::Sum", tags="1, 2")] + pub sum: ::core::option::Option, +} +/// Nested message and enum types in `Message`. +pub mod message { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Sum { + #[prost(message, tag="1")] + PexRequest(super::PexRequest), + #[prost(message, tag="2")] + PexAddrs(super::PexAddrs), + } +} diff --git a/proto/src/prost/tendermint.types.rs b/proto/src/prost/tendermint.types.rs index 61c23229e..d1beaa7ba 100644 --- a/proto/src/prost/tendermint.types.rs +++ b/proto/src/prost/tendermint.types.rs @@ -276,62 +276,6 @@ pub enum SignedMsgType { /// Proposals Proposal = 32, } -#[derive(::serde::Deserialize, ::serde::Serialize)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct CanonicalBlockId { - #[prost(bytes="vec", tag="1")] - pub hash: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag="2")] - #[serde(alias = "parts")] - pub part_set_header: ::core::option::Option, -} -#[derive(::serde::Deserialize, ::serde::Serialize)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct CanonicalPartSetHeader { - #[prost(uint32, tag="1")] - pub total: u32, - #[prost(bytes="vec", tag="2")] - pub hash: ::prost::alloc::vec::Vec, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct CanonicalProposal { - /// type alias for byte - #[prost(enumeration="SignedMsgType", tag="1")] - pub r#type: i32, - /// canonicalization requires fixed size encoding here - #[prost(sfixed64, tag="2")] - pub height: i64, - /// canonicalization requires fixed size encoding here - #[prost(sfixed64, tag="3")] - pub round: i64, - #[prost(int64, tag="4")] - pub pol_round: i64, - #[prost(message, optional, tag="5")] - pub block_id: ::core::option::Option, - #[prost(message, optional, tag="6")] - pub timestamp: ::core::option::Option, - #[prost(string, tag="7")] - pub chain_id: ::prost::alloc::string::String, -} -#[derive(::serde::Deserialize, ::serde::Serialize)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct CanonicalVote { - /// type alias for byte - #[prost(enumeration="SignedMsgType", tag="1")] - pub r#type: i32, - /// canonicalization requires fixed size encoding here - #[prost(sfixed64, tag="2")] - pub height: i64, - /// canonicalization requires fixed size encoding here - #[prost(sfixed64, tag="3")] - pub round: i64, - #[prost(message, optional, tag="4")] - pub block_id: ::core::option::Option, - #[prost(message, optional, tag="5")] - pub timestamp: ::core::option::Option, - #[prost(string, tag="6")] - pub chain_id: ::prost::alloc::string::String, -} #[derive(Clone, PartialEq, ::prost::Message)] pub struct EventDataRoundState { #[prost(int64, tag="1")] @@ -480,6 +424,62 @@ pub struct EvidenceList { } #[derive(::serde::Deserialize, ::serde::Serialize)] #[derive(Clone, PartialEq, ::prost::Message)] +pub struct CanonicalBlockId { + #[prost(bytes="vec", tag="1")] + pub hash: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="2")] + #[serde(alias = "parts")] + pub part_set_header: ::core::option::Option, +} +#[derive(::serde::Deserialize, ::serde::Serialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CanonicalPartSetHeader { + #[prost(uint32, tag="1")] + pub total: u32, + #[prost(bytes="vec", tag="2")] + pub hash: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CanonicalProposal { + /// type alias for byte + #[prost(enumeration="SignedMsgType", tag="1")] + pub r#type: i32, + /// canonicalization requires fixed size encoding here + #[prost(sfixed64, tag="2")] + pub height: i64, + /// canonicalization requires fixed size encoding here + #[prost(sfixed64, tag="3")] + pub round: i64, + #[prost(int64, tag="4")] + pub pol_round: i64, + #[prost(message, optional, tag="5")] + pub block_id: ::core::option::Option, + #[prost(message, optional, tag="6")] + pub timestamp: ::core::option::Option, + #[prost(string, tag="7")] + pub chain_id: ::prost::alloc::string::String, +} +#[derive(::serde::Deserialize, ::serde::Serialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CanonicalVote { + /// type alias for byte + #[prost(enumeration="SignedMsgType", tag="1")] + pub r#type: i32, + /// canonicalization requires fixed size encoding here + #[prost(sfixed64, tag="2")] + pub height: i64, + /// canonicalization requires fixed size encoding here + #[prost(sfixed64, tag="3")] + pub round: i64, + #[prost(message, optional, tag="4")] + pub block_id: ::core::option::Option, + #[prost(message, optional, tag="5")] + pub timestamp: ::core::option::Option, + #[prost(string, tag="6")] + pub chain_id: ::prost::alloc::string::String, +} +#[derive(::serde::Deserialize, ::serde::Serialize)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct Block { #[prost(message, optional, tag="1")] pub header: ::core::option::Option
, diff --git a/proto/src/tendermint.rs b/proto/src/tendermint.rs index 335cb2877..ca4916bce 100644 --- a/proto/src/tendermint.rs +++ b/proto/src/tendermint.rs @@ -1,63 +1,63 @@ //! Tendermint-proto auto-generated sub-modules for Tendermint -pub mod consensus { - include!("prost/tendermint.consensus.rs"); +pub mod statesync { + include!("prost/tendermint.statesync.rs"); } -pub mod types { - include!("prost/tendermint.types.rs"); +pub mod abci { + include!("prost/tendermint.abci.rs"); } -pub mod mempool { - include!("prost/tendermint.mempool.rs"); +pub mod store { + include!("prost/tendermint.store.rs"); } -pub mod rpc { - pub mod grpc { - include!("prost/tendermint.rpc.grpc.rs"); - } +pub mod version { + include!("prost/tendermint.version.rs"); } -pub mod blockchain { - include!("prost/tendermint.blockchain.rs"); +pub mod types { + include!("prost/tendermint.types.rs"); } -pub mod libs { - pub mod bits { - include!("prost/tendermint.libs.bits.rs"); - } +pub mod consensus { + include!("prost/tendermint.consensus.rs"); } -pub mod state { - include!("prost/tendermint.state.rs"); +pub mod p2p { + include!("prost/tendermint.p2p.rs"); } -pub mod version { - include!("prost/tendermint.version.rs"); +pub mod privval { + include!("prost/tendermint.privval.rs"); } -pub mod store { - include!("prost/tendermint.store.rs"); +pub mod blockchain { + include!("prost/tendermint.blockchain.rs"); } -pub mod privval { - include!("prost/tendermint.privval.rs"); +pub mod crypto { + include!("prost/tendermint.crypto.rs"); } -pub mod statesync { - include!("prost/tendermint.statesync.rs"); +pub mod mempool { + include!("prost/tendermint.mempool.rs"); } -pub mod p2p { - include!("prost/tendermint.p2p.rs"); +pub mod state { + include!("prost/tendermint.state.rs"); } -pub mod abci { - include!("prost/tendermint.abci.rs"); +pub mod libs { + pub mod bits { + include!("prost/tendermint.libs.bits.rs"); + } } -pub mod crypto { - include!("prost/tendermint.crypto.rs"); +pub mod rpc { + pub mod grpc { + include!("prost/tendermint.rpc.grpc.rs"); + } } pub mod meta { From 57dd21bc33705ad45b37e72cbe7b4df9bc8749f7 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Thu, 28 Oct 2021 15:36:39 -0700 Subject: [PATCH 04/20] Regenerate protos against tendermint v0.35.0-rc3. --- proto/src/prost/tendermint.abci.rs | 115 +++++-------- ....blockchain.rs => tendermint.blocksync.rs} | 0 proto/src/prost/tendermint.crypto.rs | 4 +- proto/src/prost/tendermint.p2p.rs | 79 ++++++--- proto/src/prost/tendermint.privval.rs | 10 ++ proto/src/prost/tendermint.statesync.rs | 32 +++- proto/src/prost/tendermint.store.rs | 7 - proto/src/prost/tendermint.types.rs | 158 +++++++++--------- proto/src/prost/tendermint.version.rs | 10 -- proto/src/tendermint.rs | 14 +- tools/proto-compiler/src/constants.rs | 2 +- 11 files changed, 224 insertions(+), 207 deletions(-) rename proto/src/prost/{tendermint.blockchain.rs => tendermint.blocksync.rs} (100%) delete mode 100644 proto/src/prost/tendermint.store.rs diff --git a/proto/src/prost/tendermint.abci.rs b/proto/src/prost/tendermint.abci.rs index 4e5142286..597346408 100644 --- a/proto/src/prost/tendermint.abci.rs +++ b/proto/src/prost/tendermint.abci.rs @@ -7,7 +7,7 @@ #[derive(Clone, PartialEq, ::prost::Message)] pub struct Request { - #[prost(oneof="request::Value", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15")] + #[prost(oneof="request::Value", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14")] pub value: ::core::option::Option, } /// Nested message and enum types in `Request`. @@ -21,28 +21,26 @@ pub mod request { #[prost(message, tag="3")] Info(super::RequestInfo), #[prost(message, tag="4")] - SetOption(super::RequestSetOption), - #[prost(message, tag="5")] InitChain(super::RequestInitChain), - #[prost(message, tag="6")] + #[prost(message, tag="5")] Query(super::RequestQuery), - #[prost(message, tag="7")] + #[prost(message, tag="6")] BeginBlock(super::RequestBeginBlock), - #[prost(message, tag="8")] + #[prost(message, tag="7")] CheckTx(super::RequestCheckTx), - #[prost(message, tag="9")] + #[prost(message, tag="8")] DeliverTx(super::RequestDeliverTx), - #[prost(message, tag="10")] + #[prost(message, tag="9")] EndBlock(super::RequestEndBlock), - #[prost(message, tag="11")] + #[prost(message, tag="10")] Commit(super::RequestCommit), - #[prost(message, tag="12")] + #[prost(message, tag="11")] ListSnapshots(super::RequestListSnapshots), - #[prost(message, tag="13")] + #[prost(message, tag="12")] OfferSnapshot(super::RequestOfferSnapshot), - #[prost(message, tag="14")] + #[prost(message, tag="13")] LoadSnapshotChunk(super::RequestLoadSnapshotChunk), - #[prost(message, tag="15")] + #[prost(message, tag="14")] ApplySnapshotChunk(super::RequestApplySnapshotChunk), } } @@ -62,14 +60,8 @@ pub struct RequestInfo { pub block_version: u64, #[prost(uint64, tag="3")] pub p2p_version: u64, -} -/// nondeterministic -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RequestSetOption { - #[prost(string, tag="1")] - pub key: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub value: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub abci_version: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RequestInitChain { @@ -78,7 +70,7 @@ pub struct RequestInitChain { #[prost(string, tag="2")] pub chain_id: ::prost::alloc::string::String, #[prost(message, optional, tag="3")] - pub consensus_params: ::core::option::Option, + pub consensus_params: ::core::option::Option, #[prost(message, repeated, tag="4")] pub validators: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="5")] @@ -167,7 +159,7 @@ pub struct RequestApplySnapshotChunk { #[derive(Clone, PartialEq, ::prost::Message)] pub struct Response { - #[prost(oneof="response::Value", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16")] + #[prost(oneof="response::Value", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15")] pub value: ::core::option::Option, } /// Nested message and enum types in `Response`. @@ -183,28 +175,26 @@ pub mod response { #[prost(message, tag="4")] Info(super::ResponseInfo), #[prost(message, tag="5")] - SetOption(super::ResponseSetOption), - #[prost(message, tag="6")] InitChain(super::ResponseInitChain), - #[prost(message, tag="7")] + #[prost(message, tag="6")] Query(super::ResponseQuery), - #[prost(message, tag="8")] + #[prost(message, tag="7")] BeginBlock(super::ResponseBeginBlock), - #[prost(message, tag="9")] + #[prost(message, tag="8")] CheckTx(super::ResponseCheckTx), - #[prost(message, tag="10")] + #[prost(message, tag="9")] DeliverTx(super::ResponseDeliverTx), - #[prost(message, tag="11")] + #[prost(message, tag="10")] EndBlock(super::ResponseEndBlock), - #[prost(message, tag="12")] + #[prost(message, tag="11")] Commit(super::ResponseCommit), - #[prost(message, tag="13")] + #[prost(message, tag="12")] ListSnapshots(super::ResponseListSnapshots), - #[prost(message, tag="14")] + #[prost(message, tag="13")] OfferSnapshot(super::ResponseOfferSnapshot), - #[prost(message, tag="15")] + #[prost(message, tag="14")] LoadSnapshotChunk(super::ResponseLoadSnapshotChunk), - #[prost(message, tag="16")] + #[prost(message, tag="15")] ApplySnapshotChunk(super::ResponseApplySnapshotChunk), } } @@ -227,6 +217,7 @@ pub struct ResponseFlush { pub struct ResponseInfo { #[prost(string, tag="1")] pub data: ::prost::alloc::string::String, + /// this is the software version of the application. TODO: remove? #[prost(string, tag="2")] pub version: ::prost::alloc::string::String, #[prost(uint64, tag="3")] @@ -239,21 +230,10 @@ pub struct ResponseInfo { #[serde(skip_serializing_if = "::prost::alloc::vec::Vec::is_empty", with = "serde_bytes")] pub last_block_app_hash: ::prost::alloc::vec::Vec, } -/// nondeterministic -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ResponseSetOption { - #[prost(uint32, tag="1")] - pub code: u32, - /// bytes data = 2; - #[prost(string, tag="3")] - pub log: ::prost::alloc::string::String, - #[prost(string, tag="4")] - pub info: ::prost::alloc::string::String, -} #[derive(Clone, PartialEq, ::prost::Message)] pub struct ResponseInitChain { #[prost(message, optional, tag="1")] - pub consensus_params: ::core::option::Option, + pub consensus_params: ::core::option::Option, #[prost(message, repeated, tag="2")] pub validators: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="3")] @@ -309,6 +289,14 @@ pub struct ResponseCheckTx { pub events: ::prost::alloc::vec::Vec, #[prost(string, tag="8")] pub codespace: ::prost::alloc::string::String, + #[prost(string, tag="9")] + pub sender: ::prost::alloc::string::String, + #[prost(int64, tag="10")] + pub priority: i64, + /// mempool_error is set by Tendermint. + /// ABCI applictions creating a ResponseCheckTX should not set mempool_error. + #[prost(string, tag="11")] + pub mempool_error: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ResponseDeliverTx { @@ -337,7 +325,7 @@ pub struct ResponseEndBlock { #[prost(message, repeated, tag="1")] pub validator_updates: ::prost::alloc::vec::Vec, #[prost(message, optional, tag="2")] - pub consensus_param_updates: ::core::option::Option, + pub consensus_param_updates: ::core::option::Option, #[prost(message, repeated, tag="3")] pub events: ::prost::alloc::vec::Vec, } @@ -416,29 +404,6 @@ pub mod response_apply_snapshot_chunk { //---------------------------------------- // Misc. -/// ConsensusParams contains all consensus-relevant parameters -/// that can be adjusted by the abci app -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ConsensusParams { - #[prost(message, optional, tag="1")] - pub block: ::core::option::Option, - #[prost(message, optional, tag="2")] - pub evidence: ::core::option::Option, - #[prost(message, optional, tag="3")] - pub validator: ::core::option::Option, - #[prost(message, optional, tag="4")] - pub version: ::core::option::Option, -} -/// BlockParams contains limits on the block size. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BlockParams { - /// Note: must be greater than 0 - #[prost(int64, tag="1")] - pub max_bytes: i64, - /// Note: must be greater or equal to -1 - #[prost(int64, tag="2")] - pub max_gas: i64, -} #[derive(Clone, PartialEq, ::prost::Message)] pub struct LastCommitInfo { #[prost(int32, tag="1")] @@ -459,10 +424,10 @@ pub struct Event { /// EventAttribute is a single key-value pair, associated with an event. #[derive(Clone, PartialEq, ::prost::Message)] pub struct EventAttribute { - #[prost(bytes="vec", tag="1")] - pub key: ::prost::alloc::vec::Vec, - #[prost(bytes="vec", tag="2")] - pub value: ::prost::alloc::vec::Vec, + #[prost(string, tag="1")] + pub key: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub value: ::prost::alloc::string::String, /// nondeterministic #[prost(bool, tag="3")] pub index: bool, diff --git a/proto/src/prost/tendermint.blockchain.rs b/proto/src/prost/tendermint.blocksync.rs similarity index 100% rename from proto/src/prost/tendermint.blockchain.rs rename to proto/src/prost/tendermint.blocksync.rs diff --git a/proto/src/prost/tendermint.crypto.rs b/proto/src/prost/tendermint.crypto.rs index 0fac07973..3266afdd5 100644 --- a/proto/src/prost/tendermint.crypto.rs +++ b/proto/src/prost/tendermint.crypto.rs @@ -54,7 +54,7 @@ pub struct ProofOps { #[derive(::serde::Deserialize, ::serde::Serialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct PublicKey { - #[prost(oneof="public_key::Sum", tags="1, 2")] + #[prost(oneof="public_key::Sum", tags="1, 2, 3")] pub sum: ::core::option::Option, } /// Nested message and enum types in `PublicKey`. @@ -69,5 +69,7 @@ pub mod public_key { #[prost(bytes, tag="2")] #[serde(rename = "tendermint/PubKeySecp256k1", with = "crate::serializers::bytes::base64string")] Secp256k1(::prost::alloc::vec::Vec), + #[prost(bytes, tag="3")] + Sr25519(::prost::alloc::vec::Vec), } } diff --git a/proto/src/prost/tendermint.p2p.rs b/proto/src/prost/tendermint.p2p.rs index 4dc33809c..4f1e500c4 100644 --- a/proto/src/prost/tendermint.p2p.rs +++ b/proto/src/prost/tendermint.p2p.rs @@ -1,13 +1,4 @@ #[derive(Clone, PartialEq, ::prost::Message)] -pub struct NetAddress { - #[prost(string, tag="1")] - pub id: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub ip: ::prost::alloc::string::String, - #[prost(uint32, tag="3")] - pub port: u32, -} -#[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtocolVersion { #[prost(uint64, tag="1")] pub p2p: u64, @@ -17,11 +8,11 @@ pub struct ProtocolVersion { pub app: u64, } #[derive(Clone, PartialEq, ::prost::Message)] -pub struct DefaultNodeInfo { +pub struct NodeInfo { #[prost(message, optional, tag="1")] pub protocol_version: ::core::option::Option, #[prost(string, tag="2")] - pub default_node_id: ::prost::alloc::string::String, + pub node_id: ::prost::alloc::string::String, #[prost(string, tag="3")] pub listen_addr: ::prost::alloc::string::String, #[prost(string, tag="4")] @@ -33,16 +24,36 @@ pub struct DefaultNodeInfo { #[prost(string, tag="7")] pub moniker: ::prost::alloc::string::String, #[prost(message, optional, tag="8")] - pub other: ::core::option::Option, + pub other: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] -pub struct DefaultNodeInfoOther { +pub struct NodeInfoOther { #[prost(string, tag="1")] pub tx_index: ::prost::alloc::string::String, #[prost(string, tag="2")] pub rpc_address: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] +pub struct PeerInfo { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(message, repeated, tag="2")] + pub address_info: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="3")] + pub last_connected: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PeerAddressInfo { + #[prost(string, tag="1")] + pub address: ::prost::alloc::string::String, + #[prost(message, optional, tag="2")] + pub last_dial_success: ::core::option::Option, + #[prost(message, optional, tag="3")] + pub last_dial_failure: ::core::option::Option, + #[prost(uint32, tag="4")] + pub dial_failures: u32, +} +#[derive(Clone, PartialEq, ::prost::Message)] pub struct PacketPing { } #[derive(Clone, PartialEq, ::prost::Message)] @@ -82,25 +93,51 @@ pub struct AuthSigMessage { pub sig: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] +pub struct PexAddress { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub ip: ::prost::alloc::string::String, + #[prost(uint32, tag="3")] + pub port: u32, +} +#[derive(Clone, PartialEq, ::prost::Message)] pub struct PexRequest { } #[derive(Clone, PartialEq, ::prost::Message)] -pub struct PexAddrs { +pub struct PexResponse { + #[prost(message, repeated, tag="1")] + pub addresses: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PexAddressV2 { + #[prost(string, tag="1")] + pub url: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PexRequestV2 { +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PexResponseV2 { #[prost(message, repeated, tag="1")] - pub addrs: ::prost::alloc::vec::Vec, + pub addresses: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] -pub struct Message { - #[prost(oneof="message::Sum", tags="1, 2")] - pub sum: ::core::option::Option, +pub struct PexMessage { + #[prost(oneof="pex_message::Sum", tags="1, 2, 3, 4")] + pub sum: ::core::option::Option, } -/// Nested message and enum types in `Message`. -pub mod message { +/// Nested message and enum types in `PexMessage`. +pub mod pex_message { #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Sum { #[prost(message, tag="1")] PexRequest(super::PexRequest), #[prost(message, tag="2")] - PexAddrs(super::PexAddrs), + PexResponse(super::PexResponse), + #[prost(message, tag="3")] + PexRequestV2(super::PexRequestV2), + #[prost(message, tag="4")] + PexResponseV2(super::PexResponseV2), } } diff --git a/proto/src/prost/tendermint.privval.rs b/proto/src/prost/tendermint.privval.rs index 8a86b3369..04fac20e6 100644 --- a/proto/src/prost/tendermint.privval.rs +++ b/proto/src/prost/tendermint.privval.rs @@ -86,6 +86,16 @@ pub mod message { PingResponse(super::PingResponse), } } +/// AuthSigMessage is duplicated from p2p prior to the P2P refactor. +/// It is used for the SecretConnection until we migrate privval to gRPC. +/// +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AuthSigMessage { + #[prost(message, optional, tag="1")] + pub pub_key: ::core::option::Option, + #[prost(bytes="vec", tag="2")] + pub sig: ::prost::alloc::vec::Vec, +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum Errors { diff --git a/proto/src/prost/tendermint.statesync.rs b/proto/src/prost/tendermint.statesync.rs index 593bd0222..c7e8d7f8a 100644 --- a/proto/src/prost/tendermint.statesync.rs +++ b/proto/src/prost/tendermint.statesync.rs @@ -1,6 +1,6 @@ #[derive(Clone, PartialEq, ::prost::Message)] pub struct Message { - #[prost(oneof="message::Sum", tags="1, 2, 3, 4")] + #[prost(oneof="message::Sum", tags="1, 2, 3, 4, 5, 6, 7, 8")] pub sum: ::core::option::Option, } /// Nested message and enum types in `Message`. @@ -15,6 +15,14 @@ pub mod message { ChunkRequest(super::ChunkRequest), #[prost(message, tag="4")] ChunkResponse(super::ChunkResponse), + #[prost(message, tag="5")] + LightBlockRequest(super::LightBlockRequest), + #[prost(message, tag="6")] + LightBlockResponse(super::LightBlockResponse), + #[prost(message, tag="7")] + ParamsRequest(super::ParamsRequest), + #[prost(message, tag="8")] + ParamsResponse(super::ParamsResponse), } } #[derive(Clone, PartialEq, ::prost::Message)] @@ -55,3 +63,25 @@ pub struct ChunkResponse { #[prost(bool, tag="5")] pub missing: bool, } +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LightBlockRequest { + #[prost(uint64, tag="1")] + pub height: u64, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LightBlockResponse { + #[prost(message, optional, tag="1")] + pub light_block: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ParamsRequest { + #[prost(uint64, tag="1")] + pub height: u64, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ParamsResponse { + #[prost(uint64, tag="1")] + pub height: u64, + #[prost(message, optional, tag="2")] + pub consensus_params: ::core::option::Option, +} diff --git a/proto/src/prost/tendermint.store.rs b/proto/src/prost/tendermint.store.rs deleted file mode 100644 index a4c2799d9..000000000 --- a/proto/src/prost/tendermint.store.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BlockStoreState { - #[prost(int64, tag="1")] - pub base: i64, - #[prost(int64, tag="2")] - pub height: i64, -} diff --git a/proto/src/prost/tendermint.types.rs b/proto/src/prost/tendermint.types.rs index d1beaa7ba..384b9f147 100644 --- a/proto/src/prost/tendermint.types.rs +++ b/proto/src/prost/tendermint.types.rs @@ -276,14 +276,76 @@ pub enum SignedMsgType { /// Proposals Proposal = 32, } +#[derive(::serde::Deserialize, ::serde::Serialize)] +#[serde(from = "crate::serializers::evidence::EvidenceVariant", into = "crate::serializers::evidence::EvidenceVariant")] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct EventDataRoundState { - #[prost(int64, tag="1")] - pub height: i64, - #[prost(int32, tag="2")] - pub round: i32, - #[prost(string, tag="3")] - pub step: ::prost::alloc::string::String, +pub struct Evidence { + #[prost(oneof="evidence::Sum", tags="1, 2")] + pub sum: ::core::option::Option, +} +/// Nested message and enum types in `Evidence`. +pub mod evidence { + #[derive(::serde::Deserialize, ::serde::Serialize)] + #[serde(tag = "type", content = "value")] + #[serde(from = "crate::serializers::evidence::EvidenceVariant", into = "crate::serializers::evidence::EvidenceVariant")] + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Sum { + #[prost(message, tag="1")] + #[serde(rename = "tendermint/DuplicateVoteEvidence")] + DuplicateVoteEvidence(super::DuplicateVoteEvidence), + #[prost(message, tag="2")] + #[serde(rename = "tendermint/LightClientAttackEvidence")] + LightClientAttackEvidence(super::LightClientAttackEvidence), + } +} +/// DuplicateVoteEvidence contains evidence of a validator signed two conflicting votes. +#[derive(::serde::Deserialize, ::serde::Serialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DuplicateVoteEvidence { + #[prost(message, optional, tag="1")] + pub vote_a: ::core::option::Option, + #[prost(message, optional, tag="2")] + pub vote_b: ::core::option::Option, + #[prost(int64, tag="3")] + pub total_voting_power: i64, + #[prost(int64, tag="4")] + pub validator_power: i64, + #[prost(message, optional, tag="5")] + pub timestamp: ::core::option::Option, +} +/// LightClientAttackEvidence contains evidence of a set of validators attempting to mislead a light client. +#[derive(::serde::Deserialize, ::serde::Serialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LightClientAttackEvidence { + #[prost(message, optional, tag="1")] + pub conflicting_block: ::core::option::Option, + #[prost(int64, tag="2")] + pub common_height: i64, + #[prost(message, repeated, tag="3")] + pub byzantine_validators: ::prost::alloc::vec::Vec, + #[prost(int64, tag="4")] + pub total_voting_power: i64, + #[prost(message, optional, tag="5")] + pub timestamp: ::core::option::Option, +} +#[derive(::serde::Deserialize, ::serde::Serialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EvidenceList { + #[prost(message, repeated, tag="1")] + #[serde(with = "crate::serializers::nullable")] + pub evidence: ::prost::alloc::vec::Vec, +} +#[derive(::serde::Deserialize, ::serde::Serialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Block { + #[prost(message, optional, tag="1")] + pub header: ::core::option::Option
, + #[prost(message, optional, tag="2")] + pub data: ::core::option::Option, + #[prost(message, optional, tag="3")] + pub evidence: ::core::option::Option, + #[prost(message, optional, tag="4")] + pub last_commit: ::core::option::Option, } /// ConsensusParams contains consensus critical parameters that determine the /// validity of blocks. @@ -309,12 +371,6 @@ pub struct BlockParams { /// Note: must be greater or equal to -1 #[prost(int64, tag="2")] pub max_gas: i64, - /// Minimum time increment between consecutive blocks (in milliseconds) If the - /// block header timestamp is ahead of the system clock, decrease this value. - /// - /// Not exposed to the application. - #[prost(int64, tag="3")] - pub time_iota_ms: i64, } /// EvidenceParams determine how we handle evidence of malfeasance. #[derive(::serde::Deserialize, ::serde::Serialize)] @@ -363,64 +419,14 @@ pub struct HashedParams { #[prost(int64, tag="2")] pub block_max_gas: i64, } -#[derive(::serde::Deserialize, ::serde::Serialize)] -#[serde(from = "crate::serializers::evidence::EvidenceVariant", into = "crate::serializers::evidence::EvidenceVariant")] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct Evidence { - #[prost(oneof="evidence::Sum", tags="1, 2")] - pub sum: ::core::option::Option, -} -/// Nested message and enum types in `Evidence`. -pub mod evidence { - #[derive(::serde::Deserialize, ::serde::Serialize)] - #[serde(tag = "type", content = "value")] - #[serde(from = "crate::serializers::evidence::EvidenceVariant", into = "crate::serializers::evidence::EvidenceVariant")] - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Sum { - #[prost(message, tag="1")] - #[serde(rename = "tendermint/DuplicateVoteEvidence")] - DuplicateVoteEvidence(super::DuplicateVoteEvidence), - #[prost(message, tag="2")] - #[serde(rename = "tendermint/LightClientAttackEvidence")] - LightClientAttackEvidence(super::LightClientAttackEvidence), - } -} -/// DuplicateVoteEvidence contains evidence of a validator signed two conflicting votes. -#[derive(::serde::Deserialize, ::serde::Serialize)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct DuplicateVoteEvidence { - #[prost(message, optional, tag="1")] - pub vote_a: ::core::option::Option, - #[prost(message, optional, tag="2")] - pub vote_b: ::core::option::Option, - #[prost(int64, tag="3")] - pub total_voting_power: i64, - #[prost(int64, tag="4")] - pub validator_power: i64, - #[prost(message, optional, tag="5")] - pub timestamp: ::core::option::Option, -} -/// LightClientAttackEvidence contains evidence of a set of validators attempting to mislead a light client. -#[derive(::serde::Deserialize, ::serde::Serialize)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct LightClientAttackEvidence { - #[prost(message, optional, tag="1")] - pub conflicting_block: ::core::option::Option, - #[prost(int64, tag="2")] - pub common_height: i64, - #[prost(message, repeated, tag="3")] - pub byzantine_validators: ::prost::alloc::vec::Vec, - #[prost(int64, tag="4")] - pub total_voting_power: i64, - #[prost(message, optional, tag="5")] - pub timestamp: ::core::option::Option, -} -#[derive(::serde::Deserialize, ::serde::Serialize)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct EvidenceList { - #[prost(message, repeated, tag="1")] - #[serde(with = "crate::serializers::nullable")] - pub evidence: ::prost::alloc::vec::Vec, +pub struct EventDataRoundState { + #[prost(int64, tag="1")] + pub height: i64, + #[prost(int32, tag="2")] + pub round: i32, + #[prost(string, tag="3")] + pub step: ::prost::alloc::string::String, } #[derive(::serde::Deserialize, ::serde::Serialize)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -478,15 +484,3 @@ pub struct CanonicalVote { #[prost(string, tag="6")] pub chain_id: ::prost::alloc::string::String, } -#[derive(::serde::Deserialize, ::serde::Serialize)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Block { - #[prost(message, optional, tag="1")] - pub header: ::core::option::Option
, - #[prost(message, optional, tag="2")] - pub data: ::core::option::Option, - #[prost(message, optional, tag="3")] - pub evidence: ::core::option::Option, - #[prost(message, optional, tag="4")] - pub last_commit: ::core::option::Option, -} diff --git a/proto/src/prost/tendermint.version.rs b/proto/src/prost/tendermint.version.rs index bd1227266..f9b227c15 100644 --- a/proto/src/prost/tendermint.version.rs +++ b/proto/src/prost/tendermint.version.rs @@ -1,13 +1,3 @@ -/// App includes the protocol and software version for the application. -/// This information is included in ResponseInfo. The App.Protocol can be -/// updated in ResponseEndBlock. -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct App { - #[prost(uint64, tag="1")] - pub protocol: u64, - #[prost(string, tag="2")] - pub software: ::prost::alloc::string::String, -} /// Consensus captures the consensus rules for processing a block in the blockchain, /// including all blockchain data structures and the rules of the application's /// state transition machine. diff --git a/proto/src/tendermint.rs b/proto/src/tendermint.rs index ca4916bce..cba47f38a 100644 --- a/proto/src/tendermint.rs +++ b/proto/src/tendermint.rs @@ -8,10 +8,6 @@ pub mod abci { include!("prost/tendermint.abci.rs"); } -pub mod store { - include!("prost/tendermint.store.rs"); -} - pub mod version { include!("prost/tendermint.version.rs"); } @@ -32,10 +28,6 @@ pub mod privval { include!("prost/tendermint.privval.rs"); } -pub mod blockchain { - include!("prost/tendermint.blockchain.rs"); -} - pub mod crypto { include!("prost/tendermint.crypto.rs"); } @@ -44,6 +36,10 @@ pub mod mempool { include!("prost/tendermint.mempool.rs"); } +pub mod blocksync { + include!("prost/tendermint.blocksync.rs"); +} + pub mod state { include!("prost/tendermint.state.rs"); } @@ -62,5 +58,5 @@ pub mod rpc { pub mod meta { pub const REPOSITORY: &str = "https://github.com/tendermint/tendermint"; - pub const COMMITISH: &str = "v0.34.9"; + pub const COMMITISH: &str = "v0.35.0-rc3"; } diff --git a/tools/proto-compiler/src/constants.rs b/tools/proto-compiler/src/constants.rs index 6a0fa439c..9eb8559c5 100644 --- a/tools/proto-compiler/src/constants.rs +++ b/tools/proto-compiler/src/constants.rs @@ -6,7 +6,7 @@ pub const TENDERMINT_REPO: &str = "https://github.com/tendermint/tendermint"; // Tag: v0.34.0-rc4 // Branch: master // Commit ID (full length): d7d0ffea13c60c98b812d243ba5a2c375f341c15 -pub const TENDERMINT_COMMITISH: &str = "v0.34.9"; +pub const TENDERMINT_COMMITISH: &str = "v0.35.0-rc3"; /// Predefined custom attributes for message annotations const PRIMITIVE_ENUM: &str = r#"#[derive(::num_derive::FromPrimitive, ::num_derive::ToPrimitive)]"#; From d6c8395e8c6688984285430a9b4c946a98bfc295 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 8 Sep 2021 20:37:35 -0700 Subject: [PATCH 05/20] Remove SetOption-related code in tendermint-abci. --- abci/src/application.rs | 11 ++--------- abci/src/client.rs | 12 +++--------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/abci/src/application.rs b/abci/src/application.rs index b4a848608..5cfe154d6 100644 --- a/abci/src/application.rs +++ b/abci/src/application.rs @@ -9,11 +9,11 @@ use tendermint_proto::abci::request::Value; use tendermint_proto::abci::{ response, Request, RequestApplySnapshotChunk, RequestBeginBlock, RequestCheckTx, RequestDeliverTx, RequestEcho, RequestEndBlock, RequestInfo, RequestInitChain, - RequestLoadSnapshotChunk, RequestOfferSnapshot, RequestQuery, RequestSetOption, Response, + RequestLoadSnapshotChunk, RequestOfferSnapshot, RequestQuery, Response, ResponseApplySnapshotChunk, ResponseBeginBlock, ResponseCheckTx, ResponseCommit, ResponseDeliverTx, ResponseEcho, ResponseEndBlock, ResponseFlush, ResponseInfo, ResponseInitChain, ResponseListSnapshots, ResponseLoadSnapshotChunk, ResponseOfferSnapshot, - ResponseQuery, ResponseSetOption, + ResponseQuery, }; /// An ABCI application. @@ -77,12 +77,6 @@ pub trait Application: Send + Clone + 'static { Default::default() } - /// Allows the Tendermint node to request that the application set an - /// option to a particular value. - fn set_option(&self, _request: RequestSetOption) -> ResponseSetOption { - Default::default() - } - /// Used during state sync to discover available snapshots on peers. fn list_snapshots(&self) -> ResponseListSnapshots { Default::default() @@ -124,7 +118,6 @@ impl RequestDispatcher for A { Value::Echo(req) => response::Value::Echo(self.echo(req)), Value::Flush(_) => response::Value::Flush(self.flush()), Value::Info(req) => response::Value::Info(self.info(req)), - Value::SetOption(req) => response::Value::SetOption(self.set_option(req)), Value::InitChain(req) => response::Value::InitChain(self.init_chain(req)), Value::Query(req) => response::Value::Query(self.query(req)), Value::BeginBlock(req) => response::Value::BeginBlock(self.begin_block(req)), diff --git a/abci/src/client.rs b/abci/src/client.rs index c5146f88a..c2e11ddba 100644 --- a/abci/src/client.rs +++ b/abci/src/client.rs @@ -7,10 +7,9 @@ use tendermint_proto::abci::{ request, response, RequestApplySnapshotChunk, RequestBeginBlock, RequestCheckTx, RequestCommit, RequestDeliverTx, RequestEndBlock, RequestFlush, RequestInfo, RequestInitChain, RequestListSnapshots, RequestLoadSnapshotChunk, RequestOfferSnapshot, RequestQuery, - RequestSetOption, ResponseApplySnapshotChunk, ResponseBeginBlock, ResponseCheckTx, - ResponseCommit, ResponseDeliverTx, ResponseEndBlock, ResponseFlush, ResponseInfo, - ResponseInitChain, ResponseListSnapshots, ResponseLoadSnapshotChunk, ResponseOfferSnapshot, - ResponseQuery, ResponseSetOption, + ResponseApplySnapshotChunk, ResponseBeginBlock, ResponseCheckTx, ResponseCommit, + ResponseDeliverTx, ResponseEndBlock, ResponseFlush, ResponseInfo, ResponseInitChain, + ResponseListSnapshots, ResponseLoadSnapshotChunk, ResponseOfferSnapshot, ResponseQuery, }; use tendermint_proto::abci::{Request, RequestEcho, ResponseEcho}; @@ -113,11 +112,6 @@ impl Client { perform!(self, Commit, RequestCommit {}) } - /// Request that the application set an option to a particular value. - pub fn set_option(&mut self, req: RequestSetOption) -> Result { - perform!(self, SetOption, req) - } - /// Used during state sync to discover available snapshots on peers. pub fn list_snapshots(&mut self) -> Result { perform!(self, ListSnapshots, RequestListSnapshots {}) From 39a9bd43cbeba16ece5291ceabe5e3ddbc421124 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 8 Sep 2021 20:47:29 -0700 Subject: [PATCH 06/20] Update imports to reflect protobuf movements. The BlockParams and ConsensusParams structs moved out of the ABCI protos. --- tendermint/src/block/size.rs | 2 +- tendermint/src/consensus/params.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tendermint/src/block/size.rs b/tendermint/src/block/size.rs index 0781e9058..3260bfeb6 100644 --- a/tendermint/src/block/size.rs +++ b/tendermint/src/block/size.rs @@ -6,7 +6,7 @@ use tendermint_proto::Protobuf; use { crate::serializers, serde::{Deserialize, Serialize}, - tendermint_proto::abci::BlockParams as RawSize, + tendermint_proto::types::BlockParams as RawSize, }; /// Block size parameters diff --git a/tendermint/src/consensus/params.rs b/tendermint/src/consensus/params.rs index 25e2af838..af42fd838 100644 --- a/tendermint/src/consensus/params.rs +++ b/tendermint/src/consensus/params.rs @@ -5,7 +5,7 @@ use crate::prelude::*; use crate::{block, evidence, public_key}; use core::convert::{TryFrom, TryInto}; use serde::{Deserialize, Serialize}; -use tendermint_proto::abci::ConsensusParams as RawParams; +use tendermint_proto::types::ConsensusParams as RawParams; use tendermint_proto::types::ValidatorParams as RawValidatorParams; use tendermint_proto::types::VersionParams as RawVersionParams; use tendermint_proto::Protobuf; From 6e48efa16c2aa4e9e799fddb099e5a7b8de5076b Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 8 Sep 2021 21:26:18 -0700 Subject: [PATCH 07/20] Update tendermint-abci to reflect upstream proto changes. --- abci/src/application/kvstore.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/abci/src/application/kvstore.rs b/abci/src/application/kvstore.rs index 57a687345..e1f6f443e 100644 --- a/abci/src/application/kvstore.rs +++ b/abci/src/application/kvstore.rs @@ -172,6 +172,9 @@ impl Application for KeyValueStoreApp { gas_used: 0, events: vec![], codespace: "".to_string(), + mempool_error: "".to_string(), + priority: 0, + sender: "".to_string(), } } @@ -195,18 +198,18 @@ impl Application for KeyValueStoreApp { r#type: "app".to_string(), attributes: vec![ EventAttribute { - key: "key".as_bytes().to_owned(), - value: key.as_bytes().to_owned(), + key: "key".to_string(), + value: key.to_string(), index: true, }, EventAttribute { - key: "index_key".as_bytes().to_owned(), - value: "index is working".as_bytes().to_owned(), + key: "index_key".to_string(), + value: "index is working".to_string(), index: true, }, EventAttribute { - key: "noindex_key".as_bytes().to_owned(), - value: "index is working".as_bytes().to_owned(), + key: "noindex_key".to_string(), + value: "index is working".to_string(), index: false, }, ], From ee4c84a5cf1b081dc4c607b00cb246cd52ce2e61 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 8 Sep 2021 21:31:57 -0700 Subject: [PATCH 08/20] p2p: treat all non-Ed25519 keys as unsupported This fixes a compile error introduced by upstream proto changes that add an Sr25519 variant. --- p2p/src/secret_connection.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/p2p/src/secret_connection.rs b/p2p/src/secret_connection.rs index 18581a1b6..28c165891 100644 --- a/p2p/src/secret_connection.rs +++ b/p2p/src/secret_connection.rs @@ -185,7 +185,7 @@ impl Handshake { proto::crypto::public_key::Sum::Ed25519(ref bytes) => { ed25519::PublicKey::from_bytes(bytes).map_err(Error::signature) } - proto::crypto::public_key::Sum::Secp256k1(_) => Err(Error::unsupported_key()), + _ => Err(Error::unsupported_key()), }?; let remote_sig = From d9ed69aa6af07373387ad915153605e83ccc023f Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 2 Aug 2021 12:19:05 -0700 Subject: [PATCH 09/20] Improve ABCI response code modeling with NonZeroU32 The previous data modeling allowed a user to construct an `Err(0)` value that would be serialized and deserialized as `Ok`. --- tendermint/src/abci/code.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tendermint/src/abci/code.rs b/tendermint/src/abci/code.rs index 5a10dedfc..ccc53958a 100644 --- a/tendermint/src/abci/code.rs +++ b/tendermint/src/abci/code.rs @@ -1,4 +1,4 @@ -use core::fmt; +use core::{fmt, num::NonZeroU32}; use serde::de::{Deserialize, Deserializer, Visitor}; use serde::{Serialize, Serializer}; @@ -15,7 +15,7 @@ pub enum Code { Ok, /// Error codes - Err(u32), + Err(NonZeroU32), } impl Default for Code { @@ -46,9 +46,9 @@ impl Code { impl From for Code { fn from(value: u32) -> Code { - match value { - 0 => Code::Ok, - err => Code::Err(err), + match NonZeroU32::new(value) { + Some(value) => Code::Err(value), + None => Code::Ok, } } } @@ -57,7 +57,7 @@ impl From for u32 { fn from(code: Code) -> u32 { match code { Code::Ok => 0, - Code::Err(err) => err, + Code::Err(err) => err.get(), } } } From 4f477121682ecd915de1970098fef86c6ac87961 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 14 Apr 2021 11:32:26 -0700 Subject: [PATCH 10/20] Use the Bytes type in ABCI protos. --- abci/src/application/kvstore.rs | 18 +++---- abci/tests/kvstore_app.rs | 6 +-- proto/Cargo.toml | 2 +- proto/src/prost/tendermint.abci.rs | 78 +++++++++++++-------------- rpc/src/endpoint/abci_info.rs | 7 +-- rpc/tests/kvstore_fixtures.rs | 2 +- tendermint/Cargo.toml | 2 +- tools/proto-compiler/src/constants.rs | 5 +- tools/proto-compiler/src/main.rs | 6 ++- 9 files changed, 65 insertions(+), 61 deletions(-) diff --git a/abci/src/application/kvstore.rs b/abci/src/application/kvstore.rs index e1f6f443e..b3ffdb429 100644 --- a/abci/src/application/kvstore.rs +++ b/abci/src/application/kvstore.rs @@ -123,17 +123,17 @@ impl Application for KeyValueStoreApp { version: "0.1.0".to_string(), app_version: 1, last_block_height, - last_block_app_hash, + last_block_app_hash: last_block_app_hash.into(), } } fn query(&self, request: RequestQuery) -> ResponseQuery { - let key = match String::from_utf8(request.data.clone()) { + let key = match std::str::from_utf8(&request.data) { Ok(s) => s, Err(e) => panic!("Failed to intepret key as UTF-8: {}", e), }; debug!("Attempting to get key: {}", key); - match self.get(key.clone()) { + match self.get(key) { Ok((height, value_opt)) => match value_opt { Some(value) => ResponseQuery { code: 0, @@ -141,7 +141,7 @@ impl Application for KeyValueStoreApp { info: "".to_string(), index: 0, key: request.data, - value: value.into_bytes(), + value: value.into_bytes().into(), proof_ops: None, height, codespace: "".to_string(), @@ -152,7 +152,7 @@ impl Application for KeyValueStoreApp { info: "".to_string(), index: 0, key: request.data, - value: vec![], + value: Default::default(), proof_ops: None, height, codespace: "".to_string(), @@ -165,7 +165,7 @@ impl Application for KeyValueStoreApp { fn check_tx(&self, _request: RequestCheckTx) -> ResponseCheckTx { ResponseCheckTx { code: 0, - data: vec![], + data: Default::default(), log: "".to_string(), info: "".to_string(), gas_wanted: 1, @@ -179,7 +179,7 @@ impl Application for KeyValueStoreApp { } fn deliver_tx(&self, request: RequestDeliverTx) -> ResponseDeliverTx { - let tx = String::from_utf8(request.tx).unwrap(); + let tx = std::str::from_utf8(&request.tx).unwrap(); let tx_parts = tx.split('=').collect::>(); let (key, value) = if tx_parts.len() == 2 { (tx_parts[0], tx_parts[1]) @@ -189,7 +189,7 @@ impl Application for KeyValueStoreApp { let _ = self.set(key, value).unwrap(); ResponseDeliverTx { code: 0, - data: vec![], + data: Default::default(), log: "".to_string(), info: "".to_string(), gas_wanted: 0, @@ -224,7 +224,7 @@ impl Application for KeyValueStoreApp { let (height, app_hash) = channel_recv(&result_rx).unwrap(); info!("Committed height {}", height); ResponseCommit { - data: app_hash, + data: app_hash.into(), retain_height: height - 1, } } diff --git a/abci/tests/kvstore_app.rs b/abci/tests/kvstore_app.rs index 62a1c51d6..060a6cc7f 100644 --- a/abci/tests/kvstore_app.rs +++ b/abci/tests/kvstore_app.rs @@ -24,19 +24,19 @@ mod kvstore_app_integration { client .deliver_tx(RequestDeliverTx { - tx: "test-key=test-value".as_bytes().to_owned(), + tx: "test-key=test-value".as_bytes().into(), }) .unwrap(); client.commit().unwrap(); let res = client .query(RequestQuery { - data: "test-key".as_bytes().to_owned(), + data: "test-key".as_bytes().into(), path: "".to_string(), height: 0, prove: false, }) .unwrap(); - assert_eq!(res.value, "test-value".as_bytes().to_owned()); + assert_eq!(res.value, "test-value".as_bytes()); } } diff --git a/proto/Cargo.toml b/proto/Cargo.toml index 6fdede136..3b836564e 100644 --- a/proto/Cargo.toml +++ b/proto/Cargo.toml @@ -19,7 +19,7 @@ all-features = true [dependencies] prost = { version = "0.9", default-features = false } prost-types = { version = "0.9", default-features = false } -bytes = { version = "1.0", default-features = false } +bytes = { version = "1.0", default-features = false, features = ["serde"] } serde = { version = "1.0", default-features = false, features = ["derive"] } serde_bytes = { version = "0.11", default-features = false, features = ["alloc"] } subtle-encoding = { version = "0.5", default-features = false, features = ["hex", "base64", "alloc"] } diff --git a/proto/src/prost/tendermint.abci.rs b/proto/src/prost/tendermint.abci.rs index 597346408..2a42bbd53 100644 --- a/proto/src/prost/tendermint.abci.rs +++ b/proto/src/prost/tendermint.abci.rs @@ -73,15 +73,15 @@ pub struct RequestInitChain { pub consensus_params: ::core::option::Option, #[prost(message, repeated, tag="4")] pub validators: ::prost::alloc::vec::Vec, - #[prost(bytes="vec", tag="5")] - pub app_state_bytes: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="5")] + pub app_state_bytes: ::prost::bytes::Bytes, #[prost(int64, tag="6")] pub initial_height: i64, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RequestQuery { - #[prost(bytes="vec", tag="1")] - pub data: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="1")] + pub data: ::prost::bytes::Bytes, #[prost(string, tag="2")] pub path: ::prost::alloc::string::String, #[prost(int64, tag="3")] @@ -91,8 +91,8 @@ pub struct RequestQuery { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RequestBeginBlock { - #[prost(bytes="vec", tag="1")] - pub hash: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="1")] + pub hash: ::prost::bytes::Bytes, #[prost(message, optional, tag="2")] pub header: ::core::option::Option, #[prost(message, optional, tag="3")] @@ -102,15 +102,15 @@ pub struct RequestBeginBlock { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RequestCheckTx { - #[prost(bytes="vec", tag="1")] - pub tx: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="1")] + pub tx: ::prost::bytes::Bytes, #[prost(enumeration="CheckTxType", tag="2")] pub r#type: i32, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RequestDeliverTx { - #[prost(bytes="vec", tag="1")] - pub tx: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="1")] + pub tx: ::prost::bytes::Bytes, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RequestEndBlock { @@ -131,8 +131,8 @@ pub struct RequestOfferSnapshot { #[prost(message, optional, tag="1")] pub snapshot: ::core::option::Option, /// light client-verified app hash for snapshot height - #[prost(bytes="vec", tag="2")] - pub app_hash: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="2")] + pub app_hash: ::prost::bytes::Bytes, } /// loads a snapshot chunk #[derive(Clone, PartialEq, ::prost::Message)] @@ -149,8 +149,8 @@ pub struct RequestLoadSnapshotChunk { pub struct RequestApplySnapshotChunk { #[prost(uint32, tag="1")] pub index: u32, - #[prost(bytes="vec", tag="2")] - pub chunk: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="2")] + pub chunk: ::prost::bytes::Bytes, #[prost(string, tag="3")] pub sender: ::prost::alloc::string::String, } @@ -226,9 +226,9 @@ pub struct ResponseInfo { #[prost(int64, tag="4")] #[serde(with = "crate::serializers::from_str")] pub last_block_height: i64, - #[prost(bytes="vec", tag="5")] - #[serde(skip_serializing_if = "::prost::alloc::vec::Vec::is_empty", with = "serde_bytes")] - pub last_block_app_hash: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="5")] + #[serde(skip_serializing_if = "bytes::Bytes::is_empty")] + pub last_block_app_hash: ::prost::bytes::Bytes, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ResponseInitChain { @@ -236,8 +236,8 @@ pub struct ResponseInitChain { pub consensus_params: ::core::option::Option, #[prost(message, repeated, tag="2")] pub validators: ::prost::alloc::vec::Vec, - #[prost(bytes="vec", tag="3")] - pub app_hash: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="3")] + pub app_hash: ::prost::bytes::Bytes, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ResponseQuery { @@ -253,10 +253,10 @@ pub struct ResponseQuery { pub info: ::prost::alloc::string::String, #[prost(int64, tag="5")] pub index: i64, - #[prost(bytes="vec", tag="6")] - pub key: ::prost::alloc::vec::Vec, - #[prost(bytes="vec", tag="7")] - pub value: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="6")] + pub key: ::prost::bytes::Bytes, + #[prost(bytes="bytes", tag="7")] + pub value: ::prost::bytes::Bytes, #[prost(message, optional, tag="8")] pub proof_ops: ::core::option::Option, #[prost(int64, tag="9")] @@ -273,8 +273,8 @@ pub struct ResponseBeginBlock { pub struct ResponseCheckTx { #[prost(uint32, tag="1")] pub code: u32, - #[prost(bytes="vec", tag="2")] - pub data: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="2")] + pub data: ::prost::bytes::Bytes, /// nondeterministic #[prost(string, tag="3")] pub log: ::prost::alloc::string::String, @@ -302,8 +302,8 @@ pub struct ResponseCheckTx { pub struct ResponseDeliverTx { #[prost(uint32, tag="1")] pub code: u32, - #[prost(bytes="vec", tag="2")] - pub data: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="2")] + pub data: ::prost::bytes::Bytes, /// nondeterministic #[prost(string, tag="3")] pub log: ::prost::alloc::string::String, @@ -332,8 +332,8 @@ pub struct ResponseEndBlock { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ResponseCommit { /// reserve 1 - #[prost(bytes="vec", tag="2")] - pub data: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="2")] + pub data: ::prost::bytes::Bytes, #[prost(int64, tag="3")] pub retain_height: i64, } @@ -368,8 +368,8 @@ pub mod response_offer_snapshot { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ResponseLoadSnapshotChunk { - #[prost(bytes="vec", tag="1")] - pub chunk: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="1")] + pub chunk: ::prost::bytes::Bytes, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ResponseApplySnapshotChunk { @@ -441,8 +441,8 @@ pub struct TxResult { pub height: i64, #[prost(uint32, tag="2")] pub index: u32, - #[prost(bytes="vec", tag="3")] - pub tx: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="3")] + pub tx: ::prost::bytes::Bytes, #[prost(message, optional, tag="4")] pub result: ::core::option::Option, } @@ -453,8 +453,8 @@ pub struct TxResult { #[derive(Clone, PartialEq, ::prost::Message)] pub struct Validator { /// The first 20 bytes of SHA256(public key) - #[prost(bytes="vec", tag="1")] - pub address: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="1")] + pub address: ::prost::bytes::Bytes, /// PubKey pub_key = 2 \[(gogoproto.nullable)=false\]; /// /// The voting power @@ -511,11 +511,11 @@ pub struct Snapshot { #[prost(uint32, tag="3")] pub chunks: u32, /// Arbitrary snapshot hash, equal only if identical - #[prost(bytes="vec", tag="4")] - pub hash: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="4")] + pub hash: ::prost::bytes::Bytes, /// Arbitrary application metadata - #[prost(bytes="vec", tag="5")] - pub metadata: ::prost::alloc::vec::Vec, + #[prost(bytes="bytes", tag="5")] + pub metadata: ::prost::bytes::Bytes, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] diff --git a/rpc/src/endpoint/abci_info.rs b/rpc/src/endpoint/abci_info.rs index 37e6fd90a..212d58a4c 100644 --- a/rpc/src/endpoint/abci_info.rs +++ b/rpc/src/endpoint/abci_info.rs @@ -1,8 +1,9 @@ //! `/abci_info` endpoint JSON-RPC wrapper -use serde::{Deserialize, Serialize}; - use core::convert::{TryFrom, TryInto}; + +use bytes::Bytes; +use serde::{Deserialize, Serialize}; use tendermint::block; use tendermint::Error; use tendermint_proto::abci::ResponseInfo; @@ -49,7 +50,7 @@ pub struct AbciInfo { pub last_block_height: block::Height, /// Last app hash for the block - pub last_block_app_hash: Vec, + pub last_block_app_hash: Bytes, } impl TryFrom for AbciInfo { diff --git a/rpc/tests/kvstore_fixtures.rs b/rpc/tests/kvstore_fixtures.rs index 1fb40251d..5fd578059 100644 --- a/rpc/tests/kvstore_fixtures.rs +++ b/rpc/tests/kvstore_fixtures.rs @@ -318,7 +318,7 @@ fn incoming_fixtures() { let result = endpoint::abci_info::Response::from_string(content).unwrap(); assert_eq!(result.response.app_version, 1); assert_eq!(result.response.data, "{\"size\":0}"); - assert_eq!(result.response.last_block_app_hash, b"AAAAAAAAAAA="); + assert_eq!(result.response.last_block_app_hash, b"AAAAAAAAAAA="[..]); assert_eq!(result.response.version, "0.17.0"); } "abci_query_with_existing_key" => { diff --git a/tendermint/Cargo.toml b/tendermint/Cargo.toml index d29e95fdf..ca84f2ee5 100644 --- a/tendermint/Cargo.toml +++ b/tendermint/Cargo.toml @@ -34,7 +34,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] async-trait = { version = "0.1", default-features = false } -bytes = { version = "1.0", default-features = false } +bytes = { version = "1.0", default-features = false, features = ["serde"] } chrono = { version = "0.4.19", default-features = false, features = ["serde"] } ed25519 = { version = "1", default-features = false } ed25519-dalek = { version = "1", default-features = false, features = ["u64_backend"] } diff --git a/tools/proto-compiler/src/constants.rs b/tools/proto-compiler/src/constants.rs index 9eb8559c5..3ff56a3e4 100644 --- a/tools/proto-compiler/src/constants.rs +++ b/tools/proto-compiler/src/constants.rs @@ -20,8 +20,7 @@ const HEXSTRING: &str = r#"#[serde(with = "crate::serializers::bytes::hexstring" const BASE64STRING: &str = r#"#[serde(with = "crate::serializers::bytes::base64string")]"#; const VEC_BASE64STRING: &str = r#"#[serde(with = "crate::serializers::bytes::vec_base64string")]"#; const OPTIONAL: &str = r#"#[serde(with = "crate::serializers::optional")]"#; -const VEC_SKIP_IF_EMPTY: &str = - r#"#[serde(skip_serializing_if = "::prost::alloc::vec::Vec::is_empty", with = "serde_bytes")]"#; +const BYTES_SKIP_IF_EMPTY: &str = r#"#[serde(skip_serializing_if = "bytes::Bytes::is_empty")]"#; const NULLABLEVECARRAY: &str = r#"#[serde(with = "crate::serializers::txs")]"#; const NULLABLE: &str = r#"#[serde(with = "crate::serializers::nullable")]"#; const ALIAS_POWER_QUOTED: &str = @@ -90,7 +89,7 @@ pub static CUSTOM_FIELD_ATTRIBUTES: &[(&str, &str)] = &[ (".tendermint.version.Consensus.app", QUOTED_WITH_DEFAULT), ( ".tendermint.abci.ResponseInfo.last_block_app_hash", - VEC_SKIP_IF_EMPTY, + BYTES_SKIP_IF_EMPTY, ), (".tendermint.abci.ResponseInfo.app_version", QUOTED), (".tendermint.types.BlockID.hash", HEXSTRING), diff --git a/tools/proto-compiler/src/main.rs b/tools/proto-compiler/src/main.rs index 8be0203d4..7de037997 100644 --- a/tools/proto-compiler/src/main.rs +++ b/tools/proto-compiler/src/main.rs @@ -55,8 +55,12 @@ fn main() { // List available proto files let protos = find_proto_files(proto_paths); - // Compile proto files with added annotations, exchange prost_types to our own let mut pb = prost_build::Config::new(); + + // Use shared Bytes buffers for ABCI messages: + pb.bytes(&[".tendermint.abci"]); + + // Compile proto files with added annotations, exchange prost_types to our own pb.out_dir(&out_dir); for type_attribute in CUSTOM_TYPE_ATTRIBUTES { pb.type_attribute(type_attribute.0, type_attribute.1); From 156cce968451631f2a88ebd584474b756d750d3e Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 14 Apr 2021 16:31:28 -0700 Subject: [PATCH 11/20] Add conversions between protobuf and chrono types. --- proto/src/chrono.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++ proto/src/lib.rs | 1 + 2 files changed, 54 insertions(+) create mode 100644 proto/src/chrono.rs diff --git a/proto/src/chrono.rs b/proto/src/chrono.rs new file mode 100644 index 000000000..3b969f0f0 --- /dev/null +++ b/proto/src/chrono.rs @@ -0,0 +1,53 @@ +use core::convert::TryInto; + +use chrono::{DateTime, Duration, TimeZone, Utc}; + +use crate::google::protobuf as pb; + +impl From> for pb::Timestamp { + fn from(dt: DateTime) -> pb::Timestamp { + pb::Timestamp { + seconds: dt.timestamp(), + // This can exceed 1_000_000_000 in the case of a leap second, but + // even with a leap second it should be under 2_147_483_647. + nanos: dt + .timestamp_subsec_nanos() + .try_into() + .expect("timestamp_subsec_nanos bigger than i32::MAX"), + } + } +} + +impl From for DateTime { + fn from(ts: pb::Timestamp) -> DateTime { + Utc.timestamp(ts.seconds, ts.nanos as u32) + } +} + +// Note: we convert a protobuf::Duration into a chrono::Duration, not a +// std::time::Duration, because std::time::Durations are unsigned, but the +// protobuf duration is signed. + +impl From for pb::Duration { + fn from(d: Duration) -> pb::Duration { + // chrono's Duration stores the fractional part as `nanos: i32` + // internally but doesn't provide a way to access it, only a way to get + // the *total* number of nanoseconds. so we have to do this cool and fun + // hoop-jumping maneuver + let seconds = d.num_seconds(); + let nanos = (d - Duration::seconds(seconds)) + .num_nanoseconds() + .expect("we computed the fractional part, so there's no overflow") + .try_into() + .expect("the fractional part fits in i32"); + + pb::Duration { seconds, nanos } + } +} + +impl From for Duration { + fn from(d: pb::Duration) -> Duration { + // there's no constructor that supplies both at once + Duration::seconds(d.seconds) + Duration::nanoseconds(d.nanos as i64) + } +} diff --git a/proto/src/lib.rs b/proto/src/lib.rs index 018ea6216..f306f87ab 100644 --- a/proto/src/lib.rs +++ b/proto/src/lib.rs @@ -20,6 +20,7 @@ pub mod google { } } +mod chrono; mod error; #[allow(warnings)] mod tendermint; From 89e665984f33f0a97355edb0b56a68d406d3966e Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Thu, 9 Sep 2021 17:58:32 -0700 Subject: [PATCH 12/20] tendermint: define Serde for Block in terms of RawBlock This changes the Serialize/Deserialize implementations for Block to convert to/from the proto-generated `RawBlock`, and use the derived serialization for that type. This is much cleaner and more maintainable than keeping Serde annotations for each sub-member of the data structure, because all of the serialization code is kept in one place, and there's only one validation path (the TryFrom conversion from RawBlock to Block) that applies to both kinds of serialization. --- tendermint/src/block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tendermint/src/block.rs b/tendermint/src/block.rs index d16d29944..58188bc42 100644 --- a/tendermint/src/block.rs +++ b/tendermint/src/block.rs @@ -35,6 +35,7 @@ use tendermint_proto::Protobuf; // Default serialization - all fields serialize; used by /block endpoint #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] #[non_exhaustive] +#[serde(try_from = "RawBlock", into = "RawBlock")] pub struct Block { /// Block header pub header: Header, @@ -46,7 +47,6 @@ pub struct Block { pub evidence: evidence::Data, /// Last commit - #[serde(with = "crate::serializers::optional")] pub last_commit: Option, } From 9beadce9e606402b350c283ea5f17ebf0f26ea61 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Thu, 9 Sep 2021 16:19:21 -0700 Subject: [PATCH 13/20] tendermint: simpler transaction modeling in Block This changes the Block type to hold the transactions as a plain `Vec>`, rather than as a custom `abci::transaction::Data` type (which is itself a wrapper for an `Option>`, the `Transaction` type being a wrapper for a `Vec`). This also updates the `Block` getter functions; it's not clear (to me) why they're there, since they access the public fields and aren't used anywhere else. --- tendermint/src/block.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tendermint/src/block.rs b/tendermint/src/block.rs index 58188bc42..b95b65f13 100644 --- a/tendermint/src/block.rs +++ b/tendermint/src/block.rs @@ -22,7 +22,7 @@ pub use self::{ size::Size, }; use crate::prelude::*; -use crate::{abci::transaction, error::Error, evidence}; +use crate::{error::Error, evidence}; use core::convert::{TryFrom, TryInto}; use serde::{Deserialize, Serialize}; use tendermint_proto::types::Block as RawBlock; @@ -41,7 +41,7 @@ pub struct Block { pub header: Header, /// Transaction data - pub data: transaction::Data, + pub data: Vec>, /// Evidence of malfeasance pub evidence: evidence::Data, @@ -75,7 +75,7 @@ impl TryFrom for Block { //} Ok(Block { header, - data: value.data.ok_or_else(Error::missing_data)?.into(), + data: value.data.ok_or_else(Error::missing_data)?.txs, evidence: value .evidence .ok_or_else(Error::missing_evidence)? @@ -87,9 +87,10 @@ impl TryFrom for Block { impl From for RawBlock { fn from(value: Block) -> Self { + use tendermint_proto::types::Data as RawData; RawBlock { header: Some(value.header.into()), - data: Some(value.data.into()), + data: Some(RawData { txs: value.data }), evidence: Some(value.evidence.into()), last_commit: value.last_commit.map(Into::into), } @@ -100,7 +101,7 @@ impl Block { /// constructor pub fn new( header: Header, - data: transaction::Data, + data: Vec>, evidence: evidence::Data, last_commit: Option, ) -> Result { @@ -128,7 +129,7 @@ impl Block { } /// Get data - pub fn data(&self) -> &transaction::Data { + pub fn data(&self) -> &Vec> { &self.data } From ecc309ddacf2a00850be374da453be794a4c61ce Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Thu, 9 Sep 2021 16:27:58 -0700 Subject: [PATCH 14/20] rpc: take over tendermint::abci The existing contents of the `tendermint::abci` module note that they're only for the purpose of implementing the RPC endpoints, not a general ABCI implementation. Moving that code from the `tendermint` crate to the `tendermint-rpc` crate decouples the RPC interface from improvements to the ABCI domain modeling. Eventually, it would be good to eliminate this code and align it with the new ABCI domain types. --- light-client/src/evidence.rs | 2 +- light-client/src/tests.rs | 2 +- rpc/Cargo.toml | 1 + rpc/src/abci.rs | 34 +++++++++++++ {tendermint => rpc}/src/abci/code.rs | 0 {tendermint => rpc}/src/abci/data.rs | 2 +- {tendermint => rpc}/src/abci/gas.rs | 2 +- {tendermint => rpc}/src/abci/info.rs | 0 {tendermint => rpc}/src/abci/log.rs | 0 {tendermint => rpc}/src/abci/path.rs | 2 +- {tendermint => rpc}/src/abci/responses.rs | 2 +- {tendermint => rpc}/src/abci/tag.rs | 2 +- {tendermint => rpc}/src/abci/transaction.rs | 0 .../src/abci/transaction/hash.rs | 2 +- rpc/src/client.rs | 2 +- rpc/src/client/bin/main.rs | 3 +- rpc/src/endpoint/abci_query.rs | 2 +- rpc/src/endpoint/block_results.rs | 3 +- rpc/src/endpoint/broadcast/tx_async.rs | 2 +- rpc/src/endpoint/broadcast/tx_commit.rs | 8 ++-- rpc/src/endpoint/broadcast/tx_sync.rs | 2 +- rpc/src/endpoint/evidence.rs | 3 +- rpc/src/endpoint/tx.rs | 5 +- rpc/src/event.rs | 4 +- rpc/src/lib.rs | 2 + rpc/src/serializers.rs | 1 + .../src/serializers/hash_base64.rs | 0 rpc/tests/kvstore_fixtures.rs | 48 +++++++++---------- rpc/tests/parse_response.rs | 2 +- tendermint/src/abci.rs | 29 ----------- tendermint/src/lib.rs | 1 - tendermint/src/serializers.rs | 1 - 32 files changed, 88 insertions(+), 81 deletions(-) create mode 100644 rpc/src/abci.rs rename {tendermint => rpc}/src/abci/code.rs (100%) rename {tendermint => rpc}/src/abci/data.rs (94%) rename {tendermint => rpc}/src/abci/gas.rs (98%) rename {tendermint => rpc}/src/abci/info.rs (100%) rename {tendermint => rpc}/src/abci/log.rs (100%) rename {tendermint => rpc}/src/abci/path.rs (94%) rename {tendermint => rpc}/src/abci/responses.rs (98%) rename {tendermint => rpc}/src/abci/tag.rs (98%) rename {tendermint => rpc}/src/abci/transaction.rs (100%) rename {tendermint => rpc}/src/abci/transaction/hash.rs (98%) create mode 100644 rpc/src/serializers.rs rename {tendermint => rpc}/src/serializers/hash_base64.rs (100%) delete mode 100644 tendermint/src/abci.rs diff --git a/light-client/src/evidence.rs b/light-client/src/evidence.rs index 279fb9501..3da3538d1 100644 --- a/light-client/src/evidence.rs +++ b/light-client/src/evidence.rs @@ -2,7 +2,7 @@ use crate::{components::io::IoError, types::PeerId}; -use tendermint::abci::transaction::Hash; +use tendermint_rpc::abci::transaction::Hash; use contracts::contract_trait; diff --git a/light-client/src/tests.rs b/light-client/src/tests.rs index 660c09a8b..093d4fa79 100644 --- a/light-client/src/tests.rs +++ b/light-client/src/tests.rs @@ -3,8 +3,8 @@ use crate::types::{Height, LightBlock, PeerId, SignedHeader, Time, TrustThreshold, ValidatorSet}; use serde::{Deserialize, Serialize}; -use tendermint::abci::transaction::Hash; use tendermint_rpc as rpc; +use tendermint_rpc::abci::transaction::Hash; use crate::components::clock::Clock; use crate::components::io::{AtHeight, Io, IoError}; diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index d97e62813..753b983ce 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -78,6 +78,7 @@ subtle-encoding = { version = "0.5", default-features = false, features = ["bech url = { version = "2.2", default-features = false } walkdir = { version = "2.3", default-features = false } flex-error = { version = "0.4.4", default-features = false } +subtle = { version = "2", default-features = false } # Optional dependencies async-trait = { version = "0.1", optional = true, default-features = false } diff --git a/rpc/src/abci.rs b/rpc/src/abci.rs new file mode 100644 index 000000000..2cbb63df4 --- /dev/null +++ b/rpc/src/abci.rs @@ -0,0 +1,34 @@ +//! Old ABCI structures, formerly defined in `tendermint::abci`. +//! +//! The original contents of `tendermint::abci` were created only to model RPC +//! responses, not to model ABCI itself: +//! +//! > NOTE: This module contains types for ABCI responses as consumed from RPC +//! endpoints. It does not contain an ABCI protocol implementation. +//! +//! The old types should be eliminated and +//! merged with the new ABCI domain types. Moving them here in the meantime +//! disentangles improving the ABCI domain modeling from changes to the RPC +//! interface. + +mod code; +mod data; +mod gas; +mod info; +mod log; +mod path; + +pub mod responses; +pub mod tag; +pub mod transaction; + +pub use self::{ + code::Code, + data::Data, + gas::Gas, + info::Info, + log::Log, + path::Path, + responses::{DeliverTx, Event, Responses}, + transaction::Transaction, +}; diff --git a/tendermint/src/abci/code.rs b/rpc/src/abci/code.rs similarity index 100% rename from tendermint/src/abci/code.rs rename to rpc/src/abci/code.rs diff --git a/tendermint/src/abci/data.rs b/rpc/src/abci/data.rs similarity index 94% rename from tendermint/src/abci/data.rs rename to rpc/src/abci/data.rs index 5fc93f00f..a2c47bf32 100644 --- a/tendermint/src/abci/data.rs +++ b/rpc/src/abci/data.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; /// application-specific rules. #[derive(Clone, Debug, Eq, PartialEq, Default, Serialize, Deserialize)] #[serde(transparent)] -pub struct Data(#[serde(with = "crate::serializers::bytes::base64string")] Vec); +pub struct Data(#[serde(with = "tendermint::serializers::bytes::base64string")] Vec); impl From> for Data { fn from(value: Vec) -> Self { diff --git a/tendermint/src/abci/gas.rs b/rpc/src/abci/gas.rs similarity index 98% rename from tendermint/src/abci/gas.rs rename to rpc/src/abci/gas.rs index af7721d27..d6fe98e9d 100644 --- a/tendermint/src/abci/gas.rs +++ b/rpc/src/abci/gas.rs @@ -5,13 +5,13 @@ //! //! -use crate::error::Error; use crate::prelude::*; use core::{ fmt::{self, Display}, str::FromStr, }; use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer}; +use tendermint::error::Error; /// Gas: representation of transaction processing resource costs #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)] diff --git a/tendermint/src/abci/info.rs b/rpc/src/abci/info.rs similarity index 100% rename from tendermint/src/abci/info.rs rename to rpc/src/abci/info.rs diff --git a/tendermint/src/abci/log.rs b/rpc/src/abci/log.rs similarity index 100% rename from tendermint/src/abci/log.rs rename to rpc/src/abci/log.rs diff --git a/tendermint/src/abci/path.rs b/rpc/src/abci/path.rs similarity index 94% rename from tendermint/src/abci/path.rs rename to rpc/src/abci/path.rs index a49eabc3b..b5b3c8ff2 100644 --- a/tendermint/src/abci/path.rs +++ b/rpc/src/abci/path.rs @@ -1,12 +1,12 @@ //! Paths to ABCI data -use crate::error::Error; use crate::prelude::*; use core::{ fmt::{self, Display}, str::FromStr, }; use serde::{Deserialize, Serialize}; +use tendermint::error::Error; /// Path to ABCI data #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] diff --git a/tendermint/src/abci/responses.rs b/rpc/src/abci/responses.rs similarity index 98% rename from tendermint/src/abci/responses.rs rename to rpc/src/abci/responses.rs index 4a112fcfa..614e1f447 100644 --- a/tendermint/src/abci/responses.rs +++ b/rpc/src/abci/responses.rs @@ -2,9 +2,9 @@ use super::{code::Code, data::Data, gas::Gas, info::Info, log::Log, tag::Tag}; use crate::prelude::*; -use crate::{consensus, serializers, validator}; use core::fmt::{self, Display}; use serde::{Deserialize, Deserializer, Serialize}; +use tendermint::{consensus, serializers, validator}; /// Responses for ABCI calls which occur during block processing. /// diff --git a/tendermint/src/abci/tag.rs b/rpc/src/abci/tag.rs similarity index 98% rename from tendermint/src/abci/tag.rs rename to rpc/src/abci/tag.rs index 50601c5dd..8136af43e 100644 --- a/tendermint/src/abci/tag.rs +++ b/rpc/src/abci/tag.rs @@ -1,9 +1,9 @@ //! Tags -use crate::error::Error; use crate::prelude::*; use core::{fmt, str::FromStr}; use serde::{Deserialize, Serialize}; +use tendermint::error::Error; use tendermint_proto::serializers::bytes::base64string; /// Tags diff --git a/tendermint/src/abci/transaction.rs b/rpc/src/abci/transaction.rs similarity index 100% rename from tendermint/src/abci/transaction.rs rename to rpc/src/abci/transaction.rs diff --git a/tendermint/src/abci/transaction/hash.rs b/rpc/src/abci/transaction/hash.rs similarity index 98% rename from tendermint/src/abci/transaction/hash.rs rename to rpc/src/abci/transaction/hash.rs index b9b00136f..5e0c47c2d 100644 --- a/tendermint/src/abci/transaction/hash.rs +++ b/rpc/src/abci/transaction/hash.rs @@ -1,6 +1,5 @@ //! Transaction hashes -use crate::error::Error; use crate::prelude::*; use core::{ fmt::{self, Debug, Display}, @@ -9,6 +8,7 @@ use core::{ use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use subtle::{self, ConstantTimeEq}; use subtle_encoding::hex; +use tendermint::error::Error; /// Size of a transaction hash in bytes pub const LENGTH: usize = 32; diff --git a/rpc/src/client.rs b/rpc/src/client.rs index a1ce9ad3a..150bf42a3 100644 --- a/rpc/src/client.rs +++ b/rpc/src/client.rs @@ -14,6 +14,7 @@ pub use transport::websocket::{ WebSocketClient, WebSocketClientDriver, WebSocketClientUrl, WebSocketConfig, }; +use crate::abci::{self, Transaction}; use crate::endpoint::validators::DEFAULT_VALIDATORS_PER_PAGE; use crate::endpoint::*; use crate::paging::Paging; @@ -22,7 +23,6 @@ use crate::query::Query; use crate::{Error, Order, SimpleRequest}; use async_trait::async_trait; use core::time::Duration; -use tendermint::abci::{self, Transaction}; use tendermint::block::Height; use tendermint::evidence::Evidence; use tendermint::Genesis; diff --git a/rpc/src/client/bin/main.rs b/rpc/src/client/bin/main.rs index eab7664f0..b6f559a15 100644 --- a/rpc/src/client/bin/main.rs +++ b/rpc/src/client/bin/main.rs @@ -3,8 +3,7 @@ use core::str::FromStr; use futures::StreamExt; use structopt::StructOpt; -use tendermint::abci::transaction::Hash; -use tendermint::abci::{Path, Transaction}; +use tendermint_rpc::abci::{transaction::Hash, Path, Transaction}; use tendermint_rpc::query::Query; use tendermint_rpc::{ Client, Error, HttpClient, Order, Paging, Scheme, Subscription, SubscriptionClient, Url, diff --git a/rpc/src/endpoint/abci_query.rs b/rpc/src/endpoint/abci_query.rs index c4dacc5fc..cd4841895 100644 --- a/rpc/src/endpoint/abci_query.rs +++ b/rpc/src/endpoint/abci_query.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; -use tendermint::abci::{Code, Log, Path}; +use crate::abci::{Code, Log, Path}; use tendermint::block; use tendermint::merkle::proof::Proof; use tendermint::serializers; diff --git a/rpc/src/endpoint/block_results.rs b/rpc/src/endpoint/block_results.rs index 0f2c8fcb6..8bf8df1f3 100644 --- a/rpc/src/endpoint/block_results.rs +++ b/rpc/src/endpoint/block_results.rs @@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize}; -use tendermint::{abci, block, consensus, validator}; +use crate::abci; +use tendermint::{block, consensus, validator}; use crate::prelude::*; diff --git a/rpc/src/endpoint/broadcast/tx_async.rs b/rpc/src/endpoint/broadcast/tx_async.rs index 2cd5bd8ae..0de93113e 100644 --- a/rpc/src/endpoint/broadcast/tx_async.rs +++ b/rpc/src/endpoint/broadcast/tx_async.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; -use tendermint::abci::{transaction, Code, Data, Log, Transaction}; +use crate::abci::{transaction, Code, Data, Log, Transaction}; /// `/broadcast_tx_async`: broadcast a transaction and return immediately. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] diff --git a/rpc/src/endpoint/broadcast/tx_commit.rs b/rpc/src/endpoint/broadcast/tx_commit.rs index bb4cf93a5..4e0a60bfb 100644 --- a/rpc/src/endpoint/broadcast/tx_commit.rs +++ b/rpc/src/endpoint/broadcast/tx_commit.rs @@ -3,12 +3,10 @@ use serde::{Deserialize, Serialize}; -use tendermint::abci::responses::Codespace; -use tendermint::abci::{Event, Gas, Info}; -use tendermint::{ - abci::{transaction, Code, Data, Log, Transaction}, - block, +use crate::abci::{ + responses::Codespace, transaction, Code, Data, Event, Gas, Info, Log, Transaction, }; +use tendermint::block; use crate::prelude::*; diff --git a/rpc/src/endpoint/broadcast/tx_sync.rs b/rpc/src/endpoint/broadcast/tx_sync.rs index 706d9d125..e188525a4 100644 --- a/rpc/src/endpoint/broadcast/tx_sync.rs +++ b/rpc/src/endpoint/broadcast/tx_sync.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; -use tendermint::abci::{transaction, Code, Data, Log, Transaction}; +use crate::abci::{transaction, Code, Data, Log, Transaction}; /// `/broadcast_tx_sync`: returns with the response from `CheckTx`. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] diff --git a/rpc/src/endpoint/evidence.rs b/rpc/src/endpoint/evidence.rs index 98bcb3158..c9e387b81 100644 --- a/rpc/src/endpoint/evidence.rs +++ b/rpc/src/endpoint/evidence.rs @@ -2,8 +2,9 @@ use crate::Method; +use crate::abci::transaction; use serde::{Deserialize, Serialize}; -use tendermint::{abci::transaction, evidence::Evidence}; +use tendermint::evidence::Evidence; /// `/broadcast_evidence`: broadcast an evidence. #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] diff --git a/rpc/src/endpoint/tx.rs b/rpc/src/endpoint/tx.rs index e3de3ebb5..dfdec475b 100644 --- a/rpc/src/endpoint/tx.rs +++ b/rpc/src/endpoint/tx.rs @@ -1,8 +1,9 @@ //! `/tx` endpoint JSON-RPC wrapper +use crate::abci; use crate::Method; use serde::{Deserialize, Serialize}; -use tendermint::{abci, block}; +use tendermint::block; use tendermint_proto::types::TxProof; /// Request for finding a transaction by its hash. @@ -12,7 +13,7 @@ pub struct Request { /// /// Serialized internally into a base64-encoded string before sending to /// the RPC server. - #[serde(with = "tendermint::serializers::hash_base64")] + #[serde(with = "crate::serializers::hash_base64")] pub hash: abci::transaction::Hash, /// Whether or not to include the proofs of the transaction's inclusion in /// the block. diff --git a/rpc/src/event.rs b/rpc/src/event.rs index cae0c62fd..0c6757bc8 100644 --- a/rpc/src/event.rs +++ b/rpc/src/event.rs @@ -1,8 +1,8 @@ //! RPC subscription event-related data structures. +use crate::abci::responses::{BeginBlock, EndBlock}; use alloc::collections::BTreeMap as HashMap; use serde::{Deserialize, Serialize}; -use tendermint::abci::responses::{BeginBlock, EndBlock}; use tendermint::Block; use crate::prelude::*; @@ -73,5 +73,5 @@ pub struct TxResult { pub log: Option, pub gas_wanted: Option, pub gas_used: Option, - pub events: Vec, + pub events: Vec, } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 9ab6b672f..be7c381a5 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -45,6 +45,7 @@ pub use client::{HttpClient, HttpClientUrl}; #[cfg(feature = "websocket-client")] pub use client::{WebSocketClient, WebSocketClientDriver, WebSocketClientUrl, WebSocketConfig}; +pub mod abci; pub mod endpoint; pub mod error; pub mod event; @@ -57,6 +58,7 @@ pub mod request; pub mod response; pub mod response_error; mod rpc_url; +mod serializers; mod utils; mod version; diff --git a/rpc/src/serializers.rs b/rpc/src/serializers.rs new file mode 100644 index 000000000..b31d8207e --- /dev/null +++ b/rpc/src/serializers.rs @@ -0,0 +1 @@ +pub mod hash_base64; diff --git a/tendermint/src/serializers/hash_base64.rs b/rpc/src/serializers/hash_base64.rs similarity index 100% rename from tendermint/src/serializers/hash_base64.rs rename to rpc/src/serializers/hash_base64.rs diff --git a/rpc/tests/kvstore_fixtures.rs b/rpc/tests/kvstore_fixtures.rs index 5fd578059..5cacb19eb 100644 --- a/rpc/tests/kvstore_fixtures.rs +++ b/rpc/tests/kvstore_fixtures.rs @@ -3,10 +3,10 @@ use core::str::FromStr; use std::{fs, path::PathBuf}; use subtle_encoding::{base64, hex}; -use tendermint::abci::transaction::Hash; use tendermint::evidence::Duration; use tendermint::public_key; use tendermint_config::net::Address; +use tendermint_rpc::abci::transaction::Hash; use tendermint_rpc::{ endpoint, error::{Error, ErrorDetail}, @@ -550,21 +550,21 @@ fn incoming_fixtures() { } "broadcast_tx_async" => { let result = endpoint::broadcast::tx_async::Response::from_string(content).unwrap(); - assert_eq!(result.code, tendermint::abci::Code::Ok); + assert_eq!(result.code, tendermint_rpc::abci::Code::Ok); assert!(result.data.value().is_empty()); assert_ne!( result.hash, - tendermint::abci::transaction::Hash::new([0; 32]) + tendermint_rpc::abci::transaction::Hash::new([0; 32]) ); assert!(result.log.value().is_empty()); } "broadcast_tx_commit" => { let result = endpoint::broadcast::tx_commit::Response::from_string(content).unwrap(); - assert_eq!(result.check_tx.code, tendermint::abci::Code::Ok); + assert_eq!(result.check_tx.code, tendermint_rpc::abci::Code::Ok); assert_eq!( result.check_tx.codespace, - tendermint::abci::responses::Codespace::default() + tendermint_rpc::abci::responses::Codespace::default() ); assert!(result.check_tx.data.is_none()); assert!(result.check_tx.events.is_empty()); @@ -573,10 +573,10 @@ fn incoming_fixtures() { //assert_eq!(result.check_tx.gas_wanted.value(), 1); assert!(result.check_tx.info.to_string().is_empty()); assert!(result.check_tx.log.value().is_empty()); - assert_eq!(result.deliver_tx.code, tendermint::abci::Code::Ok); + assert_eq!(result.deliver_tx.code, tendermint_rpc::abci::Code::Ok); assert_eq!( result.deliver_tx.codespace, - tendermint::abci::responses::Codespace::default() + tendermint_rpc::abci::responses::Codespace::default() ); assert!(result.deliver_tx.data.is_none()); assert_eq!(result.deliver_tx.events.len(), 1); @@ -644,16 +644,16 @@ fn incoming_fixtures() { assert!(result.deliver_tx.log.value().is_empty()); assert_ne!( result.hash, - tendermint::abci::transaction::Hash::new([0; 32]) + tendermint_rpc::abci::transaction::Hash::new([0; 32]) ); } "broadcast_tx_sync" => { let result = endpoint::broadcast::tx_sync::Response::from_string(content).unwrap(); - assert_eq!(result.code, tendermint::abci::Code::Ok); + assert_eq!(result.code, tendermint_rpc::abci::Code::Ok); assert!(result.data.value().is_empty()); assert_ne!( result.hash, - tendermint::abci::transaction::Hash::new([0; 32]) + tendermint_rpc::abci::transaction::Hash::new([0; 32]) ); assert!(result.log.value().is_empty()); } @@ -1353,61 +1353,61 @@ fn incoming_fixtures() { } "subscribe_txs_broadcast_tx_0" => { let result = endpoint::broadcast::tx_async::Response::from_string(content).unwrap(); - assert_eq!(result.code, tendermint::abci::Code::Ok); + assert_eq!(result.code, tendermint_rpc::abci::Code::Ok); assert!(result.data.value().is_empty()); assert_ne!( result.hash, - tendermint::abci::transaction::Hash::new([0; 32]) + tendermint_rpc::abci::transaction::Hash::new([0; 32]) ); assert!(result.log.value().is_empty()); } "subscribe_txs_broadcast_tx_1" => { let result = endpoint::broadcast::tx_async::Response::from_string(content).unwrap(); - assert_eq!(result.code, tendermint::abci::Code::Ok); + assert_eq!(result.code, tendermint_rpc::abci::Code::Ok); assert!(result.data.value().is_empty()); assert_ne!( result.hash, - tendermint::abci::transaction::Hash::new([0; 32]) + tendermint_rpc::abci::transaction::Hash::new([0; 32]) ); assert!(result.log.value().is_empty()); } "subscribe_txs_broadcast_tx_2" => { let result = endpoint::broadcast::tx_async::Response::from_string(content).unwrap(); - assert_eq!(result.code, tendermint::abci::Code::Ok); + assert_eq!(result.code, tendermint_rpc::abci::Code::Ok); assert!(result.data.value().is_empty()); assert_ne!( result.hash, - tendermint::abci::transaction::Hash::new([0; 32]) + tendermint_rpc::abci::transaction::Hash::new([0; 32]) ); assert!(result.log.value().is_empty()); } "subscribe_txs_broadcast_tx_3" => { let result = endpoint::broadcast::tx_async::Response::from_string(content).unwrap(); - assert_eq!(result.code, tendermint::abci::Code::Ok); + assert_eq!(result.code, tendermint_rpc::abci::Code::Ok); assert!(result.data.value().is_empty()); assert_ne!( result.hash, - tendermint::abci::transaction::Hash::new([0; 32]) + tendermint_rpc::abci::transaction::Hash::new([0; 32]) ); assert!(result.log.value().is_empty()); } "subscribe_txs_broadcast_tx_4" => { let result = endpoint::broadcast::tx_async::Response::from_string(content).unwrap(); - assert_eq!(result.code, tendermint::abci::Code::Ok); + assert_eq!(result.code, tendermint_rpc::abci::Code::Ok); assert!(result.data.value().is_empty()); assert_ne!( result.hash, - tendermint::abci::transaction::Hash::new([0; 32]) + tendermint_rpc::abci::transaction::Hash::new([0; 32]) ); assert!(result.log.value().is_empty()); } "subscribe_txs_broadcast_tx_5" => { let result = endpoint::broadcast::tx_async::Response::from_string(content).unwrap(); - assert_eq!(result.code, tendermint::abci::Code::Ok); + assert_eq!(result.code, tendermint_rpc::abci::Code::Ok); assert!(result.data.value().is_empty()); assert_ne!( result.hash, - tendermint::abci::transaction::Hash::new([0; 32]) + tendermint_rpc::abci::transaction::Hash::new([0; 32]) ); assert!(result.log.value().is_empty()); } @@ -1428,7 +1428,7 @@ fn incoming_fixtures() { // Test a few selected attributes of the results. for tx in result.txs { assert_ne!(tx.hash.as_bytes(), [0; 32]); - assert_eq!(tx.tx_result.code, tendermint::abci::Code::Ok); + assert_eq!(tx.tx_result.code, tendermint_rpc::abci::Code::Ok); assert_eq!(tx.tx_result.events.len(), 1); assert_eq!(tx.tx_result.events[0].type_str, "app"); assert_eq!(tx.tx_result.gas_used.value(), 0); @@ -1444,7 +1444,7 @@ fn incoming_fixtures() { // Test a few selected attributes of the results. for tx in result.txs { assert_ne!(tx.hash.as_bytes(), [0; 32]); - assert_eq!(tx.tx_result.code, tendermint::abci::Code::Ok); + assert_eq!(tx.tx_result.code, tendermint_rpc::abci::Code::Ok); assert_eq!(tx.tx_result.events.len(), 1); assert_eq!(tx.tx_result.events[0].type_str, "app"); assert_eq!(tx.tx_result.gas_used.value(), 0); diff --git a/rpc/tests/parse_response.rs b/rpc/tests/parse_response.rs index 6acc0c345..cd5ee2cad 100644 --- a/rpc/tests/parse_response.rs +++ b/rpc/tests/parse_response.rs @@ -1,7 +1,7 @@ //! Tendermint RPC endpoint testing. use std::{fs, path::PathBuf}; -use tendermint::abci::Code; +use tendermint_rpc::abci::Code; use core::str::FromStr; use tendermint::vote; diff --git a/tendermint/src/abci.rs b/tendermint/src/abci.rs deleted file mode 100644 index 9a0f84761..000000000 --- a/tendermint/src/abci.rs +++ /dev/null @@ -1,29 +0,0 @@ -//! Application BlockChain Interface (ABCI) -//! -//! NOTE: This module contains types for ABCI responses as consumed from RPC -//! endpoints. It does not contain an ABCI protocol implementation. -//! -//! For that, see: -//! -//! - -mod code; -mod data; -mod gas; -mod info; -mod log; -mod path; -pub mod responses; -pub mod tag; -pub mod transaction; - -pub use self::{ - code::Code, - data::Data, - gas::Gas, - info::Info, - log::Log, - path::Path, - responses::{DeliverTx, Event, Responses}, - transaction::Transaction, -}; diff --git a/tendermint/src/lib.rs b/tendermint/src/lib.rs index 345a3a6eb..eef95f4e0 100644 --- a/tendermint/src/lib.rs +++ b/tendermint/src/lib.rs @@ -27,7 +27,6 @@ extern crate std; #[macro_use] pub mod error; -pub mod abci; pub mod account; pub mod block; pub mod chain; diff --git a/tendermint/src/serializers.rs b/tendermint/src/serializers.rs index 697ceaa1c..8a0efc8b9 100644 --- a/tendermint/src/serializers.rs +++ b/tendermint/src/serializers.rs @@ -9,6 +9,5 @@ pub use tendermint_proto::serializers::*; pub mod apphash; pub mod hash; -pub mod hash_base64; pub mod option_hash; pub mod time; From 28682cd339f23576082b38ed299ba43d4cf3bfb5 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 13 Apr 2021 15:35:51 -0700 Subject: [PATCH 15/20] tendermint: add ABCI domain types. These types mirror the generated types in tendermint_proto, but have better naming. The documentation for each request type is adapted from the ABCI Methods and Types spec document. However, the same logical request may appear three times, as a struct with the request data, as a Request variant, and as a CategoryRequest variant. To avoid duplication, this PR uses the `#[doc = include_str!(...)]` functionality stabilized in Rust 1.54 to keep common definitions of the documentation. --- tendermint/src/abci.rs | 54 ++++ .../abci/doc/request-applysnapshotchunk.md | 21 ++ tendermint/src/abci/doc/request-beginblock.md | 6 + tendermint/src/abci/doc/request-checktx.md | 11 + tendermint/src/abci/doc/request-commit.md | 4 + tendermint/src/abci/doc/request-delivertx.md | 3 + tendermint/src/abci/doc/request-echo.md | 3 + tendermint/src/abci/doc/request-endblock.md | 5 + tendermint/src/abci/doc/request-flush.md | 3 + tendermint/src/abci/doc/request-info.md | 3 + tendermint/src/abci/doc/request-initchain.md | 3 + .../src/abci/doc/request-listsnapshots.md | 3 + .../src/abci/doc/request-loadsnapshotchunk.md | 3 + .../src/abci/doc/request-offersnapshot.md | 20 ++ tendermint/src/abci/doc/request-query.md | 3 + .../abci/doc/response-applysnapshotchunk.md | 7 + .../src/abci/doc/response-beginblock.md | 3 + tendermint/src/abci/doc/response-checktx.md | 3 + tendermint/src/abci/doc/response-commit.md | 3 + tendermint/src/abci/doc/response-delivertx.md | 4 + tendermint/src/abci/doc/response-echo.md | 3 + tendermint/src/abci/doc/response-endblock.md | 3 + tendermint/src/abci/doc/response-exception.md | 1 + tendermint/src/abci/doc/response-flush.md | 3 + tendermint/src/abci/doc/response-info.md | 3 + tendermint/src/abci/doc/response-initchain.md | 3 + .../src/abci/doc/response-listsnapshots.md | 3 + .../abci/doc/response-loadsnapshotchunk.md | 3 + .../src/abci/doc/response-offersnapshot.md | 7 + tendermint/src/abci/doc/response-query.md | 3 + tendermint/src/abci/event.rs | 186 +++++++++++ tendermint/src/abci/kind.rs | 23 ++ tendermint/src/abci/params.rs | 219 +++++++++++++ tendermint/src/abci/request.rs | 306 ++++++++++++++++++ .../src/abci/request/apply_snapshot_chunk.rs | 73 +++++ tendermint/src/abci/request/begin_block.rs | 77 +++++ tendermint/src/abci/request/check_tx.rs | 74 +++++ tendermint/src/abci/request/deliver_tx.rs | 37 +++ tendermint/src/abci/request/echo.rs | 39 +++ tendermint/src/abci/request/end_block.rs | 39 +++ tendermint/src/abci/request/info.rs | 51 +++ tendermint/src/abci/request/init_chain.rs | 73 +++++ .../src/abci/request/load_snapshot_chunk.rs | 47 +++ tendermint/src/abci/request/offer_snapshot.rs | 55 ++++ tendermint/src/abci/request/query.rs | 66 ++++ tendermint/src/abci/response.rs | 291 +++++++++++++++++ .../src/abci/response/apply_snapshot_chunk.rs | 91 ++++++ tendermint/src/abci/response/begin_block.rs | 46 +++ tendermint/src/abci/response/check_tx.rs | 95 ++++++ tendermint/src/abci/response/commit.rs | 48 +++ tendermint/src/abci/response/deliver_tx.rs | 83 +++++ tendermint/src/abci/response/echo.rs | 39 +++ tendermint/src/abci/response/end_block.rs | 66 ++++ tendermint/src/abci/response/exception.rs | 39 +++ tendermint/src/abci/response/info.rs | 58 ++++ tendermint/src/abci/response/init_chain.rs | 65 ++++ .../src/abci/response/list_snapshots.rs | 49 +++ .../src/abci/response/load_snapshot_chunk.rs | 44 +++ .../src/abci/response/offer_snapshot.rs | 66 ++++ tendermint/src/abci/response/query.rs | 85 +++++ tendermint/src/abci/types.rs | 306 ++++++++++++++++++ tendermint/src/lib.rs | 1 + 62 files changed, 3034 insertions(+) create mode 100644 tendermint/src/abci.rs create mode 100644 tendermint/src/abci/doc/request-applysnapshotchunk.md create mode 100644 tendermint/src/abci/doc/request-beginblock.md create mode 100644 tendermint/src/abci/doc/request-checktx.md create mode 100644 tendermint/src/abci/doc/request-commit.md create mode 100644 tendermint/src/abci/doc/request-delivertx.md create mode 100644 tendermint/src/abci/doc/request-echo.md create mode 100644 tendermint/src/abci/doc/request-endblock.md create mode 100644 tendermint/src/abci/doc/request-flush.md create mode 100644 tendermint/src/abci/doc/request-info.md create mode 100644 tendermint/src/abci/doc/request-initchain.md create mode 100644 tendermint/src/abci/doc/request-listsnapshots.md create mode 100644 tendermint/src/abci/doc/request-loadsnapshotchunk.md create mode 100644 tendermint/src/abci/doc/request-offersnapshot.md create mode 100644 tendermint/src/abci/doc/request-query.md create mode 100644 tendermint/src/abci/doc/response-applysnapshotchunk.md create mode 100644 tendermint/src/abci/doc/response-beginblock.md create mode 100644 tendermint/src/abci/doc/response-checktx.md create mode 100644 tendermint/src/abci/doc/response-commit.md create mode 100644 tendermint/src/abci/doc/response-delivertx.md create mode 100644 tendermint/src/abci/doc/response-echo.md create mode 100644 tendermint/src/abci/doc/response-endblock.md create mode 100644 tendermint/src/abci/doc/response-exception.md create mode 100644 tendermint/src/abci/doc/response-flush.md create mode 100644 tendermint/src/abci/doc/response-info.md create mode 100644 tendermint/src/abci/doc/response-initchain.md create mode 100644 tendermint/src/abci/doc/response-listsnapshots.md create mode 100644 tendermint/src/abci/doc/response-loadsnapshotchunk.md create mode 100644 tendermint/src/abci/doc/response-offersnapshot.md create mode 100644 tendermint/src/abci/doc/response-query.md create mode 100644 tendermint/src/abci/event.rs create mode 100644 tendermint/src/abci/kind.rs create mode 100644 tendermint/src/abci/params.rs create mode 100644 tendermint/src/abci/request.rs create mode 100644 tendermint/src/abci/request/apply_snapshot_chunk.rs create mode 100644 tendermint/src/abci/request/begin_block.rs create mode 100644 tendermint/src/abci/request/check_tx.rs create mode 100644 tendermint/src/abci/request/deliver_tx.rs create mode 100644 tendermint/src/abci/request/echo.rs create mode 100644 tendermint/src/abci/request/end_block.rs create mode 100644 tendermint/src/abci/request/info.rs create mode 100644 tendermint/src/abci/request/init_chain.rs create mode 100644 tendermint/src/abci/request/load_snapshot_chunk.rs create mode 100644 tendermint/src/abci/request/offer_snapshot.rs create mode 100644 tendermint/src/abci/request/query.rs create mode 100644 tendermint/src/abci/response.rs create mode 100644 tendermint/src/abci/response/apply_snapshot_chunk.rs create mode 100644 tendermint/src/abci/response/begin_block.rs create mode 100644 tendermint/src/abci/response/check_tx.rs create mode 100644 tendermint/src/abci/response/commit.rs create mode 100644 tendermint/src/abci/response/deliver_tx.rs create mode 100644 tendermint/src/abci/response/echo.rs create mode 100644 tendermint/src/abci/response/end_block.rs create mode 100644 tendermint/src/abci/response/exception.rs create mode 100644 tendermint/src/abci/response/info.rs create mode 100644 tendermint/src/abci/response/init_chain.rs create mode 100644 tendermint/src/abci/response/list_snapshots.rs create mode 100644 tendermint/src/abci/response/load_snapshot_chunk.rs create mode 100644 tendermint/src/abci/response/offer_snapshot.rs create mode 100644 tendermint/src/abci/response/query.rs create mode 100644 tendermint/src/abci/types.rs diff --git a/tendermint/src/abci.rs b/tendermint/src/abci.rs new file mode 100644 index 000000000..c026016ed --- /dev/null +++ b/tendermint/src/abci.rs @@ -0,0 +1,54 @@ +//! Application BlockChain Interface ([ABCI]) is the interface between Tendermint +//! (a consensus engine for Byzantine-fault-tolerant replication of a state +//! machine) and an application (the state machine to be replicated). +//! +//! Using ABCI involves writing an application driven by ABCI methods, exposing +//! that application as an ABCI server, and having Tendermint connect to the +//! server as an ABCI client. +//! +//! This module does not include an ABCI server implementation itself. Instead, +//! it provides a common set of Rust domain types that model the ABCI protocol, +//! which can be used by both ABCI applications and ABCI server implementations. +//! +//! One ABCI server implementation is provided by the [`tendermint_abci`][tmabci] +//! crate. +//! +//! Each ABCI method corresponds to a request/response pair. ABCI requests are +//! modeled by the [`Request`] enum, and responses are modeled by the +//! [`Response`] enum. As described in the [methods and types][mat] page, ABCI +//! methods are split into four categories. Tendermint opens one ABCI connection +//! for each category of messages. These categories are modeled by the +//! [`MethodKind`] enum and by per-category request and response enums: +//! +//! * [`ConsensusRequest`] / [`ConsensusResponse`] for [`MethodKind::Consensus`] methods; +//! * [`MempoolRequest`] / [`MempoolResponse`] for [`MethodKind::Mempool`] methods; +//! * [`InfoRequest`] / [`InfoResponse`] for [`MethodKind::Info`] methods; +//! * [`SnapshotRequest`] / [`SnapshotResponse`] for [`MethodKind::Snapshot`] methods. +//! +//! The domain types in this module have conversions to and from the Protobuf +//! types defined in the [`tendermint_proto`] crate. These conversions are +//! required for ABCI server implementations, which use the protobufs to +//! communicate with Tendermint, but should not be required for ABCI +//! applications, which should use the domain types in an interface defined by +//! their choice of ABCI server implementation. +//! +//! [ABCI]: https://docs.tendermint.com/master/spec/abci/ +//! [mat]: https://docs.tendermint.com/master/spec/abci/abci.html +//! [tmabci]: https://github.com/informalsystems/tendermint-rs/tree/master/abci + +mod event; +mod kind; + +pub mod params; +pub mod request; +pub mod response; +pub mod types; + +pub use event::{Event, EventAttribute, EventAttributeIndexExt}; + +#[doc(inline)] +pub use self::{ + kind::MethodKind, + request::{ConsensusRequest, InfoRequest, MempoolRequest, Request, SnapshotRequest}, + response::{ConsensusResponse, InfoResponse, MempoolResponse, Response, SnapshotResponse}, +}; diff --git a/tendermint/src/abci/doc/request-applysnapshotchunk.md b/tendermint/src/abci/doc/request-applysnapshotchunk.md new file mode 100644 index 000000000..fe1c35598 --- /dev/null +++ b/tendermint/src/abci/doc/request-applysnapshotchunk.md @@ -0,0 +1,21 @@ +Applies a snapshot chunk. + +The application can choose to refetch chunks and/or ban P2P peers as +appropriate. Tendermint will not do this unless instructed by the +application. + +The application may want to verify each chunk, e.g., by attaching chunk +hashes in [`Snapshot::metadata`] and/or incrementally verifying contents +against `app_hash`. + +When all chunks have been accepted, Tendermint will make an ABCI [`Info`] +request to verify that `last_block_app_hash` and `last_block_height` match +the expected values, and record the `app_version` in the node state. It then +switches to fast sync or consensus and joins the network. + +If Tendermint is unable to retrieve the next chunk after some time (e.g., +because no suitable peers are available), it will reject the snapshot and try +a different one via `OfferSnapshot`. The application should be prepared to +reset and accept it or abort as appropriate. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#applysnapshotchunk) \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-beginblock.md b/tendermint/src/abci/doc/request-beginblock.md new file mode 100644 index 000000000..44b98920a --- /dev/null +++ b/tendermint/src/abci/doc/request-beginblock.md @@ -0,0 +1,6 @@ +Signals the beginning of a new block. + +Called prior to any [`DeliverTx`]s. The `header` contains the height, +timestamp, and more -- it exactly matches the Tendermint block header. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#beginblock) \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-checktx.md b/tendermint/src/abci/doc/request-checktx.md new file mode 100644 index 000000000..7d97a6287 --- /dev/null +++ b/tendermint/src/abci/doc/request-checktx.md @@ -0,0 +1,11 @@ +Check whether a transaction should be included in the mempool. + +`CheckTx` is not involved in processing blocks, only in deciding whether a +transaction should be included in the mempool. Every node runs `CheckTx` +before adding a transaction to its local mempool. The transaction may come +from an external user or another node. `CheckTx` need not execute the +transaction in full, but can instead perform lightweight or statateful +validation (e.g., checking signatures or account balances) instead of more +expensive checks (like running code in a virtual machine). + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#checktx) \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-commit.md b/tendermint/src/abci/doc/request-commit.md new file mode 100644 index 000000000..0013b8302 --- /dev/null +++ b/tendermint/src/abci/doc/request-commit.md @@ -0,0 +1,4 @@ +Signals the application that it can write the queued state transitions +from the block to its state. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#commit) \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-delivertx.md b/tendermint/src/abci/doc/request-delivertx.md new file mode 100644 index 000000000..4d449cc56 --- /dev/null +++ b/tendermint/src/abci/doc/request-delivertx.md @@ -0,0 +1,3 @@ +Execute a transaction against the application state. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#delivertx) \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-echo.md b/tendermint/src/abci/doc/request-echo.md new file mode 100644 index 000000000..92658169f --- /dev/null +++ b/tendermint/src/abci/doc/request-echo.md @@ -0,0 +1,3 @@ +Echoes a string to test an ABCI implementation. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#echo) \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-endblock.md b/tendermint/src/abci/doc/request-endblock.md new file mode 100644 index 000000000..6e23b6d7c --- /dev/null +++ b/tendermint/src/abci/doc/request-endblock.md @@ -0,0 +1,5 @@ +Signals the end of a block. + +Called after all transactions, and prior to each `Commit`. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#endblock) \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-flush.md b/tendermint/src/abci/doc/request-flush.md new file mode 100644 index 000000000..c556d8b2d --- /dev/null +++ b/tendermint/src/abci/doc/request-flush.md @@ -0,0 +1,3 @@ +Indicates that any pending requests should be completed and their responses flushed. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#flush) \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-info.md b/tendermint/src/abci/doc/request-info.md new file mode 100644 index 000000000..471ec36c7 --- /dev/null +++ b/tendermint/src/abci/doc/request-info.md @@ -0,0 +1,3 @@ +Requests information about the application state. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#info) \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-initchain.md b/tendermint/src/abci/doc/request-initchain.md new file mode 100644 index 000000000..49180f351 --- /dev/null +++ b/tendermint/src/abci/doc/request-initchain.md @@ -0,0 +1,3 @@ +Called on genesis to initialize chain state. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#initchain) \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-listsnapshots.md b/tendermint/src/abci/doc/request-listsnapshots.md new file mode 100644 index 000000000..bc89accad --- /dev/null +++ b/tendermint/src/abci/doc/request-listsnapshots.md @@ -0,0 +1,3 @@ +Asks the application for a list of snapshots. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#listsnapshots) \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-loadsnapshotchunk.md b/tendermint/src/abci/doc/request-loadsnapshotchunk.md new file mode 100644 index 000000000..70b686d41 --- /dev/null +++ b/tendermint/src/abci/doc/request-loadsnapshotchunk.md @@ -0,0 +1,3 @@ +Used during state sync to retrieve snapshot chunks from peers. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#loadsnapshotchunk) \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-offersnapshot.md b/tendermint/src/abci/doc/request-offersnapshot.md new file mode 100644 index 000000000..db0e60b17 --- /dev/null +++ b/tendermint/src/abci/doc/request-offersnapshot.md @@ -0,0 +1,20 @@ +Offers a list of snapshots to the application. + +`OfferSnapshot` is called when bootstrapping a node using state sync. The +application may accept or reject snapshots as appropriate. Upon accepting, +Tendermint will retrieve and apply snapshot chunks via +[`ApplySnapshotChunk`]. The application may also choose to reject a snapshot +in the chunk response, in which case it should be prepared to accept further +`OfferSnapshot` calls. + +Only `app_hash` can be trusted, as it has been verified by the light client. +Any other data can be spoofed by adversaries, so applications should employ +additional verification schemes to avoid denial-of-service attacks. The +verified `app_hash` is automatically checked against the restored application +at the end of snapshot restoration. + +See also the [`Snapshot`] data type and the [ABCI state sync documentation][ssd]. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#offersnapshot) + +[ssd]: https://docs.tendermint.com/master/spec/abci/apps.html#state-sync \ No newline at end of file diff --git a/tendermint/src/abci/doc/request-query.md b/tendermint/src/abci/doc/request-query.md new file mode 100644 index 000000000..5d061c54e --- /dev/null +++ b/tendermint/src/abci/doc/request-query.md @@ -0,0 +1,3 @@ +Queries for data from the application at current or past height. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#query) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-applysnapshotchunk.md b/tendermint/src/abci/doc/response-applysnapshotchunk.md new file mode 100644 index 000000000..bffabe7af --- /dev/null +++ b/tendermint/src/abci/doc/response-applysnapshotchunk.md @@ -0,0 +1,7 @@ +Returns the result of applying a snapshot chunk and associated data. + +The application can choose to refetch chunks and/or ban P2P peers as +appropriate. Tendermint will not do this unless instructed by the +application. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#applysnapshotchunk) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-beginblock.md b/tendermint/src/abci/doc/response-beginblock.md new file mode 100644 index 000000000..255efd098 --- /dev/null +++ b/tendermint/src/abci/doc/response-beginblock.md @@ -0,0 +1,3 @@ +Returns events that occurred when beginning a new block. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#beginblock) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-checktx.md b/tendermint/src/abci/doc/response-checktx.md new file mode 100644 index 000000000..cd31b1703 --- /dev/null +++ b/tendermint/src/abci/doc/response-checktx.md @@ -0,0 +1,3 @@ +Returns the result of checking a transaction for mempool inclusion. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#checktx) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-commit.md b/tendermint/src/abci/doc/response-commit.md new file mode 100644 index 000000000..822aab48d --- /dev/null +++ b/tendermint/src/abci/doc/response-commit.md @@ -0,0 +1,3 @@ +Returns the result of persisting the application state. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#commit) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-delivertx.md b/tendermint/src/abci/doc/response-delivertx.md new file mode 100644 index 000000000..cb83a6fd9 --- /dev/null +++ b/tendermint/src/abci/doc/response-delivertx.md @@ -0,0 +1,4 @@ +Returns events that occurred while executing a transaction against the +application state. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#delivertx) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-echo.md b/tendermint/src/abci/doc/response-echo.md new file mode 100644 index 000000000..92658169f --- /dev/null +++ b/tendermint/src/abci/doc/response-echo.md @@ -0,0 +1,3 @@ +Echoes a string to test an ABCI implementation. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#echo) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-endblock.md b/tendermint/src/abci/doc/response-endblock.md new file mode 100644 index 000000000..062cabb84 --- /dev/null +++ b/tendermint/src/abci/doc/response-endblock.md @@ -0,0 +1,3 @@ +Returns validator updates that occur after the end of a block. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#endblock) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-exception.md b/tendermint/src/abci/doc/response-exception.md new file mode 100644 index 000000000..5d8fb6c67 --- /dev/null +++ b/tendermint/src/abci/doc/response-exception.md @@ -0,0 +1 @@ +Returns an exception (undocumented, nondeterministic). \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-flush.md b/tendermint/src/abci/doc/response-flush.md new file mode 100644 index 000000000..6c411e1bf --- /dev/null +++ b/tendermint/src/abci/doc/response-flush.md @@ -0,0 +1,3 @@ +Indicates that all pending requests have been completed with their responses flushed. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#flush) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-info.md b/tendermint/src/abci/doc/response-info.md new file mode 100644 index 000000000..e0c64b1f5 --- /dev/null +++ b/tendermint/src/abci/doc/response-info.md @@ -0,0 +1,3 @@ +Returns information about the application state. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#info) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-initchain.md b/tendermint/src/abci/doc/response-initchain.md new file mode 100644 index 000000000..b7ea62de7 --- /dev/null +++ b/tendermint/src/abci/doc/response-initchain.md @@ -0,0 +1,3 @@ +Returned on genesis after initializing chain state. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#initchain) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-listsnapshots.md b/tendermint/src/abci/doc/response-listsnapshots.md new file mode 100644 index 000000000..48255b800 --- /dev/null +++ b/tendermint/src/abci/doc/response-listsnapshots.md @@ -0,0 +1,3 @@ +Returns a list of local state snapshots. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#listsnapshots) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-loadsnapshotchunk.md b/tendermint/src/abci/doc/response-loadsnapshotchunk.md new file mode 100644 index 000000000..2eaf1c614 --- /dev/null +++ b/tendermint/src/abci/doc/response-loadsnapshotchunk.md @@ -0,0 +1,3 @@ +Returns a snapshot chunk from the application. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#loadsnapshotchunk) \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-offersnapshot.md b/tendermint/src/abci/doc/response-offersnapshot.md new file mode 100644 index 000000000..0da7a66fa --- /dev/null +++ b/tendermint/src/abci/doc/response-offersnapshot.md @@ -0,0 +1,7 @@ +Returns the application's response to a snapshot offer. + +See also the [`Snapshot`] data type and the [ABCI state sync documentation][ssd]. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#offersnapshot) + +[ssd]: https://docs.tendermint.com/master/spec/abci/apps.html#state-sync \ No newline at end of file diff --git a/tendermint/src/abci/doc/response-query.md b/tendermint/src/abci/doc/response-query.md new file mode 100644 index 000000000..57eb3bf4a --- /dev/null +++ b/tendermint/src/abci/doc/response-query.md @@ -0,0 +1,3 @@ +Returns data queried from the application. + +[ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#query) \ No newline at end of file diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs new file mode 100644 index 000000000..2dc5d7e14 --- /dev/null +++ b/tendermint/src/abci/event.rs @@ -0,0 +1,186 @@ +use crate::prelude::*; + +/// An event that occurred while processing a request. +/// +/// Application developers can attach additional information to +/// [`BeginBlock`](super::response::BeginBlock), +/// [`EndBlock`](super::response::EndBlock), +/// [`CheckTx`](super::response::CheckTx), and +/// [`DeliverTx`](super::response::DeliverTx) responses. Later, transactions may +/// be queried using these events. +/// +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#events) +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Event { + /// The kind of event. + /// + /// Tendermint calls this the `type`, but we use `kind` to avoid confusion + /// with Rust types and follow Rust conventions. + pub kind: String, + /// A list of [`EventAttribute`]s describing the event. + pub attributes: Vec, +} + +impl Event { + /// Construct an event from generic data. + /// + /// The `From` impls on [`EventAttribute`] and the [`EventAttributeIndexExt`] + /// trait allow ergonomic event construction, as in this example: + /// + /// ``` + /// use tendermint::abci::{Event, EventAttributeIndexExt}; + /// + /// let event = Event::new( + /// "app", + /// vec![ + /// ("key1", "value1").index(), + /// ("key2", "value2").index(), + /// ("key3", "value3").no_index(), // will not be indexed + /// ], + /// ); + /// ``` + // XXX(hdevalence): remove vec! from example after https://github.com/rust-lang/rust/pull/65819 + pub fn new(kind: K, attributes: I) -> Self + where + K: Into, + I: IntoIterator, + I::Item: Into, + { + Self { + kind: kind.into(), + attributes: attributes.into_iter().map(Into::into).collect(), + } + } +} + +/// A key-value pair describing an [`Event`]. +/// +/// Generic methods are provided for more ergonomic attribute construction, see +/// [`Event::new`] for details. +/// +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#events) +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct EventAttribute { + /// The event key. + pub key: String, + /// The event value. + pub value: String, + /// Whether Tendermint's indexer should index this event. + /// + /// **This field is nondeterministic**. + pub index: bool, +} + +impl, V: Into> From<(K, V, bool)> for EventAttribute { + fn from((key, value, index): (K, V, bool)) -> Self { + EventAttribute { + key: key.into(), + value: value.into(), + index, + } + } +} + +/// Adds convenience methods to tuples for more ergonomic [`EventAttribute`] +/// construction. +/// +/// See [`Event::new`] for details. +#[allow(missing_docs)] +pub trait EventAttributeIndexExt: private::Sealed { + type Key; + type Value; + + /// Indicate that this key/value pair should be indexed by Tendermint. + fn index(self) -> (Self::Key, Self::Value, bool); + /// Indicate that this key/value pair should not be indexed by Tendermint. + fn no_index(self) -> (Self::Key, Self::Value, bool); +} + +impl, V: Into> EventAttributeIndexExt for (K, V) { + type Key = K; + type Value = V; + fn index(self) -> (K, V, bool) { + let (key, value) = self; + (key, value, true) + } + fn no_index(self) -> (K, V, bool) { + let (key, value) = self; + (key, value, false) + } +} + +mod private { + use crate::prelude::*; + + pub trait Sealed {} + + impl, V: Into> Sealed for (K, V) {} +} + +impl, V: Into> From<(K, V)> for EventAttribute { + fn from((key, value): (K, V)) -> Self { + (key, value, false).into() + } +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::{TryFrom, TryInto}; + +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::EventAttribute { + fn from(event: EventAttribute) -> Self { + Self { + key: event.key, + value: event.value, + index: event.index, + } + } +} + +impl TryFrom for EventAttribute { + type Error = crate::Error; + + fn try_from(event: pb::EventAttribute) -> Result { + Ok(Self { + key: event.key, + value: event.value, + index: event.index, + }) + } +} + +impl Protobuf for EventAttribute {} + +impl From for pb::Event { + fn from(event: Event) -> Self { + Self { + r#type: event.kind, + attributes: event.attributes.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom for Event { + type Error = crate::Error; + + fn try_from(event: pb::Event) -> Result { + Ok(Self { + kind: event.r#type, + attributes: event + .attributes + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + }) + } +} + +impl Protobuf for Event {} diff --git a/tendermint/src/abci/kind.rs b/tendermint/src/abci/kind.rs new file mode 100644 index 000000000..065a01c9a --- /dev/null +++ b/tendermint/src/abci/kind.rs @@ -0,0 +1,23 @@ +/// A category of ABCI method. +/// +/// ABCI methods are split into four categories. Tendermint opens one ABCI +/// connection for each category and refers to these categories as *connections*, +/// but nothing actually restricts an ABCI connection from calling methods in +/// multiple categories. +/// +/// This enum breaks out the `Flush` method as a distinct category, since it is +/// used to control the execution of other methods. +pub enum MethodKind { + /// A consensus method, driven by the consensus protocol and responsible for + /// block execution. + Consensus, + /// A mempool method, used for validating new transactions before they're + /// shared or included in a block. + Mempool, + /// A snapshot method, used for serving and restoring state snapshots. + Snapshot, + /// An info method, used for initialization and user queries. + Info, + /// The flush method requests that all pending method requests are fully executed. + Flush, +} diff --git a/tendermint/src/abci/params.rs b/tendermint/src/abci/params.rs new file mode 100644 index 000000000..f8e85e911 --- /dev/null +++ b/tendermint/src/abci/params.rs @@ -0,0 +1,219 @@ +//! Consensus-relevant parameters that can be adjusted by the ABCI app. + +use crate::prelude::*; + +use chrono::Duration; +use core::convert::{TryFrom, TryInto}; + +/// All consensus-relevant parameters that can be adjusted by the ABCI app. +/// +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#consensusparams) +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ConsensusParams { + /// Parameters limiting the size of a block and time between consecutive blocks. + pub block: BlockParams, + /// Parameters limiting the validity of evidence of byzantine behaviour. + pub evidence: EvidenceParams, + /// Parameters limiting the types of public keys validators can use. + pub validator: ValidatorParams, + /// The ABCI application version. + pub version: VersionParams, +} +/// BlockParams contains limits on the block size. +/// +/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#blockparams) +/// +/// XXX(hdevalence): this isn't ABCI-specific, should it live here? +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct BlockParams { + /// Max block size, in bytes. + pub max_bytes: i64, + /// Max sum of `gas_wanted` in a proposed block. + /// + /// Note: blocks that violate this may be committed if there are Byzantine + /// proposers. It's the application's responsibility to handle this when + /// processing a block. + pub max_gas: i64, +} + +/// EvidenceParams determine how we handle evidence of malfeasance. +/// +/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#evidenceparams) +/// +/// XXX(hdevalence): this isn't ABCI-specific, should it live here? +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct EvidenceParams { + /// Max age of evidence, in blocks. + pub max_age_num_blocks: i64, + /// Max age of evidence, in time. + /// + /// It should correspond with an app's "unbonding period" or other similar + /// mechanism for handling [Nothing-At-Stake attacks][nas]. + /// + /// [nas]: https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed + pub max_age_duration: Duration, + /// This sets the maximum size of total evidence in bytes that can be + /// committed in a single block, and should fall comfortably under the max + /// block bytes. The default is 1048576 or 1MB. + pub max_bytes: i64, +} + +/// ValidatorParams restrict the public key types validators can use. +/// +/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#validatorparams) +/// +/// XXX(hdevalence): this isn't ABCI-specific, should it live here? +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ValidatorParams { + /// List of accepted public key types. + pub pub_key_types: Vec, +} + +/// (No description) +/// +/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#versionparams) +/// +/// XXX(hdevalence): this isn't ABCI-specific, should it live here? +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct VersionParams { + /// The ABCI application version. + pub app_version: u64, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use tendermint_proto::types as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ConsensusParams { + fn from(params: ConsensusParams) -> Self { + Self { + block: Some(params.block.into()), + evidence: Some(params.evidence.into()), + validator: Some(params.validator.into()), + version: Some(params.version.into()), + } + } +} + +impl TryFrom for ConsensusParams { + type Error = crate::Error; + + fn try_from(params: pb::ConsensusParams) -> Result { + Ok(Self { + block: params.block.ok_or("missing block params")?.try_into()?, + evidence: params + .evidence + .ok_or("missing evidence params")? + .try_into()?, + validator: params + .validator + .ok_or("missing validator params")? + .try_into()?, + version: params.version.ok_or("missing version params")?.try_into()?, + }) + } +} + +impl Protobuf for ConsensusParams {} + +impl From for pb::BlockParams { + fn from(params: BlockParams) -> Self { + Self { + max_bytes: params.max_bytes, + max_gas: params.max_gas, + } + } +} + +impl TryFrom for BlockParams { + type Error = crate::Error; + + fn try_from(params: pb::BlockParams) -> Result { + if params.max_bytes == 0 { + Err("BlockParams::max_bytes must be greater than 0")? + } + if params.max_gas < -1 { + Err("BlockParams::max_gas must be greater than or equal to -1")? + } + + Ok(Self { + max_bytes: params.max_bytes, + max_gas: params.max_gas, + }) + } +} + +impl Protobuf for BlockParams {} + +impl From for pb::EvidenceParams { + fn from(params: EvidenceParams) -> Self { + Self { + max_age_num_blocks: params.max_age_num_blocks, + max_age_duration: Some(params.max_age_duration.into()), + max_bytes: params.max_bytes, + } + } +} + +impl TryFrom for EvidenceParams { + type Error = crate::Error; + + fn try_from(params: pb::EvidenceParams) -> Result { + Ok(Self { + max_age_num_blocks: params.max_age_num_blocks, + max_age_duration: params + .max_age_duration + .ok_or("missing max age duration")? + .into(), + max_bytes: params.max_bytes, + }) + } +} + +impl Protobuf for EvidenceParams {} + +impl From for pb::ValidatorParams { + fn from(params: ValidatorParams) -> Self { + Self { + pub_key_types: params.pub_key_types, + } + } +} + +impl TryFrom for ValidatorParams { + type Error = crate::Error; + + fn try_from(params: pb::ValidatorParams) -> Result { + Ok(Self { + pub_key_types: params.pub_key_types, + }) + } +} + +impl Protobuf for ValidatorParams {} + +impl From for pb::VersionParams { + fn from(params: VersionParams) -> Self { + Self { + app_version: params.app_version, + } + } +} + +impl TryFrom for VersionParams { + type Error = crate::Error; + + fn try_from(params: pb::VersionParams) -> Result { + Ok(Self { + app_version: params.app_version, + }) + } +} + +impl Protobuf for VersionParams {} diff --git a/tendermint/src/abci/request.rs b/tendermint/src/abci/request.rs new file mode 100644 index 000000000..fa8cdd809 --- /dev/null +++ b/tendermint/src/abci/request.rs @@ -0,0 +1,306 @@ +//! ABCI requests and request data. +//! +//! The [`Request`] enum records all possible ABCI requests. Requests that +//! contain data are modeled as a separate struct, to avoid duplication of field +//! definitions. + +use crate::prelude::*; + +// IMPORTANT NOTE ON DOCUMENTATION: +// +// The documentation for each request type is adapted from the ABCI Methods and +// Types spec document. However, the same logical request may appear three +// times, as a struct with the request data, as a Request variant, and as a +// CategoryRequest variant. +// +// To avoid duplication, this documentation is stored in the doc/ folder in +// individual .md files, which are pasted onto the relevant items using #[doc = +// include_str!(...)]. +// +// This is also why certain submodules have #[allow(unused)] imports to bring +// items into scope for doc links, rather than changing the doc links -- it +// allows the doc comments to be copied without editing. + +use core::convert::{TryFrom, TryInto}; + +use super::MethodKind; + +// bring into scope for doc links +#[allow(unused)] +use super::types::Snapshot; + +mod apply_snapshot_chunk; +mod begin_block; +mod check_tx; +mod deliver_tx; +mod echo; +mod end_block; +mod info; +mod init_chain; +mod load_snapshot_chunk; +mod offer_snapshot; +mod query; + +pub use apply_snapshot_chunk::ApplySnapshotChunk; +pub use begin_block::BeginBlock; +pub use check_tx::{CheckTx, CheckTxKind}; +pub use deliver_tx::DeliverTx; +pub use echo::Echo; +pub use end_block::EndBlock; +pub use info::Info; +pub use init_chain::InitChain; +pub use load_snapshot_chunk::LoadSnapshotChunk; +pub use offer_snapshot::OfferSnapshot; +pub use query::Query; + +/// All possible ABCI requests. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum Request { + #[doc = include_str!("doc/request-echo.md")] + Echo(Echo), + #[doc = include_str!("doc/request-flush.md")] + Flush, + #[doc = include_str!("doc/request-info.md")] + Info(Info), + #[doc = include_str!("doc/request-initchain.md")] + InitChain(InitChain), + #[doc = include_str!("doc/request-query.md")] + Query(Query), + #[doc = include_str!("doc/request-beginblock.md")] + BeginBlock(BeginBlock), + #[doc = include_str!("doc/request-checktx.md")] + CheckTx(CheckTx), + #[doc = include_str!("doc/request-delivertx.md")] + DeliverTx(DeliverTx), + #[doc = include_str!("doc/request-endblock.md")] + EndBlock(EndBlock), + #[doc = include_str!("doc/request-commit.md")] + Commit, + #[doc = include_str!("doc/request-listsnapshots.md")] + ListSnapshots, + #[doc = include_str!("doc/request-offersnapshot.md")] + OfferSnapshot(OfferSnapshot), + #[doc = include_str!("doc/request-loadsnapshotchunk.md")] + LoadSnapshotChunk(LoadSnapshotChunk), + #[doc = include_str!("doc/request-applysnapshotchunk.md")] + ApplySnapshotChunk(ApplySnapshotChunk), +} + +impl Request { + /// Get the method kind for this request. + pub fn kind(&self) -> MethodKind { + use Request::*; + match self { + Flush => MethodKind::Flush, + InitChain(_) => MethodKind::Consensus, + BeginBlock(_) => MethodKind::Consensus, + DeliverTx(_) => MethodKind::Consensus, + EndBlock(_) => MethodKind::Consensus, + Commit => MethodKind::Consensus, + CheckTx(_) => MethodKind::Mempool, + ListSnapshots => MethodKind::Snapshot, + OfferSnapshot(_) => MethodKind::Snapshot, + LoadSnapshotChunk(_) => MethodKind::Snapshot, + ApplySnapshotChunk(_) => MethodKind::Snapshot, + Info(_) => MethodKind::Info, + Query(_) => MethodKind::Info, + Echo(_) => MethodKind::Info, + } + } +} + +/// The consensus category of ABCI requests. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum ConsensusRequest { + #[doc = include_str!("doc/request-initchain.md")] + InitChain(InitChain), + #[doc = include_str!("doc/request-beginblock.md")] + BeginBlock(BeginBlock), + #[doc = include_str!("doc/request-delivertx.md")] + DeliverTx(DeliverTx), + #[doc = include_str!("doc/request-endblock.md")] + EndBlock(EndBlock), + #[doc = include_str!("doc/request-commit.md")] + Commit, +} + +impl From for Request { + fn from(req: ConsensusRequest) -> Self { + match req { + ConsensusRequest::InitChain(x) => Self::InitChain(x), + ConsensusRequest::BeginBlock(x) => Self::BeginBlock(x), + ConsensusRequest::DeliverTx(x) => Self::DeliverTx(x), + ConsensusRequest::EndBlock(x) => Self::EndBlock(x), + ConsensusRequest::Commit => Self::Commit, + } + } +} + +impl TryFrom for ConsensusRequest { + type Error = &'static str; + fn try_from(req: Request) -> Result { + match req { + Request::InitChain(x) => Ok(Self::InitChain(x)), + Request::BeginBlock(x) => Ok(Self::BeginBlock(x)), + Request::DeliverTx(x) => Ok(Self::DeliverTx(x)), + Request::EndBlock(x) => Ok(Self::EndBlock(x)), + Request::Commit => Ok(Self::Commit), + _ => Err("wrong request type"), + } + } +} + +/// The mempool category of ABCI requests. +#[derive(Clone, PartialEq, Debug)] +pub enum MempoolRequest { + #[doc = include_str!("doc/request-checktx.md")] + CheckTx(CheckTx), +} + +impl From for Request { + fn from(req: MempoolRequest) -> Self { + match req { + MempoolRequest::CheckTx(x) => Self::CheckTx(x), + } + } +} + +impl TryFrom for MempoolRequest { + type Error = &'static str; + fn try_from(req: Request) -> Result { + match req { + Request::CheckTx(x) => Ok(Self::CheckTx(x)), + _ => Err("wrong request type"), + } + } +} + +/// The info category of ABCI requests. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum InfoRequest { + #[doc = include_str!("doc/request-info.md")] + Info(Info), + #[doc = include_str!("doc/request-query.md")] + Query(Query), + #[doc = include_str!("doc/request-echo.md")] + Echo(Echo), +} + +impl From for Request { + fn from(req: InfoRequest) -> Self { + match req { + InfoRequest::Info(x) => Self::Info(x), + InfoRequest::Query(x) => Self::Query(x), + InfoRequest::Echo(x) => Self::Echo(x), + } + } +} + +impl TryFrom for InfoRequest { + type Error = &'static str; + fn try_from(req: Request) -> Result { + match req { + Request::Info(x) => Ok(Self::Info(x)), + Request::Query(x) => Ok(Self::Query(x)), + Request::Echo(x) => Ok(Self::Echo(x)), + _ => Err("wrong request type"), + } + } +} + +/// The snapshot category of ABCI requests. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum SnapshotRequest { + #[doc = include_str!("doc/request-listsnapshots.md")] + ListSnapshots, + #[doc = include_str!("doc/request-offersnapshot.md")] + OfferSnapshot(OfferSnapshot), + #[doc = include_str!("doc/request-loadsnapshotchunk.md")] + LoadSnapshotChunk(LoadSnapshotChunk), + #[doc = include_str!("doc/request-applysnapshotchunk.md")] + ApplySnapshotChunk(ApplySnapshotChunk), +} + +impl From for Request { + fn from(req: SnapshotRequest) -> Self { + match req { + SnapshotRequest::ListSnapshots => Self::ListSnapshots, + SnapshotRequest::OfferSnapshot(x) => Self::OfferSnapshot(x), + SnapshotRequest::LoadSnapshotChunk(x) => Self::LoadSnapshotChunk(x), + SnapshotRequest::ApplySnapshotChunk(x) => Self::ApplySnapshotChunk(x), + } + } +} + +impl TryFrom for SnapshotRequest { + type Error = &'static str; + fn try_from(req: Request) -> Result { + match req { + Request::ListSnapshots => Ok(Self::ListSnapshots), + Request::OfferSnapshot(x) => Ok(Self::OfferSnapshot(x)), + Request::LoadSnapshotChunk(x) => Ok(Self::LoadSnapshotChunk(x)), + Request::ApplySnapshotChunk(x) => Ok(Self::ApplySnapshotChunk(x)), + _ => Err("wrong request type"), + } + } +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::Request { + fn from(request: Request) -> pb::Request { + use pb::request::Value; + let value = match request { + Request::Echo(x) => Some(Value::Echo(x.into())), + Request::Flush => Some(Value::Flush(Default::default())), + Request::Info(x) => Some(Value::Info(x.into())), + Request::InitChain(x) => Some(Value::InitChain(x.into())), + Request::Query(x) => Some(Value::Query(x.into())), + Request::BeginBlock(x) => Some(Value::BeginBlock(x.into())), + Request::CheckTx(x) => Some(Value::CheckTx(x.into())), + Request::DeliverTx(x) => Some(Value::DeliverTx(x.into())), + Request::EndBlock(x) => Some(Value::EndBlock(x.into())), + Request::Commit => Some(Value::Commit(Default::default())), + Request::ListSnapshots => Some(Value::ListSnapshots(Default::default())), + Request::OfferSnapshot(x) => Some(Value::OfferSnapshot(x.into())), + Request::LoadSnapshotChunk(x) => Some(Value::LoadSnapshotChunk(x.into())), + Request::ApplySnapshotChunk(x) => Some(Value::ApplySnapshotChunk(x.into())), + }; + pb::Request { value } + } +} + +impl TryFrom for Request { + type Error = crate::Error; + + fn try_from(request: pb::Request) -> Result { + use pb::request::Value; + match request.value { + Some(Value::Echo(x)) => Ok(Request::Echo(x.try_into()?)), + Some(Value::Flush(pb::RequestFlush {})) => Ok(Request::Flush), + Some(Value::Info(x)) => Ok(Request::Info(x.try_into()?)), + Some(Value::InitChain(x)) => Ok(Request::InitChain(x.try_into()?)), + Some(Value::Query(x)) => Ok(Request::Query(x.try_into()?)), + Some(Value::BeginBlock(x)) => Ok(Request::BeginBlock(x.try_into()?)), + Some(Value::CheckTx(x)) => Ok(Request::CheckTx(x.try_into()?)), + Some(Value::DeliverTx(x)) => Ok(Request::DeliverTx(x.try_into()?)), + Some(Value::EndBlock(x)) => Ok(Request::EndBlock(x.try_into()?)), + Some(Value::Commit(pb::RequestCommit {})) => Ok(Request::Commit), + Some(Value::ListSnapshots(pb::RequestListSnapshots {})) => Ok(Request::ListSnapshots), + Some(Value::OfferSnapshot(x)) => Ok(Request::OfferSnapshot(x.try_into()?)), + Some(Value::LoadSnapshotChunk(x)) => Ok(Request::LoadSnapshotChunk(x.try_into()?)), + Some(Value::ApplySnapshotChunk(x)) => Ok(Request::ApplySnapshotChunk(x.try_into()?)), + None => Err("no request in proto".into()), + } + } +} + +impl Protobuf for Request {} diff --git a/tendermint/src/abci/request/apply_snapshot_chunk.rs b/tendermint/src/abci/request/apply_snapshot_chunk.rs new file mode 100644 index 000000000..48fc4b7aa --- /dev/null +++ b/tendermint/src/abci/request/apply_snapshot_chunk.rs @@ -0,0 +1,73 @@ +use crate::prelude::*; + +use bytes::Bytes; + +// bring into scope for doc links +#[allow(unused)] +use super::{super::types::Snapshot, Info, LoadSnapshotChunk}; + +/// Applies a snapshot chunk. +/// +/// The application can choose to refetch chunks and/or ban P2P peers as +/// appropriate. Tendermint will not do this unless instructed by the +/// application. +/// +/// The application may want to verify each chunk, e.g., by attaching chunk +/// hashes in [`Snapshot::metadata`] and/or incrementally verifying contents +/// against `app_hash`. +/// +/// When all chunks have been accepted, Tendermint will make an ABCI [`Info`] +/// request to verify that `last_block_app_hash` and `last_block_height` match +/// the expected values, and record the `app_version` in the node state. It then +/// switches to fast sync or consensus and joins the network. +/// +/// If Tendermint is unable to retrieve the next chunk after some time (e.g., +/// because no suitable peers are available), it will reject the snapshot and try +/// a different one via `OfferSnapshot`. The application should be prepared to +/// reset and accept it or abort as appropriate. +/// +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#applysnapshotchunk) +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ApplySnapshotChunk { + /// The chunk index, starting from `0`. Tendermint applies chunks sequentially. + pub index: u32, + /// The binary chunk contents, as returned by [`LoadSnapshotChunk`]. + pub chunk: Bytes, + /// The P2P ID of the node who sent this chunk. + pub sender: String, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::RequestApplySnapshotChunk { + fn from(apply_snapshot_chunk: ApplySnapshotChunk) -> Self { + Self { + index: apply_snapshot_chunk.index, + chunk: apply_snapshot_chunk.chunk, + sender: apply_snapshot_chunk.sender, + } + } +} + +impl TryFrom for ApplySnapshotChunk { + type Error = crate::Error; + + fn try_from(apply_snapshot_chunk: pb::RequestApplySnapshotChunk) -> Result { + Ok(Self { + index: apply_snapshot_chunk.index, + chunk: apply_snapshot_chunk.chunk, + sender: apply_snapshot_chunk.sender, + }) + } +} + +impl Protobuf for ApplySnapshotChunk {} diff --git a/tendermint/src/abci/request/begin_block.rs b/tendermint/src/abci/request/begin_block.rs new file mode 100644 index 000000000..0d9ac4b37 --- /dev/null +++ b/tendermint/src/abci/request/begin_block.rs @@ -0,0 +1,77 @@ +use crate::prelude::*; + +use bytes::Bytes; + +use crate::block; + +use super::super::types::{Evidence, LastCommitInfo}; + +// bring into scope for doc links +#[allow(unused)] +use super::DeliverTx; + +#[doc = include_str!("../doc/request-beginblock.md")] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct BeginBlock { + /// The block's hash. + /// + /// This can be derived from the block header. + pub hash: Bytes, + /// The block header. + pub header: block::Header, + /// Information about the last commit. + /// + /// This includes the round, the list of validators, and which validators + /// signed the last block. + pub last_commit_info: LastCommitInfo, + /// Evidence of validator misbehavior. + pub byzantine_validators: Vec, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::{TryFrom, TryInto}; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::RequestBeginBlock { + fn from(begin_block: BeginBlock) -> Self { + Self { + hash: begin_block.hash, + header: Some(begin_block.header.into()), + last_commit_info: Some(begin_block.last_commit_info.into()), + byzantine_validators: begin_block + .byzantine_validators + .into_iter() + .map(Into::into) + .collect(), + } + } +} + +impl TryFrom for BeginBlock { + type Error = crate::Error; + + fn try_from(begin_block: pb::RequestBeginBlock) -> Result { + Ok(Self { + hash: begin_block.hash, + header: begin_block.header.ok_or("missing header")?.try_into()?, + last_commit_info: begin_block + .last_commit_info + .ok_or("missing last commit info")? + .try_into()?, + byzantine_validators: begin_block + .byzantine_validators + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + }) + } +} + +impl Protobuf for BeginBlock {} diff --git a/tendermint/src/abci/request/check_tx.rs b/tendermint/src/abci/request/check_tx.rs new file mode 100644 index 000000000..55c7f6832 --- /dev/null +++ b/tendermint/src/abci/request/check_tx.rs @@ -0,0 +1,74 @@ +use crate::prelude::*; + +use bytes::Bytes; + +#[doc = include_str!("../doc/request-checktx.md")] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct CheckTx { + /// The transaction bytes. + pub tx: Bytes, + /// The kind of check to perform. + /// + /// Note: this field is called `type` in the protobuf, but we call it `kind` + /// to avoid the Rust keyword. + pub kind: CheckTxKind, +} + +/// The possible kinds of [`CheckTx`] checks. +/// +/// Note: the +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#checktx) +/// calls this `CheckTxType`, but we follow the Rust convention and name it `CheckTxKind` +/// to avoid confusion with Rust types. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[repr(i32)] +pub enum CheckTxKind { + /// A full check is required (the default). + New = 0, + /// Indicates that the mempool is initiating a recheck of the transaction. + Recheck = 1, +} + +impl Default for CheckTxKind { + fn default() -> Self { + CheckTxKind::New + } +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::RequestCheckTx { + fn from(check_tx: CheckTx) -> Self { + Self { + tx: check_tx.tx, + r#type: check_tx.kind as i32, + } + } +} + +impl TryFrom for CheckTx { + type Error = crate::Error; + + fn try_from(check_tx: pb::RequestCheckTx) -> Result { + let kind = match check_tx.r#type { + 0 => CheckTxKind::New, + 1 => CheckTxKind::Recheck, + _ => Err("unknown checktx type")?, + }; + Ok(Self { + tx: check_tx.tx, + kind, + }) + } +} + +impl Protobuf for CheckTx {} diff --git a/tendermint/src/abci/request/deliver_tx.rs b/tendermint/src/abci/request/deliver_tx.rs new file mode 100644 index 000000000..0b4c0907d --- /dev/null +++ b/tendermint/src/abci/request/deliver_tx.rs @@ -0,0 +1,37 @@ +use crate::prelude::*; + +use bytes::Bytes; + +#[doc = include_str!("../doc/request-delivertx.md")] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct DeliverTx { + /// The bytes of the transaction to execute. + pub tx: Bytes, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::RequestDeliverTx { + fn from(deliver_tx: DeliverTx) -> Self { + Self { tx: deliver_tx.tx } + } +} + +impl TryFrom for DeliverTx { + type Error = crate::Error; + + fn try_from(deliver_tx: pb::RequestDeliverTx) -> Result { + Ok(Self { tx: deliver_tx.tx }) + } +} + +impl Protobuf for DeliverTx {} diff --git a/tendermint/src/abci/request/echo.rs b/tendermint/src/abci/request/echo.rs new file mode 100644 index 000000000..13580398b --- /dev/null +++ b/tendermint/src/abci/request/echo.rs @@ -0,0 +1,39 @@ +use crate::prelude::*; + +#[doc = include_str!("../doc/request-echo.md")] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Echo { + /// The message to send back. + pub message: String, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::RequestEcho { + fn from(echo: Echo) -> Self { + Self { + message: echo.message, + } + } +} + +impl TryFrom for Echo { + type Error = &'static str; + + fn try_from(echo: pb::RequestEcho) -> Result { + Ok(Self { + message: echo.message, + }) + } +} + +impl Protobuf for Echo {} diff --git a/tendermint/src/abci/request/end_block.rs b/tendermint/src/abci/request/end_block.rs new file mode 100644 index 000000000..985153403 --- /dev/null +++ b/tendermint/src/abci/request/end_block.rs @@ -0,0 +1,39 @@ +use crate::prelude::*; + +#[doc = include_str!("../doc/request-endblock.md")] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct EndBlock { + /// The height of the block just executed. + pub height: i64, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::RequestEndBlock { + fn from(end_block: EndBlock) -> Self { + Self { + height: end_block.height, + } + } +} + +impl TryFrom for EndBlock { + type Error = crate::Error; + + fn try_from(end_block: pb::RequestEndBlock) -> Result { + Ok(Self { + height: end_block.height, + }) + } +} + +impl Protobuf for EndBlock {} diff --git a/tendermint/src/abci/request/info.rs b/tendermint/src/abci/request/info.rs new file mode 100644 index 000000000..3aa8e893c --- /dev/null +++ b/tendermint/src/abci/request/info.rs @@ -0,0 +1,51 @@ +use crate::prelude::*; + +#[doc = include_str!("../doc/request-info.md")] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Info { + /// The Tendermint software semantic version. + pub version: String, + /// The Tendermint block protocol version. + pub block_version: u64, + /// The Tendermint p2p protocol version. + pub p2p_version: u64, + /// The Tendermint ABCI semantic version. + pub abci_version: String, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::RequestInfo { + fn from(info: Info) -> Self { + Self { + version: info.version, + block_version: info.block_version, + p2p_version: info.p2p_version, + abci_version: info.abci_version, + } + } +} + +impl TryFrom for Info { + type Error = &'static str; + + fn try_from(info: pb::RequestInfo) -> Result { + Ok(Self { + version: info.version, + block_version: info.block_version, + p2p_version: info.p2p_version, + abci_version: info.abci_version, + }) + } +} + +impl Protobuf for Info {} diff --git a/tendermint/src/abci/request/init_chain.rs b/tendermint/src/abci/request/init_chain.rs new file mode 100644 index 000000000..4a2e86c63 --- /dev/null +++ b/tendermint/src/abci/request/init_chain.rs @@ -0,0 +1,73 @@ +use crate::prelude::*; + +use bytes::Bytes; +use chrono::{DateTime, Utc}; + +use super::super::{params::ConsensusParams, types::ValidatorUpdate}; + +/// Called on genesis to initialize chain state. +/// +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#initchain) +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct InitChain { + /// The genesis time. + pub time: DateTime, + /// The ID of the blockchain. + pub chain_id: String, + /// Initial consensus-critical parameters. + pub consensus_params: ConsensusParams, + /// Initial genesis validators, sorted by voting power. + pub validators: Vec, + /// Serialized JSON bytes containing the initial application state. + pub app_state_bytes: Bytes, + /// Height of the initial block (typically `1`). + pub initial_height: i64, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::{TryFrom, TryInto}; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::RequestInitChain { + fn from(init_chain: InitChain) -> Self { + Self { + time: Some(init_chain.time.into()), + chain_id: init_chain.chain_id, + consensus_params: Some(init_chain.consensus_params.into()), + validators: init_chain.validators.into_iter().map(Into::into).collect(), + app_state_bytes: init_chain.app_state_bytes, + initial_height: init_chain.initial_height, + } + } +} + +impl TryFrom for InitChain { + type Error = crate::Error; + + fn try_from(init_chain: pb::RequestInitChain) -> Result { + Ok(Self { + time: init_chain.time.ok_or("missing genesis time")?.try_into()?, + chain_id: init_chain.chain_id, + consensus_params: init_chain + .consensus_params + .ok_or("missing consensus params")? + .try_into()?, + validators: init_chain + .validators + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + app_state_bytes: init_chain.app_state_bytes, + initial_height: init_chain.initial_height, + }) + } +} + +impl Protobuf for InitChain {} diff --git a/tendermint/src/abci/request/load_snapshot_chunk.rs b/tendermint/src/abci/request/load_snapshot_chunk.rs new file mode 100644 index 000000000..25229f600 --- /dev/null +++ b/tendermint/src/abci/request/load_snapshot_chunk.rs @@ -0,0 +1,47 @@ +use crate::prelude::*; + +#[doc = include_str!("../doc/request-loadsnapshotchunk.md")] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct LoadSnapshotChunk { + /// The height of the snapshot the chunks belong to. + pub height: u64, + /// An application-specific identifier of the format of the snapshot chunk. + pub format: u32, + /// The chunk index, starting from `0` for the initial chunk. + pub chunk: u32, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::RequestLoadSnapshotChunk { + fn from(load_snapshot_chunk: LoadSnapshotChunk) -> Self { + Self { + height: load_snapshot_chunk.height, + format: load_snapshot_chunk.format, + chunk: load_snapshot_chunk.chunk, + } + } +} + +impl TryFrom for LoadSnapshotChunk { + type Error = crate::Error; + + fn try_from(load_snapshot_chunk: pb::RequestLoadSnapshotChunk) -> Result { + Ok(Self { + height: load_snapshot_chunk.height, + format: load_snapshot_chunk.format, + chunk: load_snapshot_chunk.chunk, + }) + } +} + +impl Protobuf for LoadSnapshotChunk {} diff --git a/tendermint/src/abci/request/offer_snapshot.rs b/tendermint/src/abci/request/offer_snapshot.rs new file mode 100644 index 000000000..57d7c060c --- /dev/null +++ b/tendermint/src/abci/request/offer_snapshot.rs @@ -0,0 +1,55 @@ +use crate::prelude::*; + +use bytes::Bytes; + +use super::super::types::Snapshot; + +// bring into scope for doc links +#[allow(unused)] +use super::ApplySnapshotChunk; + +#[doc = include_str!("../doc/request-offersnapshot.md")] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct OfferSnapshot { + /// The snapshot offered for restoration. + pub snapshot: Snapshot, + /// The light client verified app hash for this height. + // XXX(hdevalence): replace with apphash + pub app_hash: Bytes, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::{TryFrom, TryInto}; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::RequestOfferSnapshot { + fn from(offer_snapshot: OfferSnapshot) -> Self { + Self { + snapshot: Some(offer_snapshot.snapshot.into()), + app_hash: offer_snapshot.app_hash, + } + } +} + +impl TryFrom for OfferSnapshot { + type Error = crate::Error; + + fn try_from(offer_snapshot: pb::RequestOfferSnapshot) -> Result { + Ok(Self { + snapshot: offer_snapshot + .snapshot + .ok_or("missing snapshot")? + .try_into()?, + app_hash: offer_snapshot.app_hash, + }) + } +} + +impl Protobuf for OfferSnapshot {} diff --git a/tendermint/src/abci/request/query.rs b/tendermint/src/abci/request/query.rs new file mode 100644 index 000000000..e567c5865 --- /dev/null +++ b/tendermint/src/abci/request/query.rs @@ -0,0 +1,66 @@ +use crate::prelude::*; + +use bytes::Bytes; + +#[doc = include_str!("../doc/request-query.md")] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Query { + /// Raw query bytes. + /// + /// Can be used with or in lieu of `path`. + pub data: Bytes, + /// Path of the request, like an HTTP `GET` path. + /// + /// Can be used with or in lieu of `data`. + /// + /// Applications MUST interpret `/store` as a query by key on the underlying + /// store. The key SHOULD be specified in the Data field. Applications SHOULD + /// allow queries over specific types like `/accounts/...` or `/votes/...`. + pub path: String, + /// The block height for which the query should be executed. + /// + /// The default `0` returns data for the latest committed block. Note that + /// this is the height of the block containing the application's Merkle root + /// hash, which represents the state as it was after committing the block at + /// `height - 1`. + pub height: i64, + /// Whether to return a Merkle proof with the response, if possible. + pub prove: bool, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::RequestQuery { + fn from(query: Query) -> Self { + Self { + data: query.data, + path: query.path, + height: query.height, + prove: query.prove, + } + } +} + +impl TryFrom for Query { + type Error = crate::Error; + + fn try_from(query: pb::RequestQuery) -> Result { + Ok(Self { + data: query.data, + path: query.path, + height: query.height, + prove: query.prove, + }) + } +} + +impl Protobuf for Query {} diff --git a/tendermint/src/abci/response.rs b/tendermint/src/abci/response.rs new file mode 100644 index 000000000..33c4080d8 --- /dev/null +++ b/tendermint/src/abci/response.rs @@ -0,0 +1,291 @@ +//! ABCI responses and response data. +//! +//! The [`Response`] enum records all possible ABCI responses. Responses that +//! contain data are modeled as a separate struct, to avoid duplication of field +//! definitions. + +use crate::prelude::*; + +// IMPORTANT NOTE ON DOCUMENTATION: +// +// The documentation for each request type is adapted from the ABCI Methods and +// Types spec document. However, the same logical request may appear three +// times, as a struct with the request data, as a Request variant, and as a +// CategoryRequest variant. +// +// To avoid duplication, this documentation is stored in the doc/ folder in +// individual .md files, which are pasted onto the relevant items using #[doc = +// include_str!(...)]. +// +// This is also why certain submodules have #[allow(unused)] imports to bring +// items into scope for doc links, rather than changing the doc links -- it +// allows the doc comments to be copied without editing. + +use core::convert::{TryFrom, TryInto}; + +// bring into scope for doc links +#[allow(unused)] +use super::types::Snapshot; + +mod apply_snapshot_chunk; +mod begin_block; +mod check_tx; +mod commit; +mod deliver_tx; +mod echo; +mod end_block; +mod exception; +mod info; +mod init_chain; +mod list_snapshots; +mod load_snapshot_chunk; +mod offer_snapshot; +mod query; + +pub use apply_snapshot_chunk::{ApplySnapshotChunk, ApplySnapshotChunkResult}; +pub use begin_block::BeginBlock; +pub use check_tx::CheckTx; +pub use commit::Commit; +pub use deliver_tx::DeliverTx; +pub use echo::Echo; +pub use end_block::EndBlock; +pub use exception::Exception; +pub use info::Info; +pub use init_chain::InitChain; +pub use list_snapshots::ListSnapshots; +pub use load_snapshot_chunk::LoadSnapshotChunk; +pub use offer_snapshot::OfferSnapshot; +pub use query::Query; + +/// All possible ABCI responses. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum Response { + #[doc = include_str!("doc/response-exception.md")] + Exception(Exception), + #[doc = include_str!("doc/response-echo.md")] + Echo(Echo), + #[doc = include_str!("doc/response-flush.md")] + Flush, + #[doc = include_str!("doc/response-info.md")] + Info(Info), + #[doc = include_str!("doc/response-initchain.md")] + InitChain(InitChain), + #[doc = include_str!("doc/response-query.md")] + Query(Query), + #[doc = include_str!("doc/response-beginblock.md")] + BeginBlock(BeginBlock), + #[doc = include_str!("doc/response-checktx.md")] + CheckTx(CheckTx), + #[doc = include_str!("doc/response-delivertx.md")] + DeliverTx(DeliverTx), + #[doc = include_str!("doc/response-endblock.md")] + EndBlock(EndBlock), + #[doc = include_str!("doc/response-commit.md")] + Commit(Commit), + #[doc = include_str!("doc/response-listsnapshots.md")] + ListSnapshots(ListSnapshots), + #[doc = include_str!("doc/response-offersnapshot.md")] + OfferSnapshot(OfferSnapshot), + #[doc = include_str!("doc/response-loadsnapshotchunk.md")] + LoadSnapshotChunk(LoadSnapshotChunk), + #[doc = include_str!("doc/response-applysnapshotchunk.md")] + ApplySnapshotChunk(ApplySnapshotChunk), +} + +/// The consensus category of ABCI responses. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum ConsensusResponse { + #[doc = include_str!("doc/response-initchain.md")] + InitChain(InitChain), + #[doc = include_str!("doc/response-beginblock.md")] + BeginBlock(BeginBlock), + #[doc = include_str!("doc/response-delivertx.md")] + DeliverTx(DeliverTx), + #[doc = include_str!("doc/response-endblock.md")] + EndBlock(EndBlock), + #[doc = include_str!("doc/response-commit.md")] + Commit(Commit), +} + +impl From for Response { + fn from(req: ConsensusResponse) -> Self { + match req { + ConsensusResponse::InitChain(x) => Self::InitChain(x), + ConsensusResponse::BeginBlock(x) => Self::BeginBlock(x), + ConsensusResponse::DeliverTx(x) => Self::DeliverTx(x), + ConsensusResponse::EndBlock(x) => Self::EndBlock(x), + ConsensusResponse::Commit(x) => Self::Commit(x), + } + } +} + +impl TryFrom for ConsensusResponse { + type Error = &'static str; + fn try_from(req: Response) -> Result { + match req { + Response::InitChain(x) => Ok(Self::InitChain(x)), + Response::BeginBlock(x) => Ok(Self::BeginBlock(x)), + Response::DeliverTx(x) => Ok(Self::DeliverTx(x)), + Response::EndBlock(x) => Ok(Self::EndBlock(x)), + Response::Commit(x) => Ok(Self::Commit(x)), + _ => Err("wrong request type"), + } + } +} + +/// The mempool category of ABCI responses. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum MempoolResponse { + #[doc = include_str!("doc/response-checktx.md")] + CheckTx(CheckTx), +} + +impl From for Response { + fn from(req: MempoolResponse) -> Self { + match req { + MempoolResponse::CheckTx(x) => Self::CheckTx(x), + } + } +} + +impl TryFrom for MempoolResponse { + type Error = &'static str; + fn try_from(req: Response) -> Result { + match req { + Response::CheckTx(x) => Ok(Self::CheckTx(x)), + _ => Err("wrong request type"), + } + } +} + +/// The info category of ABCI responses. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum InfoResponse { + #[doc = include_str!("doc/response-echo.md")] + Echo(Echo), + #[doc = include_str!("doc/response-info.md")] + Info(Info), + #[doc = include_str!("doc/response-query.md")] + Query(Query), +} + +impl From for Response { + fn from(req: InfoResponse) -> Self { + match req { + InfoResponse::Echo(x) => Self::Echo(x), + InfoResponse::Info(x) => Self::Info(x), + InfoResponse::Query(x) => Self::Query(x), + } + } +} + +impl TryFrom for InfoResponse { + type Error = &'static str; + fn try_from(req: Response) -> Result { + match req { + Response::Echo(x) => Ok(Self::Echo(x)), + Response::Info(x) => Ok(Self::Info(x)), + Response::Query(x) => Ok(Self::Query(x)), + _ => Err("wrong request type"), + } + } +} + +/// The snapshot category of ABCI responses. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum SnapshotResponse { + #[doc = include_str!("doc/response-listsnapshots.md")] + ListSnapshots(ListSnapshots), + #[doc = include_str!("doc/response-offersnapshot.md")] + OfferSnapshot(OfferSnapshot), + #[doc = include_str!("doc/response-loadsnapshotchunk.md")] + LoadSnapshotChunk(LoadSnapshotChunk), + #[doc = include_str!("doc/response-applysnapshotchunk.md")] + ApplySnapshotChunk(ApplySnapshotChunk), +} + +impl From for Response { + fn from(req: SnapshotResponse) -> Self { + match req { + SnapshotResponse::ListSnapshots(x) => Self::ListSnapshots(x), + SnapshotResponse::OfferSnapshot(x) => Self::OfferSnapshot(x), + SnapshotResponse::LoadSnapshotChunk(x) => Self::LoadSnapshotChunk(x), + SnapshotResponse::ApplySnapshotChunk(x) => Self::ApplySnapshotChunk(x), + } + } +} + +impl TryFrom for SnapshotResponse { + type Error = &'static str; + fn try_from(req: Response) -> Result { + match req { + Response::ListSnapshots(x) => Ok(Self::ListSnapshots(x)), + Response::OfferSnapshot(x) => Ok(Self::OfferSnapshot(x)), + Response::LoadSnapshotChunk(x) => Ok(Self::LoadSnapshotChunk(x)), + Response::ApplySnapshotChunk(x) => Ok(Self::ApplySnapshotChunk(x)), + _ => Err("wrong request type"), + } + } +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::Response { + fn from(response: Response) -> pb::Response { + use pb::response::Value; + let value = match response { + Response::Exception(x) => Some(Value::Exception(x.into())), + Response::Echo(x) => Some(Value::Echo(x.into())), + Response::Flush => Some(Value::Flush(Default::default())), + Response::Info(x) => Some(Value::Info(x.into())), + Response::InitChain(x) => Some(Value::InitChain(x.into())), + Response::Query(x) => Some(Value::Query(x.into())), + Response::BeginBlock(x) => Some(Value::BeginBlock(x.into())), + Response::CheckTx(x) => Some(Value::CheckTx(x.into())), + Response::DeliverTx(x) => Some(Value::DeliverTx(x.into())), + Response::EndBlock(x) => Some(Value::EndBlock(x.into())), + Response::Commit(x) => Some(Value::Commit(x.into())), + Response::ListSnapshots(x) => Some(Value::ListSnapshots(x.into())), + Response::OfferSnapshot(x) => Some(Value::OfferSnapshot(x.into())), + Response::LoadSnapshotChunk(x) => Some(Value::LoadSnapshotChunk(x.into())), + Response::ApplySnapshotChunk(x) => Some(Value::ApplySnapshotChunk(x.into())), + }; + pb::Response { value } + } +} + +impl TryFrom for Response { + type Error = crate::Error; + + fn try_from(response: pb::Response) -> Result { + use pb::response::Value; + match response.value { + Some(Value::Exception(x)) => Ok(Response::Exception(x.try_into()?)), + Some(Value::Echo(x)) => Ok(Response::Echo(x.try_into()?)), + Some(Value::Flush(_)) => Ok(Response::Flush), + Some(Value::Info(x)) => Ok(Response::Info(x.try_into()?)), + Some(Value::InitChain(x)) => Ok(Response::InitChain(x.try_into()?)), + Some(Value::Query(x)) => Ok(Response::Query(x.try_into()?)), + Some(Value::BeginBlock(x)) => Ok(Response::BeginBlock(x.try_into()?)), + Some(Value::CheckTx(x)) => Ok(Response::CheckTx(x.try_into()?)), + Some(Value::DeliverTx(x)) => Ok(Response::DeliverTx(x.try_into()?)), + Some(Value::EndBlock(x)) => Ok(Response::EndBlock(x.try_into()?)), + Some(Value::Commit(x)) => Ok(Response::Commit(x.try_into()?)), + Some(Value::ListSnapshots(x)) => Ok(Response::ListSnapshots(x.try_into()?)), + Some(Value::OfferSnapshot(x)) => Ok(Response::OfferSnapshot(x.try_into()?)), + Some(Value::LoadSnapshotChunk(x)) => Ok(Response::LoadSnapshotChunk(x.try_into()?)), + Some(Value::ApplySnapshotChunk(x)) => Ok(Response::ApplySnapshotChunk(x.try_into()?)), + None => Err("no response in proto".into()), + } + } +} + +impl Protobuf for Response {} diff --git a/tendermint/src/abci/response/apply_snapshot_chunk.rs b/tendermint/src/abci/response/apply_snapshot_chunk.rs new file mode 100644 index 000000000..31f165b59 --- /dev/null +++ b/tendermint/src/abci/response/apply_snapshot_chunk.rs @@ -0,0 +1,91 @@ +use crate::prelude::*; + +#[doc = include_str!("../doc/response-applysnapshotchunk.md")] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct ApplySnapshotChunk { + /// The result of applying the snapshot chunk. + pub result: ApplySnapshotChunkResult, + /// Refetch and reapply the given chunks, regardless of `result`. + /// + /// Only the listed chunks will be refetched, and reapplied in sequential + /// order. + pub refetch_chunks: Vec, + /// Reject the given P2P senders, regardless of `result`. + /// + /// Any chunks already applied will not be refetched unless explicitly + /// requested, but queued chunks from these senders will be discarded, and + /// new chunks or other snapshots rejected. + pub reject_senders: Vec, +} + +/// The result of applying a snapshot chunk. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[repr(i32)] +pub enum ApplySnapshotChunkResult { + /// Unknown result, abort all snapshot restoration. + Unknown = 0, + /// The chunk was accepted. + Accept = 1, + /// Abort snapshot restoration, and don't try any other snapshots. + Abort = 2, + /// Reapply this chunk, combine with + /// [`refetch_chunks`](ApplySnapshotChunk::refetch_chunks) and + /// [`reject_senders`](ApplySnapshotChunk::reject_senders) as appropriate. + Retry = 3, + /// Restart this snapshot from + /// [`OfferSnapshot`](super::super::request::OfferSnapshot), + /// reusing chunks unless instructed otherwise. + RetrySnapshot = 4, + /// Reject this snapshot, try a different one. + RejectSnapshot = 5, +} + +impl Default for ApplySnapshotChunkResult { + fn default() -> Self { + Self::Unknown + } +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseApplySnapshotChunk { + fn from(apply_snapshot_chunk: ApplySnapshotChunk) -> Self { + Self { + result: apply_snapshot_chunk.result as i32, + refetch_chunks: apply_snapshot_chunk.refetch_chunks, + reject_senders: apply_snapshot_chunk.reject_senders, + } + } +} + +impl TryFrom for ApplySnapshotChunk { + type Error = crate::Error; + + fn try_from(apply_snapshot_chunk: pb::ResponseApplySnapshotChunk) -> Result { + let result = match apply_snapshot_chunk.result { + 0 => ApplySnapshotChunkResult::Unknown, + 1 => ApplySnapshotChunkResult::Accept, + 2 => ApplySnapshotChunkResult::Abort, + 3 => ApplySnapshotChunkResult::Retry, + 4 => ApplySnapshotChunkResult::RetrySnapshot, + 5 => ApplySnapshotChunkResult::RejectSnapshot, + _ => Err("unknown snapshot chunk result")?, + }; + Ok(Self { + result, + refetch_chunks: apply_snapshot_chunk.refetch_chunks, + reject_senders: apply_snapshot_chunk.reject_senders, + }) + } +} + +impl Protobuf for ApplySnapshotChunk {} diff --git a/tendermint/src/abci/response/begin_block.rs b/tendermint/src/abci/response/begin_block.rs new file mode 100644 index 000000000..dd39f9ec1 --- /dev/null +++ b/tendermint/src/abci/response/begin_block.rs @@ -0,0 +1,46 @@ +use crate::prelude::*; + +// XXX(hdevalence): fix this import +use super::super::event::Event; + +#[doc = include_str!("../doc/response-beginblock.md")] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct BeginBlock { + /// Events that occurred while beginning the block. + pub events: Vec, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::{TryFrom, TryInto}; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseBeginBlock { + fn from(begin_block: BeginBlock) -> Self { + Self { + events: begin_block.events.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom for BeginBlock { + type Error = crate::Error; + + fn try_from(begin_block: pb::ResponseBeginBlock) -> Result { + Ok(Self { + events: begin_block + .events + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + }) + } +} + +impl Protobuf for BeginBlock {} diff --git a/tendermint/src/abci/response/check_tx.rs b/tendermint/src/abci/response/check_tx.rs new file mode 100644 index 000000000..659aa245f --- /dev/null +++ b/tendermint/src/abci/response/check_tx.rs @@ -0,0 +1,95 @@ +use crate::prelude::*; + +use bytes::Bytes; + +use super::super::Event; + +#[doc = include_str!("../doc/response-checktx.md")] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct CheckTx { + /// The response code. + /// + /// Transactions where `code != 0` will be rejected; these transactions will + /// not be broadcast to other nodes or included in a proposal block. + /// Tendermint attributes no other value to the response code. + pub code: u32, + /// Result bytes, if any. + pub data: Bytes, + /// The output of the application's logger. + /// + /// **May be non-deterministic**. + pub log: String, + /// Additional information. + /// + /// **May be non-deterministic**. + pub info: String, + /// Amount of gas requested for the transaction. + pub gas_wanted: i64, + /// Amount of gas consumed by the transaction. + pub gas_used: i64, + /// Events that occurred while checking the transaction. + pub events: Vec, + /// The namespace for the `code`. + pub codespace: String, + /// The transaction's sender (e.g. the signer). + pub sender: String, + /// The transaction's priority (for mempool ordering). + pub priority: i64, + /* mempool_error is contained in the proto, but skipped here: + * > mempool_error is set by Tendermint. + * > ABCI applictions creating a ResponseCheckTX should not set mempool_error. */ +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::{TryFrom, TryInto}; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseCheckTx { + fn from(check_tx: CheckTx) -> Self { + Self { + code: check_tx.code, + data: check_tx.data, + log: check_tx.log, + info: check_tx.info, + gas_wanted: check_tx.gas_wanted, + gas_used: check_tx.gas_used, + events: check_tx.events.into_iter().map(Into::into).collect(), + codespace: check_tx.codespace, + sender: check_tx.sender, + priority: check_tx.priority, + mempool_error: String::default(), + } + } +} + +impl TryFrom for CheckTx { + type Error = crate::Error; + + fn try_from(check_tx: pb::ResponseCheckTx) -> Result { + Ok(Self { + code: check_tx.code, + data: check_tx.data, + log: check_tx.log, + info: check_tx.info, + gas_wanted: check_tx.gas_wanted, + gas_used: check_tx.gas_used, + events: check_tx + .events + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + codespace: check_tx.codespace, + sender: check_tx.sender, + priority: check_tx.priority, + }) + } +} + +impl Protobuf for CheckTx {} diff --git a/tendermint/src/abci/response/commit.rs b/tendermint/src/abci/response/commit.rs new file mode 100644 index 000000000..cfdfa3036 --- /dev/null +++ b/tendermint/src/abci/response/commit.rs @@ -0,0 +1,48 @@ +use crate::prelude::*; + +use bytes::Bytes; + +#[doc = include_str!("../doc/response-commit.md")] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct Commit { + /// The Merkle root hash of the application state + /// + /// XXX(hdevalence) - is this different from an app hash? + /// XXX(hdevalence) - rename to app_hash ? + pub data: Bytes, + /// Blocks below this height may be removed. + pub retain_height: i64, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseCommit { + fn from(commit: Commit) -> Self { + Self { + data: commit.data, + retain_height: commit.retain_height, + } + } +} + +impl TryFrom for Commit { + type Error = crate::Error; + + fn try_from(commit: pb::ResponseCommit) -> Result { + Ok(Self { + data: commit.data, + retain_height: commit.retain_height, + }) + } +} + +impl Protobuf for Commit {} diff --git a/tendermint/src/abci/response/deliver_tx.rs b/tendermint/src/abci/response/deliver_tx.rs new file mode 100644 index 000000000..ed3fd663d --- /dev/null +++ b/tendermint/src/abci/response/deliver_tx.rs @@ -0,0 +1,83 @@ +use crate::prelude::*; + +use bytes::Bytes; + +use super::super::Event; + +#[doc = include_str!("../doc/response-delivertx.md")] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct DeliverTx { + /// The response code. + /// + /// This code should be `0` only if the transaction is fully valid. However, + /// invalid transactions included in a block will still be executed against + /// the application state. + pub code: u32, + /// Result bytes, if any. + pub data: Bytes, + /// The output of the application's logger. + /// + /// **May be non-deterministic**. + pub log: String, + /// Additional information. + /// + /// **May be non-deterministic**. + pub info: String, + /// Amount of gas requested for the transaction. + pub gas_wanted: i64, + /// Amount of gas consumed by the transaction. + pub gas_used: i64, + /// Events that occurred while executing the transaction. + pub events: Vec, + /// The namespace for the `code`. + pub codespace: String, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::{TryFrom, TryInto}; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseDeliverTx { + fn from(deliver_tx: DeliverTx) -> Self { + Self { + code: deliver_tx.code, + data: deliver_tx.data, + log: deliver_tx.log, + info: deliver_tx.info, + gas_wanted: deliver_tx.gas_wanted, + gas_used: deliver_tx.gas_used, + events: deliver_tx.events.into_iter().map(Into::into).collect(), + codespace: deliver_tx.codespace, + } + } +} + +impl TryFrom for DeliverTx { + type Error = crate::Error; + + fn try_from(deliver_tx: pb::ResponseDeliverTx) -> Result { + Ok(Self { + code: deliver_tx.code, + data: deliver_tx.data, + log: deliver_tx.log, + info: deliver_tx.info, + gas_wanted: deliver_tx.gas_wanted, + gas_used: deliver_tx.gas_used, + events: deliver_tx + .events + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + codespace: deliver_tx.codespace, + }) + } +} + +impl Protobuf for DeliverTx {} diff --git a/tendermint/src/abci/response/echo.rs b/tendermint/src/abci/response/echo.rs new file mode 100644 index 000000000..20d991a1d --- /dev/null +++ b/tendermint/src/abci/response/echo.rs @@ -0,0 +1,39 @@ +use crate::prelude::*; + +#[doc = include_str!("../doc/response-echo.md")] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct Echo { + /// The message sent in the request. + pub message: String, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseEcho { + fn from(echo: Echo) -> Self { + Self { + message: echo.message, + } + } +} + +impl TryFrom for Echo { + type Error = &'static str; + + fn try_from(echo: pb::ResponseEcho) -> Result { + Ok(Self { + message: echo.message, + }) + } +} + +impl Protobuf for Echo {} diff --git a/tendermint/src/abci/response/end_block.rs b/tendermint/src/abci/response/end_block.rs new file mode 100644 index 000000000..bd1fe26ad --- /dev/null +++ b/tendermint/src/abci/response/end_block.rs @@ -0,0 +1,66 @@ +use crate::prelude::*; + +use super::super::{params::ConsensusParams, types::ValidatorUpdate, Event}; + +#[doc = include_str!("../doc/response-endblock.md")] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct EndBlock { + /// Changes to the validator set, if any. + /// + /// Setting the voting power to 0 removes a validator. + pub validator_updates: Vec, + /// Changes to consensus parameters (optional). + pub consensus_param_updates: Option, + /// Events that occurred while ending the block. + pub events: Vec, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::{TryFrom, TryInto}; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseEndBlock { + fn from(end_block: EndBlock) -> Self { + Self { + validator_updates: end_block + .validator_updates + .into_iter() + .map(Into::into) + .collect(), + consensus_param_updates: end_block.consensus_param_updates.map(Into::into), + events: end_block.events.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom for EndBlock { + type Error = crate::Error; + + fn try_from(end_block: pb::ResponseEndBlock) -> Result { + Ok(Self { + validator_updates: end_block + .validator_updates + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + consensus_param_updates: end_block + .consensus_param_updates + .map(TryInto::try_into) + .transpose()?, + events: end_block + .events + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + }) + } +} + +impl Protobuf for EndBlock {} diff --git a/tendermint/src/abci/response/exception.rs b/tendermint/src/abci/response/exception.rs new file mode 100644 index 000000000..9f4a2968c --- /dev/null +++ b/tendermint/src/abci/response/exception.rs @@ -0,0 +1,39 @@ +use crate::prelude::*; + +#[doc = include_str!("../doc/response-exception.md")] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Exception { + /// Undocumented. + pub error: String, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseException { + fn from(exception: Exception) -> Self { + Self { + error: exception.error, + } + } +} + +impl TryFrom for Exception { + type Error = &'static str; + + fn try_from(exception: pb::ResponseException) -> Result { + Ok(Self { + error: exception.error, + }) + } +} + +impl Protobuf for Exception {} diff --git a/tendermint/src/abci/response/info.rs b/tendermint/src/abci/response/info.rs new file mode 100644 index 000000000..aa3f798e7 --- /dev/null +++ b/tendermint/src/abci/response/info.rs @@ -0,0 +1,58 @@ +use crate::prelude::*; + +use bytes::Bytes; + +#[doc = include_str!("../doc/response-info.md")] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct Info { + /// Some arbitrary information. + pub data: String, + /// The application software semantic version. + pub version: String, + /// The application protocol version. + pub app_version: u64, + /// The latest block for which the app has called [`Commit`](super::super::Request::Commit). + pub last_block_height: i64, + /// The latest result of [`Commit`](super::super::Request::Commit). + // XXX(hdevalence): fix this, should be apphash? + pub last_block_app_hash: Bytes, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseInfo { + fn from(info: Info) -> Self { + Self { + data: info.data, + version: info.version, + app_version: info.app_version, + last_block_height: info.last_block_height, + last_block_app_hash: info.last_block_app_hash, + } + } +} + +impl TryFrom for Info { + type Error = &'static str; + + fn try_from(info: pb::ResponseInfo) -> Result { + Ok(Self { + data: info.data, + version: info.version, + app_version: info.app_version, + last_block_height: info.last_block_height, + last_block_app_hash: info.last_block_app_hash, + }) + } +} + +impl Protobuf for Info {} diff --git a/tendermint/src/abci/response/init_chain.rs b/tendermint/src/abci/response/init_chain.rs new file mode 100644 index 000000000..30f037587 --- /dev/null +++ b/tendermint/src/abci/response/init_chain.rs @@ -0,0 +1,65 @@ +use crate::prelude::*; + +use bytes::Bytes; + +use super::super::{params::ConsensusParams, types::ValidatorUpdate}; + +#[doc = include_str!("../doc/response-initchain.md")] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct InitChain { + /// Initial consensus-critical parameters (optional). + pub consensus_params: Option, + /// Initial validator set (optional). + /// + /// If this list is empty, the initial validator set will be the one given in + /// [`request::InitChain::validators`](super::super::request::InitChain::validators). + /// + /// If this list is nonempty, it will be the initial validator set, instead + /// of the one given in + /// [`request::InitChain::validators`](super::super::request::InitChain::validators). + pub validators: Vec, + /// Initial application hash. + pub app_hash: Bytes, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::{TryFrom, TryInto}; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseInitChain { + fn from(init_chain: InitChain) -> Self { + Self { + consensus_params: init_chain.consensus_params.map(Into::into), + validators: init_chain.validators.into_iter().map(Into::into).collect(), + app_hash: init_chain.app_hash, + } + } +} + +impl TryFrom for InitChain { + type Error = crate::Error; + + fn try_from(init_chain: pb::ResponseInitChain) -> Result { + Ok(Self { + consensus_params: init_chain + .consensus_params + .map(TryInto::try_into) + .transpose()?, + validators: init_chain + .validators + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + app_hash: init_chain.app_hash, + }) + } +} + +impl Protobuf for InitChain {} diff --git a/tendermint/src/abci/response/list_snapshots.rs b/tendermint/src/abci/response/list_snapshots.rs new file mode 100644 index 000000000..79511f08a --- /dev/null +++ b/tendermint/src/abci/response/list_snapshots.rs @@ -0,0 +1,49 @@ +use crate::prelude::*; + +use super::super::types::Snapshot; + +#[doc = include_str!("../doc/response-listsnapshots.md")] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct ListSnapshots { + /// A list of local state snapshots. + pub snapshots: Vec, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::{TryFrom, TryInto}; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseListSnapshots { + fn from(list_snapshots: ListSnapshots) -> Self { + Self { + snapshots: list_snapshots + .snapshots + .into_iter() + .map(Into::into) + .collect(), + } + } +} + +impl TryFrom for ListSnapshots { + type Error = crate::Error; + + fn try_from(list_snapshots: pb::ResponseListSnapshots) -> Result { + Ok(Self { + snapshots: list_snapshots + .snapshots + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + }) + } +} + +impl Protobuf for ListSnapshots {} diff --git a/tendermint/src/abci/response/load_snapshot_chunk.rs b/tendermint/src/abci/response/load_snapshot_chunk.rs new file mode 100644 index 000000000..c86ad8887 --- /dev/null +++ b/tendermint/src/abci/response/load_snapshot_chunk.rs @@ -0,0 +1,44 @@ +use crate::prelude::*; + +use bytes::Bytes; + +#[doc = include_str!("../doc/response-loadsnapshotchunk.md")] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct LoadSnapshotChunk { + /// The binary chunk contents, in an arbitrary format. + /// + /// Chunk messages cannot be larger than 16MB *including metadata*, so 10MB + /// is a good starting point. + pub chunk: Bytes, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseLoadSnapshotChunk { + fn from(load_snapshot_chunk: LoadSnapshotChunk) -> Self { + Self { + chunk: load_snapshot_chunk.chunk, + } + } +} + +impl TryFrom for LoadSnapshotChunk { + type Error = crate::Error; + + fn try_from(load_snapshot_chunk: pb::ResponseLoadSnapshotChunk) -> Result { + Ok(Self { + chunk: load_snapshot_chunk.chunk, + }) + } +} + +impl Protobuf for LoadSnapshotChunk {} diff --git a/tendermint/src/abci/response/offer_snapshot.rs b/tendermint/src/abci/response/offer_snapshot.rs new file mode 100644 index 000000000..f84fc9b9d --- /dev/null +++ b/tendermint/src/abci/response/offer_snapshot.rs @@ -0,0 +1,66 @@ +use crate::prelude::*; + +// bring into scope for doc links +#[allow(unused)] +use super::super::types::Snapshot; + +#[doc = include_str!("../doc/response-offersnapshot.md")] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[repr(i32)] +pub enum OfferSnapshot { + /// Unknown result, abort all snapshot restoration + Unknown = 0, + /// Snapshot accepted, apply chunks + Accept = 1, + /// Abort all snapshot restoration + Abort = 2, + /// Reject this specific snapshot, try others + Reject = 3, + /// Reject all snapshots of this format, try others + RejectFormat = 4, + /// Reject all snapshots from the sender(s), try others + RejectSender = 5, +} + +impl Default for OfferSnapshot { + fn default() -> Self { + Self::Unknown + } +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::TryFrom; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseOfferSnapshot { + fn from(offer_snapshot: OfferSnapshot) -> Self { + Self { + result: offer_snapshot as i32, + } + } +} + +impl TryFrom for OfferSnapshot { + type Error = crate::Error; + + fn try_from(offer_snapshot: pb::ResponseOfferSnapshot) -> Result { + Ok(match offer_snapshot.result { + 0 => OfferSnapshot::Unknown, + 1 => OfferSnapshot::Accept, + 2 => OfferSnapshot::Abort, + 3 => OfferSnapshot::Reject, + 4 => OfferSnapshot::RejectFormat, + 5 => OfferSnapshot::RejectSender, + _ => Err("unknown offer snapshot result code")?, + }) + } +} + +impl Protobuf for OfferSnapshot {} diff --git a/tendermint/src/abci/response/query.rs b/tendermint/src/abci/response/query.rs new file mode 100644 index 000000000..9185f205e --- /dev/null +++ b/tendermint/src/abci/response/query.rs @@ -0,0 +1,85 @@ +use crate::prelude::*; + +use bytes::Bytes; + +/// XXX(hdevalence): hide merkle::proof and re-export its contents from merkle? +use crate::merkle::proof as merkle; + +#[doc = include_str!("../doc/response-query.md")] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +pub struct Query { + /// The response code for the query. + pub code: u32, + /// The output of the application's logger. + /// + /// **May be non-deterministic**. + pub log: String, + /// Additional information. + /// + /// **May be non-deterministic**. + pub info: String, + /// The index of the key in the tree. + pub index: i64, + /// The key of the matching data. + pub key: Bytes, + /// The value of the matching data. + pub value: Bytes, + /// Serialized proof for the value data, if requested, to be verified against + /// the app hash for the given `height`. + pub proof: Option, + /// The block height from which data was derived. + /// + /// Note that this is the height of the block containing the application's + /// Merkle root hash, which represents the state as it was after committing + /// the block at `height - 1`. + pub height: i64, + /// The namespace for the `code`. + pub codespace: String, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use core::convert::{TryFrom, TryInto}; +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::ResponseQuery { + fn from(query: Query) -> Self { + Self { + code: query.code, + log: query.log, + info: query.info, + index: query.index, + key: query.key, + value: query.value, + proof_ops: query.proof.map(Into::into), + height: query.height, + codespace: query.codespace, + } + } +} + +impl TryFrom for Query { + type Error = crate::Error; + + fn try_from(query: pb::ResponseQuery) -> Result { + Ok(Self { + code: query.code, + log: query.log, + info: query.info, + index: query.index, + key: query.key, + value: query.value, + proof: query.proof_ops.map(TryInto::try_into).transpose()?, + height: query.height, + codespace: query.codespace, + }) + } +} + +impl Protobuf for Query {} diff --git a/tendermint/src/abci/types.rs b/tendermint/src/abci/types.rs new file mode 100644 index 000000000..f77a36a51 --- /dev/null +++ b/tendermint/src/abci/types.rs @@ -0,0 +1,306 @@ +//! ABCI-specific data types used in requests and responses. +//! +//! These types have changes from the core data structures to better accomodate +//! ABCI applications. +//! +//! [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#data-types) + +use crate::prelude::*; + +use core::convert::{TryFrom, TryInto}; + +use bytes::Bytes; +use chrono::{DateTime, Utc}; + +use crate::PublicKey; + +/// A validator address with voting power. +/// +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#validator) +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Validator { + /// The validator's address (the first 20 bytes of `SHA256(public_key)`). + pub address: [u8; 20], + /// The voting power of the validator. + pub power: i64, +} + +/// A change to the validator set. +/// +/// Used to inform Tendermint of changes to the validator set. +/// +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#validatorupdate) +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ValidatorUpdate { + /// The validator's public key. + pub pub_key: PublicKey, + /// The validator's voting power. + pub power: i64, +} + +/// Information about a whether a validator signed the last block. +/// +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#voteinfo) +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct VoteInfo { + /// Identifies the validator. + pub validator: Validator, + /// Whether or not the validator signed the last block. + pub signed_last_block: bool, +} + +/// The possible kinds of [`Evidence`]. +/// +/// Note: the +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#evidencetype-2) +/// calls this `EvidenceType`, but we follow the Rust convention and name it `EvidenceKind` +/// to avoid confusion with Rust types. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[repr(i32)] +pub enum EvidenceKind { + /// Unknown evidence type (proto default value). + Unknown = 0, + /// Evidence that the validator voted for two different blocks in the same + /// round of the same height. + DuplicateVote = 1, + /// Evidence that a validator attacked a light client. + LightClientAttack = 2, +} + +/// Evidence of validator misbehavior. +/// +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#evidence) +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Evidence { + /// The kind of evidence. + /// + /// Note: this field is called `type` in the protobuf, but we call it `kind` + /// to avoid the Rust keyword. + pub kind: EvidenceKind, + /// The offending validator. + pub validator: Validator, + /// The height when the offense occurred. + pub height: i64, + /// The corresponding time when the offense occurred. + pub time: DateTime, + /// Total voting power of the validator set at `height`. + /// + /// This is included in case the ABCI application does not store historical + /// validators, cf. + /// [#4581](https://github.com/tendermint/tendermint/issues/4581) + pub total_voting_power: i64, +} + +/// Information on the last block commit. +/// +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#lastcommitinfo) +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct LastCommitInfo { + /// The commit round. + /// + /// Reflects the total number of rounds it took to come to consensus for the + /// current block. + pub round: i32, + /// The list of validator addresses in the last validator set, with their + /// voting power and whether or not they signed a vote. + pub votes: Vec, +} + +/// Used for state sync snapshots. +/// +/// When sent across the network, a `Snapshot` can be at most 4 MB. +/// +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#snapshot) +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Snapshot { + /// The height at which the snapshot was taken + pub height: u64, + /// The application-specific snapshot format identifier. + /// + /// This allows applications to version their snapshot data format and make + /// backwards-incompatible changes. Tendermint does not interpret this field. + pub format: u32, + /// The number of chunks in the snapshot. Must be at least 1. + pub chunks: u32, + /// An arbitrary snapshot hash. + /// + /// This hash must be equal only for identical snapshots across nodes. + /// Tendermint does not interpret the hash, only compares it with other + /// hashes. + pub hash: Bytes, + /// Arbitrary application metadata, e.g., chunk hashes or other verification data. + pub metadata: Bytes, +} + +// ============================================================================= +// Protobuf conversions +// ============================================================================= + +// XXX(hdevalence): these all use &'static str for now, this should be fixed +// to align with the crate's error-handling strategy. + +use tendermint_proto::abci as pb; +use tendermint_proto::Protobuf; + +impl From for pb::Validator { + fn from(v: Validator) -> Self { + Self { + address: Bytes::copy_from_slice(&v.address[..]), + power: v.power, + } + } +} + +impl TryFrom for Validator { + type Error = crate::Error; + + fn try_from(vu: pb::Validator) -> Result { + let address = if vu.address.len() == 20 { + let mut bytes = [0u8; 20]; + bytes.copy_from_slice(&vu.address); + bytes + } else { + return Err("wrong address length".into()); + }; + + Ok(Self { + address, + power: vu.power, + }) + } +} + +impl Protobuf for Validator {} + +impl From for pb::ValidatorUpdate { + fn from(vu: ValidatorUpdate) -> Self { + Self { + pub_key: Some(vu.pub_key.into()), + power: vu.power, + } + } +} + +impl TryFrom for ValidatorUpdate { + type Error = crate::Error; + + fn try_from(vu: pb::ValidatorUpdate) -> Result { + Ok(Self { + pub_key: vu.pub_key.ok_or("missing public key")?.try_into()?, + power: vu.power, + }) + } +} + +impl Protobuf for ValidatorUpdate {} + +impl From for pb::VoteInfo { + fn from(vi: VoteInfo) -> Self { + Self { + validator: Some(vi.validator.into()), + signed_last_block: vi.signed_last_block, + } + } +} + +impl TryFrom for VoteInfo { + type Error = crate::Error; + + fn try_from(vi: pb::VoteInfo) -> Result { + Ok(Self { + validator: vi.validator.ok_or("missing validator")?.try_into()?, + signed_last_block: vi.signed_last_block, + }) + } +} + +impl Protobuf for VoteInfo {} + +impl From for pb::Evidence { + fn from(evidence: Evidence) -> Self { + Self { + r#type: evidence.kind as i32, + validator: Some(evidence.validator.into()), + height: evidence.height, + time: Some(evidence.time.into()), + total_voting_power: evidence.total_voting_power, + } + } +} + +impl TryFrom for Evidence { + type Error = crate::Error; + + fn try_from(evidence: pb::Evidence) -> Result { + let kind = match evidence.r#type { + 0 => EvidenceKind::Unknown, + 1 => EvidenceKind::DuplicateVote, + 2 => EvidenceKind::LightClientAttack, + _ => Err("unknown evidence kind")?, + }; + + Ok(Self { + kind, + validator: evidence.validator.ok_or("missing validator")?.try_into()?, + height: evidence.height, + time: evidence.time.ok_or("missing time")?.into(), + total_voting_power: evidence.total_voting_power, + }) + } +} + +impl Protobuf for Evidence {} + +impl From for pb::LastCommitInfo { + fn from(lci: LastCommitInfo) -> Self { + Self { + round: lci.round, + votes: lci.votes.into_iter().map(Into::into).collect(), + } + } +} + +impl TryFrom for LastCommitInfo { + type Error = crate::Error; + + fn try_from(lci: pb::LastCommitInfo) -> Result { + Ok(Self { + round: lci.round, + votes: lci + .votes + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + }) + } +} + +impl Protobuf for LastCommitInfo {} + +impl From for pb::Snapshot { + fn from(snapshot: Snapshot) -> Self { + Self { + height: snapshot.height, + format: snapshot.format, + chunks: snapshot.chunks, + hash: snapshot.hash, + metadata: snapshot.metadata, + } + } +} + +impl TryFrom for Snapshot { + type Error = crate::Error; + + fn try_from(snapshot: pb::Snapshot) -> Result { + Ok(Self { + height: snapshot.height, + format: snapshot.format, + chunks: snapshot.chunks, + hash: snapshot.hash, + metadata: snapshot.metadata, + }) + } +} + +impl Protobuf for Snapshot {} diff --git a/tendermint/src/lib.rs b/tendermint/src/lib.rs index eef95f4e0..345a3a6eb 100644 --- a/tendermint/src/lib.rs +++ b/tendermint/src/lib.rs @@ -27,6 +27,7 @@ extern crate std; #[macro_use] pub mod error; +pub mod abci; pub mod account; pub mod block; pub mod chain; From 0dcdc6f08c9aca585eb22cd5a95f54b62b07cfa6 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 15 Nov 2021 16:13:07 -0800 Subject: [PATCH 16/20] tendermint: eliminate &'static str errors in ABCI domain types. --- tendermint/src/abci/event.rs | 3 - tendermint/src/abci/request.rs | 24 ++++---- .../src/abci/request/apply_snapshot_chunk.rs | 3 - tendermint/src/abci/request/begin_block.rs | 13 +++-- tendermint/src/abci/request/check_tx.rs | 5 +- tendermint/src/abci/request/deliver_tx.rs | 3 - tendermint/src/abci/request/echo.rs | 5 +- tendermint/src/abci/request/end_block.rs | 3 - tendermint/src/abci/request/info.rs | 5 +- tendermint/src/abci/request/init_chain.rs | 13 +++-- .../src/abci/request/load_snapshot_chunk.rs | 3 - tendermint/src/abci/request/offer_snapshot.rs | 5 +- tendermint/src/abci/request/query.rs | 3 - tendermint/src/abci/response.rs | 24 ++++---- .../src/abci/response/apply_snapshot_chunk.rs | 5 +- tendermint/src/abci/response/begin_block.rs | 6 +- tendermint/src/abci/response/check_tx.rs | 3 - tendermint/src/abci/response/commit.rs | 3 - tendermint/src/abci/response/deliver_tx.rs | 3 - tendermint/src/abci/response/echo.rs | 5 +- tendermint/src/abci/response/end_block.rs | 3 - tendermint/src/abci/response/exception.rs | 5 +- tendermint/src/abci/response/info.rs | 3 - tendermint/src/abci/response/init_chain.rs | 3 - .../src/abci/response/list_snapshots.rs | 3 - .../src/abci/response/load_snapshot_chunk.rs | 3 - .../src/abci/response/offer_snapshot.rs | 5 +- tendermint/src/abci/response/query.rs | 3 - tendermint/src/abci/types.rs | 34 +++++------ tendermint/src/error.rs | 57 ++++++++++++++----- 30 files changed, 104 insertions(+), 152 deletions(-) diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index 2dc5d7e14..76677572b 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -127,9 +127,6 @@ impl, V: Into> From<(K, V)> for EventAttribute { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::{TryFrom, TryInto}; use tendermint_proto::abci as pb; diff --git a/tendermint/src/abci/request.rs b/tendermint/src/abci/request.rs index fa8cdd809..f37397de3 100644 --- a/tendermint/src/abci/request.rs +++ b/tendermint/src/abci/request.rs @@ -24,6 +24,7 @@ use crate::prelude::*; use core::convert::{TryFrom, TryInto}; use super::MethodKind; +use crate::Error; // bring into scope for doc links #[allow(unused)] @@ -137,7 +138,7 @@ impl From for Request { } impl TryFrom for ConsensusRequest { - type Error = &'static str; + type Error = Error; fn try_from(req: Request) -> Result { match req { Request::InitChain(x) => Ok(Self::InitChain(x)), @@ -145,7 +146,7 @@ impl TryFrom for ConsensusRequest { Request::DeliverTx(x) => Ok(Self::DeliverTx(x)), Request::EndBlock(x) => Ok(Self::EndBlock(x)), Request::Commit => Ok(Self::Commit), - _ => Err("wrong request type"), + _ => Err(Error::invalid_abci_request_type()), } } } @@ -166,11 +167,11 @@ impl From for Request { } impl TryFrom for MempoolRequest { - type Error = &'static str; + type Error = Error; fn try_from(req: Request) -> Result { match req { Request::CheckTx(x) => Ok(Self::CheckTx(x)), - _ => Err("wrong request type"), + _ => Err(Error::invalid_abci_request_type()), } } } @@ -197,13 +198,13 @@ impl From for Request { } impl TryFrom for InfoRequest { - type Error = &'static str; + type Error = Error; fn try_from(req: Request) -> Result { match req { Request::Info(x) => Ok(Self::Info(x)), Request::Query(x) => Ok(Self::Query(x)), Request::Echo(x) => Ok(Self::Echo(x)), - _ => Err("wrong request type"), + _ => Err(Error::invalid_abci_request_type()), } } } @@ -233,14 +234,14 @@ impl From for Request { } impl TryFrom for SnapshotRequest { - type Error = &'static str; + type Error = Error; fn try_from(req: Request) -> Result { match req { Request::ListSnapshots => Ok(Self::ListSnapshots), Request::OfferSnapshot(x) => Ok(Self::OfferSnapshot(x)), Request::LoadSnapshotChunk(x) => Ok(Self::LoadSnapshotChunk(x)), Request::ApplySnapshotChunk(x) => Ok(Self::ApplySnapshotChunk(x)), - _ => Err("wrong request type"), + _ => Err(Error::invalid_abci_request_type()), } } } @@ -249,9 +250,6 @@ impl TryFrom for SnapshotRequest { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -279,7 +277,7 @@ impl From for pb::Request { } impl TryFrom for Request { - type Error = crate::Error; + type Error = Error; fn try_from(request: pb::Request) -> Result { use pb::request::Value; @@ -298,7 +296,7 @@ impl TryFrom for Request { Some(Value::OfferSnapshot(x)) => Ok(Request::OfferSnapshot(x.try_into()?)), Some(Value::LoadSnapshotChunk(x)) => Ok(Request::LoadSnapshotChunk(x.try_into()?)), Some(Value::ApplySnapshotChunk(x)) => Ok(Request::ApplySnapshotChunk(x.try_into()?)), - None => Err("no request in proto".into()), + None => Err(crate::Error::missing_data()), } } } diff --git a/tendermint/src/abci/request/apply_snapshot_chunk.rs b/tendermint/src/abci/request/apply_snapshot_chunk.rs index 48fc4b7aa..aca95daf2 100644 --- a/tendermint/src/abci/request/apply_snapshot_chunk.rs +++ b/tendermint/src/abci/request/apply_snapshot_chunk.rs @@ -41,9 +41,6 @@ pub struct ApplySnapshotChunk { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/request/begin_block.rs b/tendermint/src/abci/request/begin_block.rs index 0d9ac4b37..814038b7d 100644 --- a/tendermint/src/abci/request/begin_block.rs +++ b/tendermint/src/abci/request/begin_block.rs @@ -5,6 +5,7 @@ use bytes::Bytes; use crate::block; use super::super::types::{Evidence, LastCommitInfo}; +use crate::Error; // bring into scope for doc links #[allow(unused)] @@ -32,9 +33,6 @@ pub struct BeginBlock { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::{TryFrom, TryInto}; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -55,15 +53,18 @@ impl From for pb::RequestBeginBlock { } impl TryFrom for BeginBlock { - type Error = crate::Error; + type Error = Error; fn try_from(begin_block: pb::RequestBeginBlock) -> Result { Ok(Self { hash: begin_block.hash, - header: begin_block.header.ok_or("missing header")?.try_into()?, + header: begin_block + .header + .ok_or(Error::missing_header())? + .try_into()?, last_commit_info: begin_block .last_commit_info - .ok_or("missing last commit info")? + .ok_or(Error::missing_last_commit_info())? .try_into()?, byzantine_validators: begin_block .byzantine_validators diff --git a/tendermint/src/abci/request/check_tx.rs b/tendermint/src/abci/request/check_tx.rs index 55c7f6832..0a82dc030 100644 --- a/tendermint/src/abci/request/check_tx.rs +++ b/tendermint/src/abci/request/check_tx.rs @@ -39,9 +39,6 @@ impl Default for CheckTxKind { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -62,7 +59,7 @@ impl TryFrom for CheckTx { let kind = match check_tx.r#type { 0 => CheckTxKind::New, 1 => CheckTxKind::Recheck, - _ => Err("unknown checktx type")?, + _ => Err(crate::Error::unsupported_check_tx_type())?, }; Ok(Self { tx: check_tx.tx, diff --git a/tendermint/src/abci/request/deliver_tx.rs b/tendermint/src/abci/request/deliver_tx.rs index 0b4c0907d..456e45733 100644 --- a/tendermint/src/abci/request/deliver_tx.rs +++ b/tendermint/src/abci/request/deliver_tx.rs @@ -13,9 +13,6 @@ pub struct DeliverTx { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/request/echo.rs b/tendermint/src/abci/request/echo.rs index 13580398b..7da97b61a 100644 --- a/tendermint/src/abci/request/echo.rs +++ b/tendermint/src/abci/request/echo.rs @@ -11,9 +11,6 @@ pub struct Echo { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -27,7 +24,7 @@ impl From for pb::RequestEcho { } impl TryFrom for Echo { - type Error = &'static str; + type Error = crate::Error; fn try_from(echo: pb::RequestEcho) -> Result { Ok(Self { diff --git a/tendermint/src/abci/request/end_block.rs b/tendermint/src/abci/request/end_block.rs index 985153403..3d72341ae 100644 --- a/tendermint/src/abci/request/end_block.rs +++ b/tendermint/src/abci/request/end_block.rs @@ -11,9 +11,6 @@ pub struct EndBlock { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/request/info.rs b/tendermint/src/abci/request/info.rs index 3aa8e893c..a110337fd 100644 --- a/tendermint/src/abci/request/info.rs +++ b/tendermint/src/abci/request/info.rs @@ -17,9 +17,6 @@ pub struct Info { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -36,7 +33,7 @@ impl From for pb::RequestInfo { } impl TryFrom for Info { - type Error = &'static str; + type Error = crate::Error; fn try_from(info: pb::RequestInfo) -> Result { Ok(Self { diff --git a/tendermint/src/abci/request/init_chain.rs b/tendermint/src/abci/request/init_chain.rs index 4a2e86c63..fb0077a66 100644 --- a/tendermint/src/abci/request/init_chain.rs +++ b/tendermint/src/abci/request/init_chain.rs @@ -28,9 +28,7 @@ pub struct InitChain { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - +use crate::Error; use core::convert::{TryFrom, TryInto}; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -49,15 +47,18 @@ impl From for pb::RequestInitChain { } impl TryFrom for InitChain { - type Error = crate::Error; + type Error = Error; fn try_from(init_chain: pb::RequestInitChain) -> Result { Ok(Self { - time: init_chain.time.ok_or("missing genesis time")?.try_into()?, + time: init_chain + .time + .ok_or(Error::missing_genesis_time())? + .try_into()?, chain_id: init_chain.chain_id, consensus_params: init_chain .consensus_params - .ok_or("missing consensus params")? + .ok_or(Error::missing_consensus_params())? .try_into()?, validators: init_chain .validators diff --git a/tendermint/src/abci/request/load_snapshot_chunk.rs b/tendermint/src/abci/request/load_snapshot_chunk.rs index 25229f600..25f163067 100644 --- a/tendermint/src/abci/request/load_snapshot_chunk.rs +++ b/tendermint/src/abci/request/load_snapshot_chunk.rs @@ -15,9 +15,6 @@ pub struct LoadSnapshotChunk { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/request/offer_snapshot.rs b/tendermint/src/abci/request/offer_snapshot.rs index 57d7c060c..2c959e694 100644 --- a/tendermint/src/abci/request/offer_snapshot.rs +++ b/tendermint/src/abci/request/offer_snapshot.rs @@ -22,9 +22,6 @@ pub struct OfferSnapshot { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::{TryFrom, TryInto}; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -45,7 +42,7 @@ impl TryFrom for OfferSnapshot { Ok(Self { snapshot: offer_snapshot .snapshot - .ok_or("missing snapshot")? + .ok_or(crate::Error::missing_data())? .try_into()?, app_hash: offer_snapshot.app_hash, }) diff --git a/tendermint/src/abci/request/query.rs b/tendermint/src/abci/request/query.rs index e567c5865..46d35cdd8 100644 --- a/tendermint/src/abci/request/query.rs +++ b/tendermint/src/abci/request/query.rs @@ -32,9 +32,6 @@ pub struct Query { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/response.rs b/tendermint/src/abci/response.rs index 33c4080d8..eed823f9b 100644 --- a/tendermint/src/abci/response.rs +++ b/tendermint/src/abci/response.rs @@ -23,6 +23,7 @@ use crate::prelude::*; use core::convert::{TryFrom, TryInto}; +use crate::Error; // bring into scope for doc links #[allow(unused)] use super::types::Snapshot; @@ -120,7 +121,7 @@ impl From for Response { } impl TryFrom for ConsensusResponse { - type Error = &'static str; + type Error = Error; fn try_from(req: Response) -> Result { match req { Response::InitChain(x) => Ok(Self::InitChain(x)), @@ -128,7 +129,7 @@ impl TryFrom for ConsensusResponse { Response::DeliverTx(x) => Ok(Self::DeliverTx(x)), Response::EndBlock(x) => Ok(Self::EndBlock(x)), Response::Commit(x) => Ok(Self::Commit(x)), - _ => Err("wrong request type"), + _ => Err(Error::invalid_abci_response_type()), } } } @@ -149,11 +150,11 @@ impl From for Response { } impl TryFrom for MempoolResponse { - type Error = &'static str; + type Error = Error; fn try_from(req: Response) -> Result { match req { Response::CheckTx(x) => Ok(Self::CheckTx(x)), - _ => Err("wrong request type"), + _ => Err(Error::invalid_abci_response_type()), } } } @@ -180,13 +181,13 @@ impl From for Response { } impl TryFrom for InfoResponse { - type Error = &'static str; + type Error = Error; fn try_from(req: Response) -> Result { match req { Response::Echo(x) => Ok(Self::Echo(x)), Response::Info(x) => Ok(Self::Info(x)), Response::Query(x) => Ok(Self::Query(x)), - _ => Err("wrong request type"), + _ => Err(Error::invalid_abci_response_type()), } } } @@ -216,14 +217,14 @@ impl From for Response { } impl TryFrom for SnapshotResponse { - type Error = &'static str; + type Error = Error; fn try_from(req: Response) -> Result { match req { Response::ListSnapshots(x) => Ok(Self::ListSnapshots(x)), Response::OfferSnapshot(x) => Ok(Self::OfferSnapshot(x)), Response::LoadSnapshotChunk(x) => Ok(Self::LoadSnapshotChunk(x)), Response::ApplySnapshotChunk(x) => Ok(Self::ApplySnapshotChunk(x)), - _ => Err("wrong request type"), + _ => Err(Error::invalid_abci_response_type()), } } } @@ -232,9 +233,6 @@ impl TryFrom for SnapshotResponse { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -263,7 +261,7 @@ impl From for pb::Response { } impl TryFrom for Response { - type Error = crate::Error; + type Error = Error; fn try_from(response: pb::Response) -> Result { use pb::response::Value; @@ -283,7 +281,7 @@ impl TryFrom for Response { Some(Value::OfferSnapshot(x)) => Ok(Response::OfferSnapshot(x.try_into()?)), Some(Value::LoadSnapshotChunk(x)) => Ok(Response::LoadSnapshotChunk(x.try_into()?)), Some(Value::ApplySnapshotChunk(x)) => Ok(Response::ApplySnapshotChunk(x.try_into()?)), - None => Err("no response in proto".into()), + None => Err(crate::Error::missing_data()), } } } diff --git a/tendermint/src/abci/response/apply_snapshot_chunk.rs b/tendermint/src/abci/response/apply_snapshot_chunk.rs index 31f165b59..fc8eef903 100644 --- a/tendermint/src/abci/response/apply_snapshot_chunk.rs +++ b/tendermint/src/abci/response/apply_snapshot_chunk.rs @@ -50,9 +50,6 @@ impl Default for ApplySnapshotChunkResult { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -78,7 +75,7 @@ impl TryFrom for ApplySnapshotChunk { 3 => ApplySnapshotChunkResult::Retry, 4 => ApplySnapshotChunkResult::RetrySnapshot, 5 => ApplySnapshotChunkResult::RejectSnapshot, - _ => Err("unknown snapshot chunk result")?, + _ => Err(crate::Error::unsupported_apply_snapshot_chunk_result())?, }; Ok(Self { result, diff --git a/tendermint/src/abci/response/begin_block.rs b/tendermint/src/abci/response/begin_block.rs index dd39f9ec1..2335becfb 100644 --- a/tendermint/src/abci/response/begin_block.rs +++ b/tendermint/src/abci/response/begin_block.rs @@ -1,7 +1,6 @@ use crate::prelude::*; -// XXX(hdevalence): fix this import -use super::super::event::Event; +use super::super::Event; #[doc = include_str!("../doc/response-beginblock.md")] #[derive(Clone, PartialEq, Eq, Debug, Default)] @@ -14,9 +13,6 @@ pub struct BeginBlock { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::{TryFrom, TryInto}; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/response/check_tx.rs b/tendermint/src/abci/response/check_tx.rs index 659aa245f..500b9699e 100644 --- a/tendermint/src/abci/response/check_tx.rs +++ b/tendermint/src/abci/response/check_tx.rs @@ -44,9 +44,6 @@ pub struct CheckTx { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::{TryFrom, TryInto}; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/response/commit.rs b/tendermint/src/abci/response/commit.rs index cfdfa3036..a5163c757 100644 --- a/tendermint/src/abci/response/commit.rs +++ b/tendermint/src/abci/response/commit.rs @@ -18,9 +18,6 @@ pub struct Commit { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/response/deliver_tx.rs b/tendermint/src/abci/response/deliver_tx.rs index ed3fd663d..271f82457 100644 --- a/tendermint/src/abci/response/deliver_tx.rs +++ b/tendermint/src/abci/response/deliver_tx.rs @@ -37,9 +37,6 @@ pub struct DeliverTx { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::{TryFrom, TryInto}; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/response/echo.rs b/tendermint/src/abci/response/echo.rs index 20d991a1d..03cdcb185 100644 --- a/tendermint/src/abci/response/echo.rs +++ b/tendermint/src/abci/response/echo.rs @@ -11,9 +11,6 @@ pub struct Echo { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -27,7 +24,7 @@ impl From for pb::ResponseEcho { } impl TryFrom for Echo { - type Error = &'static str; + type Error = crate::Error; fn try_from(echo: pb::ResponseEcho) -> Result { Ok(Self { diff --git a/tendermint/src/abci/response/end_block.rs b/tendermint/src/abci/response/end_block.rs index bd1fe26ad..32d851aca 100644 --- a/tendermint/src/abci/response/end_block.rs +++ b/tendermint/src/abci/response/end_block.rs @@ -19,9 +19,6 @@ pub struct EndBlock { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::{TryFrom, TryInto}; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/response/exception.rs b/tendermint/src/abci/response/exception.rs index 9f4a2968c..cbb607c5d 100644 --- a/tendermint/src/abci/response/exception.rs +++ b/tendermint/src/abci/response/exception.rs @@ -11,9 +11,6 @@ pub struct Exception { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -27,7 +24,7 @@ impl From for pb::ResponseException { } impl TryFrom for Exception { - type Error = &'static str; + type Error = crate::Error; fn try_from(exception: pb::ResponseException) -> Result { Ok(Self { diff --git a/tendermint/src/abci/response/info.rs b/tendermint/src/abci/response/info.rs index aa3f798e7..1fcd37cbc 100644 --- a/tendermint/src/abci/response/info.rs +++ b/tendermint/src/abci/response/info.rs @@ -22,9 +22,6 @@ pub struct Info { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/response/init_chain.rs b/tendermint/src/abci/response/init_chain.rs index 30f037587..9e218a62e 100644 --- a/tendermint/src/abci/response/init_chain.rs +++ b/tendermint/src/abci/response/init_chain.rs @@ -26,9 +26,6 @@ pub struct InitChain { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::{TryFrom, TryInto}; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/response/list_snapshots.rs b/tendermint/src/abci/response/list_snapshots.rs index 79511f08a..ef5353f73 100644 --- a/tendermint/src/abci/response/list_snapshots.rs +++ b/tendermint/src/abci/response/list_snapshots.rs @@ -13,9 +13,6 @@ pub struct ListSnapshots { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::{TryFrom, TryInto}; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/response/load_snapshot_chunk.rs b/tendermint/src/abci/response/load_snapshot_chunk.rs index c86ad8887..406a4470a 100644 --- a/tendermint/src/abci/response/load_snapshot_chunk.rs +++ b/tendermint/src/abci/response/load_snapshot_chunk.rs @@ -16,9 +16,6 @@ pub struct LoadSnapshotChunk { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/response/offer_snapshot.rs b/tendermint/src/abci/response/offer_snapshot.rs index f84fc9b9d..a59ba9fac 100644 --- a/tendermint/src/abci/response/offer_snapshot.rs +++ b/tendermint/src/abci/response/offer_snapshot.rs @@ -32,9 +32,6 @@ impl Default for OfferSnapshot { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::TryFrom; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -58,7 +55,7 @@ impl TryFrom for OfferSnapshot { 3 => OfferSnapshot::Reject, 4 => OfferSnapshot::RejectFormat, 5 => OfferSnapshot::RejectSender, - _ => Err("unknown offer snapshot result code")?, + _ => Err(crate::Error::unsupported_offer_snapshot_chunk_result())?, }) } } diff --git a/tendermint/src/abci/response/query.rs b/tendermint/src/abci/response/query.rs index 9185f205e..642a6c98c 100644 --- a/tendermint/src/abci/response/query.rs +++ b/tendermint/src/abci/response/query.rs @@ -41,9 +41,6 @@ pub struct Query { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use core::convert::{TryFrom, TryInto}; use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; diff --git a/tendermint/src/abci/types.rs b/tendermint/src/abci/types.rs index f77a36a51..6cd8cd91b 100644 --- a/tendermint/src/abci/types.rs +++ b/tendermint/src/abci/types.rs @@ -12,7 +12,7 @@ use core::convert::{TryFrom, TryInto}; use bytes::Bytes; use chrono::{DateTime, Utc}; -use crate::PublicKey; +use crate::{Error, PublicKey}; /// A validator address with voting power. /// @@ -136,9 +136,6 @@ pub struct Snapshot { // Protobuf conversions // ============================================================================= -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - use tendermint_proto::abci as pb; use tendermint_proto::Protobuf; @@ -152,7 +149,7 @@ impl From for pb::Validator { } impl TryFrom for Validator { - type Error = crate::Error; + type Error = Error; fn try_from(vu: pb::Validator) -> Result { let address = if vu.address.len() == 20 { @@ -160,7 +157,7 @@ impl TryFrom for Validator { bytes.copy_from_slice(&vu.address); bytes } else { - return Err("wrong address length".into()); + return Err(Error::invalid_account_id_length()); }; Ok(Self { @@ -182,11 +179,11 @@ impl From for pb::ValidatorUpdate { } impl TryFrom for ValidatorUpdate { - type Error = crate::Error; + type Error = Error; fn try_from(vu: pb::ValidatorUpdate) -> Result { Ok(Self { - pub_key: vu.pub_key.ok_or("missing public key")?.try_into()?, + pub_key: vu.pub_key.ok_or(Error::missing_public_key())?.try_into()?, power: vu.power, }) } @@ -204,11 +201,11 @@ impl From for pb::VoteInfo { } impl TryFrom for VoteInfo { - type Error = crate::Error; + type Error = Error; fn try_from(vi: pb::VoteInfo) -> Result { Ok(Self { - validator: vi.validator.ok_or("missing validator")?.try_into()?, + validator: vi.validator.ok_or(Error::missing_validator())?.try_into()?, signed_last_block: vi.signed_last_block, }) } @@ -229,21 +226,24 @@ impl From for pb::Evidence { } impl TryFrom for Evidence { - type Error = crate::Error; + type Error = Error; fn try_from(evidence: pb::Evidence) -> Result { let kind = match evidence.r#type { 0 => EvidenceKind::Unknown, 1 => EvidenceKind::DuplicateVote, 2 => EvidenceKind::LightClientAttack, - _ => Err("unknown evidence kind")?, + _ => Err(Error::invalid_evidence())?, }; Ok(Self { kind, - validator: evidence.validator.ok_or("missing validator")?.try_into()?, - height: evidence.height, - time: evidence.time.ok_or("missing time")?.into(), + validator: evidence + .validator + .ok_or(Error::missing_validator())? + .try_into()?, + height: evidence.height.try_into()?, + time: evidence.time.ok_or(Error::missing_timestamp())?.into(), total_voting_power: evidence.total_voting_power, }) } @@ -261,7 +261,7 @@ impl From for pb::LastCommitInfo { } impl TryFrom for LastCommitInfo { - type Error = crate::Error; + type Error = Error; fn try_from(lci: pb::LastCommitInfo) -> Result { Ok(Self { @@ -290,7 +290,7 @@ impl From for pb::Snapshot { } impl TryFrom for Snapshot { - type Error = crate::Error; + type Error = Error; fn try_from(snapshot: pb::Snapshot) -> Result { Ok(Self { diff --git a/tendermint/src/error.rs b/tendermint/src/error.rs index e3506dd67..62eed778e 100644 --- a/tendermint/src/error.rs +++ b/tendermint/src/error.rs @@ -112,6 +112,27 @@ define_error! { MissingTimestamp |_| { format_args!("missing timestamp field") }, + MissingVersion + |_| { format_args!("missing version") }, + + MissingMaxAgeDuration + |_| { format_args!("missing max_age_duration") }, + + MissingPublicKey + |_| { format_args!("missing public key") }, + + MissingValidator + |_| { format_args!("missing validator") }, + + MissingLastCommitInfo + |_| { format_args!("missing last commit info") }, + + MissingGenesisTime + |_| { format_args!("missing genesis time") }, + + MissingConsensusParams + |_| { format_args!("missing consensus params") }, + InvalidTimestamp { reason: String } | e | { format_args!("invalid timestamp: {}", e.reason) }, @@ -120,9 +141,6 @@ define_error! { { reason: String } | e | { format_args!("invalid block: {}", e.reason) }, - MissingVersion - |_| { format_args!("missing version") }, - InvalidFirstHeader |_| { format_args!("last_block_id is not null on first height") }, @@ -139,6 +157,18 @@ define_error! { InvalidEvidence |_| { format_args!("invalid evidence") }, + InvalidValidatorParams + |_| { format_args!("invalid validator parameters") }, + + InvalidVersionParams + |_| { format_args!("invalid version parameters") }, + + InvalidAbciRequestType + |_| { format_args!("invalid ABCI request type") }, + + InvalidAbciResponseType + |_| { format_args!("invalid ABCI response type") }, + BlockIdFlag |_| { format_args!("invalid block id flag") }, @@ -149,26 +179,23 @@ define_error! { UnsupportedKeyType |_| { format_args!("unsupported key type" ) }, - RawVotingPowerMismatch - { raw: vote::Power, computed: vote::Power } - |e| { format_args!("mismatch between raw voting ({0:?}) and computed one ({1:?})", e.raw, e.computed) }, + UnsupportedCheckTxType + |_| { format_args!("unsupported CheckTx type" ) }, - MissingPublicKey - |_| { format_args!("missing public key") }, + UnsupportedApplySnapshotChunkResult + |_| { format_args!("unsupported ApplySnapshotChunkResult type" ) }, - InvalidValidatorParams - |_| { format_args!("invalid validator parameters") }, + UnsupportedOfferSnapshotChunkResult + |_| { format_args!("unsupported OfferSnapshotChunkResult type" ) }, - InvalidVersionParams - |_| { format_args!("invalid version parameters") }, + RawVotingPowerMismatch + { raw: vote::Power, computed: vote::Power } + |e| { format_args!("mismatch between raw voting ({0:?}) and computed one ({1:?})", e.raw, e.computed) }, NegativeMaxAgeNum [ DisplayOnly ] |_| { format_args!("negative max_age_num_blocks") }, - MissingMaxAgeDuration - |_| { format_args!("missing max_age_duration") }, - ProposerNotFound { account: account::Id } |e| { format_args!("proposer with address '{0}' no found in validator set", e.account) }, From 4dbbbd0f54a6115cc22b561bb88b67eed3220ca7 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 15 Nov 2021 14:54:25 -0800 Subject: [PATCH 17/20] Merge `abci::params::ConsensusParams` with `consensus::Params`. The code in the `abci` module had more complete documentation from the ABCI docs, so I copied it onto the existing structure. --- tendermint/src/abci.rs | 1 - tendermint/src/abci/params.rs | 219 --------------------- tendermint/src/abci/request/init_chain.rs | 8 +- tendermint/src/abci/response/end_block.rs | 6 +- tendermint/src/abci/response/init_chain.rs | 8 +- tendermint/src/consensus/params.rs | 25 ++- tendermint/src/evidence.rs | 17 +- 7 files changed, 39 insertions(+), 245 deletions(-) delete mode 100644 tendermint/src/abci/params.rs diff --git a/tendermint/src/abci.rs b/tendermint/src/abci.rs index c026016ed..cb039806d 100644 --- a/tendermint/src/abci.rs +++ b/tendermint/src/abci.rs @@ -39,7 +39,6 @@ mod event; mod kind; -pub mod params; pub mod request; pub mod response; pub mod types; diff --git a/tendermint/src/abci/params.rs b/tendermint/src/abci/params.rs deleted file mode 100644 index f8e85e911..000000000 --- a/tendermint/src/abci/params.rs +++ /dev/null @@ -1,219 +0,0 @@ -//! Consensus-relevant parameters that can be adjusted by the ABCI app. - -use crate::prelude::*; - -use chrono::Duration; -use core::convert::{TryFrom, TryInto}; - -/// All consensus-relevant parameters that can be adjusted by the ABCI app. -/// -/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#consensusparams) -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct ConsensusParams { - /// Parameters limiting the size of a block and time between consecutive blocks. - pub block: BlockParams, - /// Parameters limiting the validity of evidence of byzantine behaviour. - pub evidence: EvidenceParams, - /// Parameters limiting the types of public keys validators can use. - pub validator: ValidatorParams, - /// The ABCI application version. - pub version: VersionParams, -} -/// BlockParams contains limits on the block size. -/// -/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#blockparams) -/// -/// XXX(hdevalence): this isn't ABCI-specific, should it live here? -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct BlockParams { - /// Max block size, in bytes. - pub max_bytes: i64, - /// Max sum of `gas_wanted` in a proposed block. - /// - /// Note: blocks that violate this may be committed if there are Byzantine - /// proposers. It's the application's responsibility to handle this when - /// processing a block. - pub max_gas: i64, -} - -/// EvidenceParams determine how we handle evidence of malfeasance. -/// -/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#evidenceparams) -/// -/// XXX(hdevalence): this isn't ABCI-specific, should it live here? -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct EvidenceParams { - /// Max age of evidence, in blocks. - pub max_age_num_blocks: i64, - /// Max age of evidence, in time. - /// - /// It should correspond with an app's "unbonding period" or other similar - /// mechanism for handling [Nothing-At-Stake attacks][nas]. - /// - /// [nas]: https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed - pub max_age_duration: Duration, - /// This sets the maximum size of total evidence in bytes that can be - /// committed in a single block, and should fall comfortably under the max - /// block bytes. The default is 1048576 or 1MB. - pub max_bytes: i64, -} - -/// ValidatorParams restrict the public key types validators can use. -/// -/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#validatorparams) -/// -/// XXX(hdevalence): this isn't ABCI-specific, should it live here? -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct ValidatorParams { - /// List of accepted public key types. - pub pub_key_types: Vec, -} - -/// (No description) -/// -/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#versionparams) -/// -/// XXX(hdevalence): this isn't ABCI-specific, should it live here? -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct VersionParams { - /// The ABCI application version. - pub app_version: u64, -} - -// ============================================================================= -// Protobuf conversions -// ============================================================================= - -// XXX(hdevalence): these all use &'static str for now, this should be fixed -// to align with the crate's error-handling strategy. - -use tendermint_proto::types as pb; -use tendermint_proto::Protobuf; - -impl From for pb::ConsensusParams { - fn from(params: ConsensusParams) -> Self { - Self { - block: Some(params.block.into()), - evidence: Some(params.evidence.into()), - validator: Some(params.validator.into()), - version: Some(params.version.into()), - } - } -} - -impl TryFrom for ConsensusParams { - type Error = crate::Error; - - fn try_from(params: pb::ConsensusParams) -> Result { - Ok(Self { - block: params.block.ok_or("missing block params")?.try_into()?, - evidence: params - .evidence - .ok_or("missing evidence params")? - .try_into()?, - validator: params - .validator - .ok_or("missing validator params")? - .try_into()?, - version: params.version.ok_or("missing version params")?.try_into()?, - }) - } -} - -impl Protobuf for ConsensusParams {} - -impl From for pb::BlockParams { - fn from(params: BlockParams) -> Self { - Self { - max_bytes: params.max_bytes, - max_gas: params.max_gas, - } - } -} - -impl TryFrom for BlockParams { - type Error = crate::Error; - - fn try_from(params: pb::BlockParams) -> Result { - if params.max_bytes == 0 { - Err("BlockParams::max_bytes must be greater than 0")? - } - if params.max_gas < -1 { - Err("BlockParams::max_gas must be greater than or equal to -1")? - } - - Ok(Self { - max_bytes: params.max_bytes, - max_gas: params.max_gas, - }) - } -} - -impl Protobuf for BlockParams {} - -impl From for pb::EvidenceParams { - fn from(params: EvidenceParams) -> Self { - Self { - max_age_num_blocks: params.max_age_num_blocks, - max_age_duration: Some(params.max_age_duration.into()), - max_bytes: params.max_bytes, - } - } -} - -impl TryFrom for EvidenceParams { - type Error = crate::Error; - - fn try_from(params: pb::EvidenceParams) -> Result { - Ok(Self { - max_age_num_blocks: params.max_age_num_blocks, - max_age_duration: params - .max_age_duration - .ok_or("missing max age duration")? - .into(), - max_bytes: params.max_bytes, - }) - } -} - -impl Protobuf for EvidenceParams {} - -impl From for pb::ValidatorParams { - fn from(params: ValidatorParams) -> Self { - Self { - pub_key_types: params.pub_key_types, - } - } -} - -impl TryFrom for ValidatorParams { - type Error = crate::Error; - - fn try_from(params: pb::ValidatorParams) -> Result { - Ok(Self { - pub_key_types: params.pub_key_types, - }) - } -} - -impl Protobuf for ValidatorParams {} - -impl From for pb::VersionParams { - fn from(params: VersionParams) -> Self { - Self { - app_version: params.app_version, - } - } -} - -impl TryFrom for VersionParams { - type Error = crate::Error; - - fn try_from(params: pb::VersionParams) -> Result { - Ok(Self { - app_version: params.app_version, - }) - } -} - -impl Protobuf for VersionParams {} diff --git a/tendermint/src/abci/request/init_chain.rs b/tendermint/src/abci/request/init_chain.rs index fb0077a66..7acc938f4 100644 --- a/tendermint/src/abci/request/init_chain.rs +++ b/tendermint/src/abci/request/init_chain.rs @@ -1,9 +1,9 @@ -use crate::prelude::*; - use bytes::Bytes; use chrono::{DateTime, Utc}; -use super::super::{params::ConsensusParams, types::ValidatorUpdate}; +use crate::{consensus, prelude::*}; + +use super::super::types::ValidatorUpdate; /// Called on genesis to initialize chain state. /// @@ -15,7 +15,7 @@ pub struct InitChain { /// The ID of the blockchain. pub chain_id: String, /// Initial consensus-critical parameters. - pub consensus_params: ConsensusParams, + pub consensus_params: consensus::Params, /// Initial genesis validators, sorted by voting power. pub validators: Vec, /// Serialized JSON bytes containing the initial application state. diff --git a/tendermint/src/abci/response/end_block.rs b/tendermint/src/abci/response/end_block.rs index 32d851aca..521a44978 100644 --- a/tendermint/src/abci/response/end_block.rs +++ b/tendermint/src/abci/response/end_block.rs @@ -1,6 +1,6 @@ -use crate::prelude::*; +use crate::{consensus, prelude::*}; -use super::super::{params::ConsensusParams, types::ValidatorUpdate, Event}; +use super::super::{types::ValidatorUpdate, Event}; #[doc = include_str!("../doc/response-endblock.md")] #[derive(Clone, PartialEq, Eq, Debug, Default)] @@ -10,7 +10,7 @@ pub struct EndBlock { /// Setting the voting power to 0 removes a validator. pub validator_updates: Vec, /// Changes to consensus parameters (optional). - pub consensus_param_updates: Option, + pub consensus_param_updates: Option, /// Events that occurred while ending the block. pub events: Vec, } diff --git a/tendermint/src/abci/response/init_chain.rs b/tendermint/src/abci/response/init_chain.rs index 9e218a62e..6d443b71d 100644 --- a/tendermint/src/abci/response/init_chain.rs +++ b/tendermint/src/abci/response/init_chain.rs @@ -1,14 +1,14 @@ -use crate::prelude::*; - use bytes::Bytes; -use super::super::{params::ConsensusParams, types::ValidatorUpdate}; +use crate::{consensus, prelude::*}; + +use super::super::types::ValidatorUpdate; #[doc = include_str!("../doc/response-initchain.md")] #[derive(Clone, PartialEq, Eq, Debug, Default)] pub struct InitChain { /// Initial consensus-critical parameters (optional). - pub consensus_params: Option, + pub consensus_params: Option, /// Initial validator set (optional). /// /// If this list is empty, the initial validator set will be the one given in diff --git a/tendermint/src/consensus/params.rs b/tendermint/src/consensus/params.rs index af42fd838..fbc73a6f1 100644 --- a/tendermint/src/consensus/params.rs +++ b/tendermint/src/consensus/params.rs @@ -10,18 +10,18 @@ use tendermint_proto::types::ValidatorParams as RawValidatorParams; use tendermint_proto::types::VersionParams as RawVersionParams; use tendermint_proto::Protobuf; -/// Tendermint consensus parameters +/// All consensus-relevant parameters that can be adjusted by the ABCI app. +/// +/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#consensusparams) #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] pub struct Params { - /// Block size parameters + /// Parameters limiting the size of a block and time between consecutive blocks. pub block: block::Size, - - /// Evidence parameters + /// Parameters limiting the validity of evidence of byzantine behaviour. pub evidence: evidence::Params, - - /// Validator parameters + /// Parameters limiting the types of public keys validators can use. pub validator: ValidatorParams, - + /// The ABCI application version. /// Version parameters #[serde(skip)] // Todo: FIXME kvstore /genesis returns '{}' instead of '{app_version: "0"}' pub version: Option, @@ -62,10 +62,12 @@ impl From for RawParams { } } -/// Validator consensus parameters +/// ValidatorParams restrict the public key types validators can use. +/// +/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#validatorparams) #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] pub struct ValidatorParams { - /// Allowed algorithms for validator signing + /// List of accepted public key types. pub pub_key_types: Vec, } @@ -108,10 +110,13 @@ impl From for RawValidatorParams { } /// Version Parameters +/// +/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#versionparams) #[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq, Default)] pub struct VersionParams { + /// The ABCI application version. #[serde(with = "crate::serializers::from_str")] - app_version: u64, + pub app_version: u64, } impl Protobuf for VersionParams {} diff --git a/tendermint/src/evidence.rs b/tendermint/src/evidence.rs index 66ac5465f..767b7e385 100644 --- a/tendermint/src/evidence.rs +++ b/tendermint/src/evidence.rs @@ -207,19 +207,28 @@ impl AsRef<[Evidence]> for Data { } } -/// Evidence collection parameters +/// EvidenceParams determine how we handle evidence of malfeasance. +/// +/// [Tendermint documentation](https://docs.tendermint.com/master/spec/core/data_structures.html#evidenceparams) #[derive(Deserialize, Serialize, Clone, Debug, Eq, PartialEq)] // Todo: This struct is ready to be converted through tendermint_proto::types::EvidenceParams. // https://github.com/informalsystems/tendermint-rs/issues/741 pub struct Params { - /// Maximum allowed age for evidence to be collected + /// Max age of evidence, in blocks. #[serde(with = "serializers::from_str")] pub max_age_num_blocks: u64, - /// Max age duration + /// Max age of evidence, in time. + /// + /// It should correspond with an app's "unbonding period" or other similar + /// mechanism for handling [Nothing-At-Stake attacks][nas]. + /// + /// [nas]: https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed pub max_age_duration: Duration, - /// Max bytes + /// This sets the maximum size of total evidence in bytes that can be + /// committed in a single block, and should fall comfortably under the max + /// block bytes. The default is 1048576 or 1MB. #[serde(with = "serializers::from_str", default)] pub max_bytes: i64, } From 3c5eff5d666fd7ecc0b4c9fdb5ca159fbff415a6 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 15 Nov 2021 15:01:49 -0800 Subject: [PATCH 18/20] Add hex encoding Serde attribute to Sr25519 keys. --- proto/src/prost/tendermint.crypto.rs | 1 + tools/proto-compiler/src/constants.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/proto/src/prost/tendermint.crypto.rs b/proto/src/prost/tendermint.crypto.rs index 3266afdd5..4bb7a72e8 100644 --- a/proto/src/prost/tendermint.crypto.rs +++ b/proto/src/prost/tendermint.crypto.rs @@ -70,6 +70,7 @@ pub mod public_key { #[serde(rename = "tendermint/PubKeySecp256k1", with = "crate::serializers::bytes::base64string")] Secp256k1(::prost::alloc::vec::Vec), #[prost(bytes, tag="3")] + #[serde(rename = "tendermint/PubKeySr25519", with = "crate::serializers::bytes::base64string")] Sr25519(::prost::alloc::vec::Vec), } } diff --git a/tools/proto-compiler/src/constants.rs b/tools/proto-compiler/src/constants.rs index 3ff56a3e4..e65c0e083 100644 --- a/tools/proto-compiler/src/constants.rs +++ b/tools/proto-compiler/src/constants.rs @@ -29,6 +29,7 @@ const PART_SET_HEADER_TOTAL: &str = r#"#[serde(with = "crate::serializers::part_set_header_total")]"#; const RENAME_EDPUBKEY: &str = r#"#[serde(rename = "tendermint/PubKeyEd25519", with = "crate::serializers::bytes::base64string")]"#; const RENAME_SECPPUBKEY: &str = r#"#[serde(rename = "tendermint/PubKeySecp256k1", with = "crate::serializers::bytes::base64string")]"#; +const RENAME_SRPUBKEY: &str = r#"#[serde(rename = "tendermint/PubKeySr25519", with = "crate::serializers::bytes::base64string")]"#; const RENAME_DUPLICATEVOTE: &str = r#"#[serde(rename = "tendermint/DuplicateVoteEvidence")]"#; const RENAME_LIGHTCLIENTATTACK: &str = r#"#[serde(rename = "tendermint/LightClientAttackEvidence")]"#; @@ -143,6 +144,7 @@ pub static CUSTOM_FIELD_ATTRIBUTES: &[(&str, &str)] = &[ ".tendermint.crypto.PublicKey.sum.secp256k1", RENAME_SECPPUBKEY, ), + (".tendermint.crypto.PublicKey.sum.sr25519", RENAME_SRPUBKEY), ( ".tendermint.types.Evidence.sum.duplicate_vote_evidence", RENAME_DUPLICATEVOTE, From 1f1a4c89533763c56168574a028d68a8c8b16d4d Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 15 Nov 2021 15:22:05 -0800 Subject: [PATCH 19/20] Replace integers with `block::Height`, `vote::Power` --- tendermint/src/abci/request/init_chain.rs | 8 ++--- .../src/abci/request/load_snapshot_chunk.rs | 8 ++--- tendermint/src/abci/request/query.rs | 10 +++--- tendermint/src/abci/response/commit.rs | 8 ++--- tendermint/src/abci/response/info.rs | 12 +++---- tendermint/src/abci/response/query.rs | 9 +++--- tendermint/src/abci/types.rs | 32 +++++++++---------- tendermint/src/prelude.rs | 3 ++ 8 files changed, 45 insertions(+), 45 deletions(-) diff --git a/tendermint/src/abci/request/init_chain.rs b/tendermint/src/abci/request/init_chain.rs index 7acc938f4..4b85e4848 100644 --- a/tendermint/src/abci/request/init_chain.rs +++ b/tendermint/src/abci/request/init_chain.rs @@ -1,7 +1,7 @@ use bytes::Bytes; use chrono::{DateTime, Utc}; -use crate::{consensus, prelude::*}; +use crate::{block, consensus, prelude::*}; use super::super::types::ValidatorUpdate; @@ -21,7 +21,7 @@ pub struct InitChain { /// Serialized JSON bytes containing the initial application state. pub app_state_bytes: Bytes, /// Height of the initial block (typically `1`). - pub initial_height: i64, + pub initial_height: block::Height, } // ============================================================================= @@ -41,7 +41,7 @@ impl From for pb::RequestInitChain { consensus_params: Some(init_chain.consensus_params.into()), validators: init_chain.validators.into_iter().map(Into::into).collect(), app_state_bytes: init_chain.app_state_bytes, - initial_height: init_chain.initial_height, + initial_height: init_chain.initial_height.into(), } } } @@ -66,7 +66,7 @@ impl TryFrom for InitChain { .map(TryInto::try_into) .collect::>()?, app_state_bytes: init_chain.app_state_bytes, - initial_height: init_chain.initial_height, + initial_height: init_chain.initial_height.try_into()?, }) } } diff --git a/tendermint/src/abci/request/load_snapshot_chunk.rs b/tendermint/src/abci/request/load_snapshot_chunk.rs index 25f163067..d88885cd0 100644 --- a/tendermint/src/abci/request/load_snapshot_chunk.rs +++ b/tendermint/src/abci/request/load_snapshot_chunk.rs @@ -1,10 +1,10 @@ -use crate::prelude::*; +use crate::{block, prelude::*}; #[doc = include_str!("../doc/request-loadsnapshotchunk.md")] #[derive(Clone, PartialEq, Eq, Debug)] pub struct LoadSnapshotChunk { /// The height of the snapshot the chunks belong to. - pub height: u64, + pub height: block::Height, /// An application-specific identifier of the format of the snapshot chunk. pub format: u32, /// The chunk index, starting from `0` for the initial chunk. @@ -22,7 +22,7 @@ use tendermint_proto::Protobuf; impl From for pb::RequestLoadSnapshotChunk { fn from(load_snapshot_chunk: LoadSnapshotChunk) -> Self { Self { - height: load_snapshot_chunk.height, + height: load_snapshot_chunk.height.into(), format: load_snapshot_chunk.format, chunk: load_snapshot_chunk.chunk, } @@ -34,7 +34,7 @@ impl TryFrom for LoadSnapshotChunk { fn try_from(load_snapshot_chunk: pb::RequestLoadSnapshotChunk) -> Result { Ok(Self { - height: load_snapshot_chunk.height, + height: load_snapshot_chunk.height.try_into()?, format: load_snapshot_chunk.format, chunk: load_snapshot_chunk.chunk, }) diff --git a/tendermint/src/abci/request/query.rs b/tendermint/src/abci/request/query.rs index 46d35cdd8..1530f69d2 100644 --- a/tendermint/src/abci/request/query.rs +++ b/tendermint/src/abci/request/query.rs @@ -1,7 +1,7 @@ -use crate::prelude::*; - use bytes::Bytes; +use crate::{block, prelude::*}; + #[doc = include_str!("../doc/request-query.md")] #[derive(Clone, PartialEq, Eq, Debug)] pub struct Query { @@ -23,7 +23,7 @@ pub struct Query { /// this is the height of the block containing the application's Merkle root /// hash, which represents the state as it was after committing the block at /// `height - 1`. - pub height: i64, + pub height: block::Height, /// Whether to return a Merkle proof with the response, if possible. pub prove: bool, } @@ -41,7 +41,7 @@ impl From for pb::RequestQuery { Self { data: query.data, path: query.path, - height: query.height, + height: query.height.into(), prove: query.prove, } } @@ -54,7 +54,7 @@ impl TryFrom for Query { Ok(Self { data: query.data, path: query.path, - height: query.height, + height: query.height.try_into()?, prove: query.prove, }) } diff --git a/tendermint/src/abci/response/commit.rs b/tendermint/src/abci/response/commit.rs index a5163c757..9cded2e26 100644 --- a/tendermint/src/abci/response/commit.rs +++ b/tendermint/src/abci/response/commit.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use crate::{block, prelude::*}; use bytes::Bytes; @@ -11,7 +11,7 @@ pub struct Commit { /// XXX(hdevalence) - rename to app_hash ? pub data: Bytes, /// Blocks below this height may be removed. - pub retain_height: i64, + pub retain_height: block::Height, } // ============================================================================= @@ -26,7 +26,7 @@ impl From for pb::ResponseCommit { fn from(commit: Commit) -> Self { Self { data: commit.data, - retain_height: commit.retain_height, + retain_height: commit.retain_height.into(), } } } @@ -37,7 +37,7 @@ impl TryFrom for Commit { fn try_from(commit: pb::ResponseCommit) -> Result { Ok(Self { data: commit.data, - retain_height: commit.retain_height, + retain_height: commit.retain_height.try_into()?, }) } } diff --git a/tendermint/src/abci/response/info.rs b/tendermint/src/abci/response/info.rs index 1fcd37cbc..02bc6e9a1 100644 --- a/tendermint/src/abci/response/info.rs +++ b/tendermint/src/abci/response/info.rs @@ -1,9 +1,9 @@ -use crate::prelude::*; +use crate::{block, prelude::*, Error}; use bytes::Bytes; #[doc = include_str!("../doc/response-info.md")] -#[derive(Clone, PartialEq, Eq, Debug, Default)] +#[derive(Clone, PartialEq, Eq, Debug)] pub struct Info { /// Some arbitrary information. pub data: String, @@ -12,7 +12,7 @@ pub struct Info { /// The application protocol version. pub app_version: u64, /// The latest block for which the app has called [`Commit`](super::super::Request::Commit). - pub last_block_height: i64, + pub last_block_height: block::Height, /// The latest result of [`Commit`](super::super::Request::Commit). // XXX(hdevalence): fix this, should be apphash? pub last_block_app_hash: Bytes, @@ -32,21 +32,21 @@ impl From for pb::ResponseInfo { data: info.data, version: info.version, app_version: info.app_version, - last_block_height: info.last_block_height, + last_block_height: info.last_block_height.into(), last_block_app_hash: info.last_block_app_hash, } } } impl TryFrom for Info { - type Error = &'static str; + type Error = Error; fn try_from(info: pb::ResponseInfo) -> Result { Ok(Self { data: info.data, version: info.version, app_version: info.app_version, - last_block_height: info.last_block_height, + last_block_height: info.last_block_height.try_into()?, last_block_app_hash: info.last_block_app_hash, }) } diff --git a/tendermint/src/abci/response/query.rs b/tendermint/src/abci/response/query.rs index 642a6c98c..fd1b9655d 100644 --- a/tendermint/src/abci/response/query.rs +++ b/tendermint/src/abci/response/query.rs @@ -1,9 +1,8 @@ -use crate::prelude::*; - use bytes::Bytes; /// XXX(hdevalence): hide merkle::proof and re-export its contents from merkle? use crate::merkle::proof as merkle; +use crate::{block, prelude::*}; #[doc = include_str!("../doc/response-query.md")] #[derive(Clone, PartialEq, Eq, Debug, Default)] @@ -32,7 +31,7 @@ pub struct Query { /// Note that this is the height of the block containing the application's /// Merkle root hash, which represents the state as it was after committing /// the block at `height - 1`. - pub height: i64, + pub height: block::Height, /// The namespace for the `code`. pub codespace: String, } @@ -55,7 +54,7 @@ impl From for pb::ResponseQuery { key: query.key, value: query.value, proof_ops: query.proof.map(Into::into), - height: query.height, + height: query.height.into(), codespace: query.codespace, } } @@ -73,7 +72,7 @@ impl TryFrom for Query { key: query.key, value: query.value, proof: query.proof_ops.map(TryInto::try_into).transpose()?, - height: query.height, + height: query.height.try_into()?, codespace: query.codespace, }) } diff --git a/tendermint/src/abci/types.rs b/tendermint/src/abci/types.rs index 6cd8cd91b..920a95ce5 100644 --- a/tendermint/src/abci/types.rs +++ b/tendermint/src/abci/types.rs @@ -5,14 +5,12 @@ //! //! [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#data-types) -use crate::prelude::*; - use core::convert::{TryFrom, TryInto}; use bytes::Bytes; use chrono::{DateTime, Utc}; -use crate::{Error, PublicKey}; +use crate::{block, prelude::*, vote, Error, PublicKey}; /// A validator address with voting power. /// @@ -22,7 +20,7 @@ pub struct Validator { /// The validator's address (the first 20 bytes of `SHA256(public_key)`). pub address: [u8; 20], /// The voting power of the validator. - pub power: i64, + pub power: vote::Power, } /// A change to the validator set. @@ -35,7 +33,7 @@ pub struct ValidatorUpdate { /// The validator's public key. pub pub_key: PublicKey, /// The validator's voting power. - pub power: i64, + pub power: vote::Power, } /// Information about a whether a validator signed the last block. @@ -80,7 +78,7 @@ pub struct Evidence { /// The offending validator. pub validator: Validator, /// The height when the offense occurred. - pub height: i64, + pub height: block::Height, /// The corresponding time when the offense occurred. pub time: DateTime, /// Total voting power of the validator set at `height`. @@ -88,7 +86,7 @@ pub struct Evidence { /// This is included in case the ABCI application does not store historical /// validators, cf. /// [#4581](https://github.com/tendermint/tendermint/issues/4581) - pub total_voting_power: i64, + pub total_voting_power: vote::Power, } /// Information on the last block commit. @@ -114,7 +112,7 @@ pub struct LastCommitInfo { #[derive(Clone, PartialEq, Eq, Debug)] pub struct Snapshot { /// The height at which the snapshot was taken - pub height: u64, + pub height: block::Height, /// The application-specific snapshot format identifier. /// /// This allows applications to version their snapshot data format and make @@ -143,7 +141,7 @@ impl From for pb::Validator { fn from(v: Validator) -> Self { Self { address: Bytes::copy_from_slice(&v.address[..]), - power: v.power, + power: v.power.into(), } } } @@ -162,7 +160,7 @@ impl TryFrom for Validator { Ok(Self { address, - power: vu.power, + power: vu.power.try_into()?, }) } } @@ -173,7 +171,7 @@ impl From for pb::ValidatorUpdate { fn from(vu: ValidatorUpdate) -> Self { Self { pub_key: Some(vu.pub_key.into()), - power: vu.power, + power: vu.power.into(), } } } @@ -184,7 +182,7 @@ impl TryFrom for ValidatorUpdate { fn try_from(vu: pb::ValidatorUpdate) -> Result { Ok(Self { pub_key: vu.pub_key.ok_or(Error::missing_public_key())?.try_into()?, - power: vu.power, + power: vu.power.try_into()?, }) } } @@ -218,9 +216,9 @@ impl From for pb::Evidence { Self { r#type: evidence.kind as i32, validator: Some(evidence.validator.into()), - height: evidence.height, + height: evidence.height.into(), time: Some(evidence.time.into()), - total_voting_power: evidence.total_voting_power, + total_voting_power: evidence.total_voting_power.into(), } } } @@ -244,7 +242,7 @@ impl TryFrom for Evidence { .try_into()?, height: evidence.height.try_into()?, time: evidence.time.ok_or(Error::missing_timestamp())?.into(), - total_voting_power: evidence.total_voting_power, + total_voting_power: evidence.total_voting_power.try_into()?, }) } } @@ -280,7 +278,7 @@ impl Protobuf for LastCommitInfo {} impl From for pb::Snapshot { fn from(snapshot: Snapshot) -> Self { Self { - height: snapshot.height, + height: snapshot.height.into(), format: snapshot.format, chunks: snapshot.chunks, hash: snapshot.hash, @@ -294,7 +292,7 @@ impl TryFrom for Snapshot { fn try_from(snapshot: pb::Snapshot) -> Result { Ok(Self { - height: snapshot.height, + height: snapshot.height.try_into()?, format: snapshot.format, chunks: snapshot.chunks, hash: snapshot.hash, diff --git a/tendermint/src/prelude.rs b/tendermint/src/prelude.rs index 9ff42a989..3aee8bcda 100644 --- a/tendermint/src/prelude.rs +++ b/tendermint/src/prelude.rs @@ -9,3 +9,6 @@ pub use alloc::vec::Vec; pub use alloc::format; pub use alloc::vec; + +// will be included in 2021 edition. +pub use core::convert::{TryFrom, TryInto}; From 9660feb5223e3d23eb3813bcb308644daa17b29c Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 15 Nov 2021 15:25:10 -0800 Subject: [PATCH 20/20] Replace integer with block::Round --- tendermint/src/abci/types.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tendermint/src/abci/types.rs b/tendermint/src/abci/types.rs index 920a95ce5..30dc0cded 100644 --- a/tendermint/src/abci/types.rs +++ b/tendermint/src/abci/types.rs @@ -98,7 +98,7 @@ pub struct LastCommitInfo { /// /// Reflects the total number of rounds it took to come to consensus for the /// current block. - pub round: i32, + pub round: block::Round, /// The list of validator addresses in the last validator set, with their /// voting power and whether or not they signed a vote. pub votes: Vec, @@ -252,7 +252,7 @@ impl Protobuf for Evidence {} impl From for pb::LastCommitInfo { fn from(lci: LastCommitInfo) -> Self { Self { - round: lci.round, + round: lci.round.into(), votes: lci.votes.into_iter().map(Into::into).collect(), } } @@ -263,7 +263,7 @@ impl TryFrom for LastCommitInfo { fn try_from(lci: pb::LastCommitInfo) -> Result { Ok(Self { - round: lci.round, + round: lci.round.try_into()?, votes: lci .votes .into_iter()