diff --git a/CHANGELOG.md b/CHANGELOG.md index 41f0d4121b..bef502d6b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,71 @@ # Changelog +## v0.0.4 +*September 30, 2020* + +This release focuses on the refinement of the IBC message processor framework, protobuf migration, +adding (de)serialization capability to ICS02 and ICS03 messages and structures. + +Additional highlights: +- Added initial implementations for the ICS26 (routing module) and ICS18 (basic relayer algorithms module) for use in testing. +- Also added support for packet handling in the relayer algorithm specifications. + +### BREAKING CHANGES: + +### FEATURES: +- [modules/ics03] ICS03 Ack and Confirm message processors ([#223]) +- [relayer-cli] Relayer CLIs for client messages ([#207]) +- [relayer-cli] Relayer CLIs for connection-open-init ([#206]) +- [modules] Routing module minimal implementation for MVP ([#159], [#232]) +- [spec/relayer] Relayer specification for packet handling ([#229], [#234], [#237]) +- [spec/relayer] Basic packet handling in TLA+([#124]) +- [modules] Basic relayer functionality: a test with ClientUpdate ping-pong between two mocked chains ([#276]) + +### IMPROVEMENTS: +- [modules] Implemented the `DomainType` trait for IBC proto structures ([#249]). +- [modules] & [ibc-proto] Several improvements to message processors, among which ([#218]): + - ICS03 connection handshake protocol initial implementation and tests ([#160]) + - Add capability to decode from protobuf Any* type into Tendermint and Mock client states + - Cleanup Any* client wrappers related code + - Migrate handlers to newer protobuf definitions ([#226]) + - Extend client context mock ([#221]) +- [modules/ics03] Split `msgs.rs` in multiple files, implement `From` for all messages ([#253]) +- [ibc-proto] Move ibc-proto source code into ibc-rs ([#142]) +- [spec/relayer] Add support for APALACHE to the Relayer TLA+ spec ([#165]) +- [relayer] Update to tendermint v.0.16 and integrate with the new light client implementation ([#90], [#243]) + +### BUG FIXES: +- [relayer-cli] Fix for client query subcommands ([#231]) +- [disclosure-log] & [spec/connection-handshake] Disclosed bugs in ICS3 version negotiation and proposed a fix ([#209], [#213]) + +[#90]: https://github.com/informalsystems/ibc-rs/issues/90 +[#124]: https://github.com/informalsystems/ibc-rs/issues/124 +[#142]: https://github.com/informalsystems/ibc-rs/issues/142 +[#159]: https://github.com/informalsystems/ibc-rs/issues/159 +[#160]: https://github.com/informalsystems/ibc-rs/issues/160 +[#165]: https://github.com/informalsystems/ibc-rs/issues/165 +[#206]: https://github.com/informalsystems/ibc-rs/issues/206 +[#207]: https://github.com/informalsystems/ibc-rs/issues/207 +[#209]: https://github.com/informalsystems/ibc-rs/issues/209 +[#213]: https://github.com/informalsystems/ibc-rs/issues/213 +[#218]: https://github.com/informalsystems/ibc-rs/issues/218 +[#221]: https://github.com/informalsystems/ibc-rs/issues/221 +[#223]: https://github.com/informalsystems/ibc-rs/issues/223 +[#226]: https://github.com/informalsystems/ibc-rs/issues/226 +[#229]: https://github.com/informalsystems/ibc-rs/issues/229 +[#231]: https://github.com/informalsystems/ibc-rs/issues/231 +[#232]: https://github.com/informalsystems/ibc-rs/issues/232 +[#234]: https://github.com/informalsystems/ibc-rs/issues/234 +[#237]: https://github.com/informalsystems/ibc-rs/issues/237 +[#243]: https://github.com/informalsystems/ibc-rs/issues/243 +[#249]: https://github.com/informalsystems/ibc-rs/issues/249 +[#253]: https://github.com/informalsystems/ibc-rs/issues/253 +[#276]: https://github.com/informalsystems/ibc-rs/issues/276 +[ibc-proto]: https://github.com/informalsystems/ibc-rs/tree/master/proto +[disclosure-log]: https://github.com/informalsystems/ibc-rs/blob/master/docs/disclosure-log.md +[spec/connection-handshake]: https://github.com/informalsystems/ibc-rs/tree/master/docs/spec/connection-handshake +[relayer]: https://github.com/informalsystems/ibc-rs/tree/master/relayer + ## v0.0.3 *September 1, 2020* diff --git a/modules/Cargo.toml b/modules/Cargo.toml index 5580cbb371..38592949b9 100644 --- a/modules/Cargo.toml +++ b/modules/Cargo.toml @@ -18,7 +18,7 @@ description = """ tendermint-proto = "0.1.0" # Proto definitions for all IBC-related interfaces, e.g., connections or channels. -ibc-proto = { version = "0.3.0", path = "../proto" } +ibc-proto = { version = "0.4.0", path = "../proto" } anomaly = "0.2.0" chrono = "0.4" diff --git a/modules/src/context_mock.rs b/modules/src/context_mock.rs index dd4c695417..2bc10f8169 100644 --- a/modules/src/context_mock.rs +++ b/modules/src/context_mock.rs @@ -1,9 +1,12 @@ use crate::context::{ChainKeeper, ChainReader, HistoricalInfo, SelfChainType, SelfHeader}; use crate::ics02_client::client_def::{AnyConsensusState, AnyHeader}; use crate::mock_client::header::MockHeader; -use serde_derive::{Deserialize, Serialize}; + use std::cmp::min; +use std::convert::TryInto; use std::error::Error; + +use serde_derive::{Deserialize, Serialize}; use tendermint::block::Height; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Default)] @@ -21,12 +24,14 @@ impl MockChainContext { pub fn new(max_size: usize, h: Height) -> Self { // number of headers to store, if h is 0 nothing is stored let n = min(max_size as u64, h.value()); + Self { max_size, latest: h, history: (0..n) .rev() - .map(|i| MockHeader(Height(h.value() - i))) + // SAFETY: Call to `unwrap` is safe because we are decreasing the height + .map(|i| MockHeader((h.value() - i).try_into().unwrap())) .collect(), } } @@ -39,9 +44,9 @@ impl MockChainContext { pub fn populate(&mut self, hs: Vec) { for h in hs { self.store_historical_info( - Height(h), + h.try_into().unwrap(), HistoricalInfo { - header: SelfHeader::Mock(MockHeader(Height(h))), + header: SelfHeader::Mock(MockHeader(h.try_into().unwrap())), }, ); } @@ -53,9 +58,9 @@ impl MockChainContext { new_h = u64::from(self.latest.increment()); } self.store_historical_info( - Height(new_h), + new_h.try_into().unwrap(), HistoricalInfo { - header: SelfHeader::Mock(MockHeader(Height(new_h))), + header: SelfHeader::Mock(MockHeader(new_h.try_into().unwrap())), }, ); } @@ -145,7 +150,7 @@ impl ChainKeeper for MockChainContext { #[cfg(test)] mod tests { use crate::context_mock::MockChainContext; - use tendermint::block::Height; + use std::convert::TryInto; #[test] fn test_store_historical_info() { @@ -164,22 +169,22 @@ mod tests { let tests: Vec = vec![ Test { name: "Add no prune".to_string(), - ctx: MockChainContext::new(3, Height(0)), + ctx: MockChainContext::new(3, 0_u64.try_into().unwrap()), args: [1].to_vec(), }, Test { name: "Add with prune".to_string(), - ctx: MockChainContext::new(3, Height(2)), + ctx: MockChainContext::new(3, 2_u64.try_into().unwrap()), args: [3, 4].to_vec(), }, Test { name: "Add with initial prune".to_string(), - ctx: MockChainContext::new(3, Height(10)), + ctx: MockChainContext::new(3, 10_u64.try_into().unwrap()), args: [11].to_vec(), }, Test { name: "Attempt to add non sequential headers".to_string(), - ctx: MockChainContext::new(3, Height(2)), + ctx: MockChainContext::new(3, 2_u64.try_into().unwrap()), args: [3, 5, 7].to_vec(), }, ]; diff --git a/modules/src/events.rs b/modules/src/events.rs index 44fbf4309f..5a637ed226 100644 --- a/modules/src/events.rs +++ b/modules/src/events.rs @@ -137,9 +137,9 @@ pub fn get_all_events(result: RpcEvent) -> Result, String> { let actions_and_indices = extract_helper(&events)?; for action in actions_and_indices { let ev = build_event(RawObject::new( - height.into(), + height.try_into().unwrap(), // TODO: Handle overflow action.0, - action.1.try_into().unwrap(), + action.1 as usize, events.clone(), )) .map_err(|e| e.to_string())?; diff --git a/modules/src/ics02_client/client_def.rs b/modules/src/ics02_client/client_def.rs index 233b3135e4..0acd283bd3 100644 --- a/modules/src/ics02_client/client_def.rs +++ b/modules/src/ics02_client/client_def.rs @@ -118,6 +118,17 @@ pub enum AnyClientState { Mock(MockClientState), } +impl AnyClientState { + pub fn height(&self) -> Height { + match self { + AnyClientState::Tendermint(tcs) => tcs.latest_height(), + + #[cfg(test)] + AnyClientState::Mock(mcs) => mcs.latest_height(), + } + } +} + impl DomainType for AnyClientState {} impl TryFrom for AnyClientState { @@ -248,15 +259,6 @@ impl ConsensusState for AnyConsensusState { todo!() } - fn height(&self) -> Height { - match self { - AnyConsensusState::Tendermint(cs) => cs.height(), - - #[cfg(test)] - AnyConsensusState::Mock(cs) => cs.height(), - } - } - fn root(&self) -> &CommitmentRoot { todo!() } @@ -476,7 +478,7 @@ mod tests { use crate::ics07_tendermint::client_state::ClientState; use crate::ics07_tendermint::header::test_util::get_dummy_header; use prost_types::Any; - use std::convert::TryFrom; + use std::convert::{TryFrom, TryInto}; use std::time::Duration; #[test] @@ -488,7 +490,9 @@ mod tests { unbonding_period: Duration::from_secs(128000), max_clock_drift: Duration::from_millis(3000), latest_height: tm_header.signed_header.header.height, - frozen_height: 0_u64.into(), + frozen_height: 0_u64.try_into().unwrap(), + allow_update_after_expiry: false, + allow_update_after_misbehaviour: false, }); let raw: Any = tm_client_state.clone().into(); diff --git a/modules/src/ics02_client/context.rs b/modules/src/ics02_client/context.rs index 517a373d64..92adeb8e3e 100644 --- a/modules/src/ics02_client/context.rs +++ b/modules/src/ics02_client/context.rs @@ -17,12 +17,20 @@ pub trait ClientKeeper { match handler_res { CreateResult(res) => { self.store_client_type(res.client_id.clone(), res.client_type)?; - self.store_client_state(res.client_id.clone(), res.client_state)?; - self.store_consensus_state(res.client_id, res.consensus_state)?; + self.store_client_state(res.client_id.clone(), res.client_state.clone())?; + self.store_consensus_state( + res.client_id, + res.client_state.height(), + res.consensus_state, + )?; } UpdateResult(res) => { - self.store_client_state(res.client_id.clone(), res.client_state)?; - self.store_consensus_state(res.client_id, res.consensus_state)?; + self.store_client_state(res.client_id.clone(), res.client_state.clone())?; + self.store_consensus_state( + res.client_id, + res.client_state.height(), + res.consensus_state, + )?; } } Ok(()) @@ -43,6 +51,7 @@ pub trait ClientKeeper { fn store_consensus_state( &mut self, client_id: ClientId, + height: Height, consensus_state: AnyConsensusState, ) -> Result<(), Error>; } diff --git a/modules/src/ics02_client/context_mock.rs b/modules/src/ics02_client/context_mock.rs index 48d6065f50..fc04918e63 100644 --- a/modules/src/ics02_client/context_mock.rs +++ b/modules/src/ics02_client/context_mock.rs @@ -3,11 +3,11 @@ use crate::ics02_client::client_def::{AnyClientState, AnyConsensusState}; use crate::ics02_client::client_type::ClientType; use crate::ics02_client::context::{ClientKeeper, ClientReader}; use crate::ics02_client::error::{Error, Kind}; -use crate::ics02_client::state::ConsensusState; use crate::ics24_host::identifier::ClientId; use crate::mock_client::header::MockHeader; use crate::mock_client::state::{MockClientRecord, MockClientState, MockConsensusState}; use std::collections::HashMap; +use std::convert::TryInto; use tendermint::block::Height; /// A mock implementation of client context. This mocks (i.e., replaces) the functionality of @@ -25,7 +25,10 @@ pub struct MockClientContext { impl MockClientContext { pub fn new(chain_height: u64, max_history_size: usize) -> Self { MockClientContext { - chain_context: MockChainContext::new(max_history_size, Height(chain_height)), + chain_context: MockChainContext::new( + max_history_size, + chain_height.try_into().unwrap(), + ), clients: Default::default(), } } @@ -156,6 +159,7 @@ impl ClientKeeper for MockClientContext { fn store_consensus_state( &mut self, client_id: ClientId, + height: Height, consensus_state: AnyConsensusState, ) -> Result<(), Error> { match consensus_state { @@ -167,7 +171,7 @@ impl ClientKeeper for MockClientContext { }); client_record .consensus_states - .insert(consensus_state.height(), consensus_state); + .insert(height, consensus_state); Ok(()) } _ => Err(Kind::BadClientState.into()), diff --git a/modules/src/ics02_client/handler/create_client.rs b/modules/src/ics02_client/handler/create_client.rs index 3d484c3e29..cf848d935d 100644 --- a/modules/src/ics02_client/handler/create_client.rs +++ b/modules/src/ics02_client/handler/create_client.rs @@ -53,8 +53,8 @@ pub fn process( #[cfg(test)] mod tests { + use std::convert::TryInto; use std::time::Duration; - use tendermint::block::Height; use super::*; use crate::ics02_client::context_mock::MockClientContext; @@ -74,8 +74,8 @@ mod tests { let msg = MsgCreateAnyClient { client_id, client_type: ClientType::Mock, - client_state: MockClientState(MockHeader(Height(42))).into(), - consensus_state: MockConsensusState(MockHeader(Height(42))).into(), + client_state: MockClientState(MockHeader(42_u64.try_into().unwrap())).into(), + consensus_state: MockConsensusState(MockHeader(42_u64.try_into().unwrap())).into(), signer, }; @@ -108,7 +108,7 @@ mod tests { #[test] fn test_create_client_existing_client_type() { - let height = Height(42); + let height = 42_u64.try_into().unwrap(); let client_id: ClientId = "mockclient".parse().unwrap(); let signer = get_dummy_account_id(); @@ -140,14 +140,14 @@ mod tests { let signer = get_dummy_account_id(); let mut ctx = MockClientContext::default(); - let height = Height(30); + let height = 30_u64.try_into().unwrap(); ctx.with_client_consensus_state(&client_id, height); let msg = MsgCreateAnyClient { client_id, client_type: ClientType::Tendermint, - client_state: MockClientState(MockHeader(Height(42))).into(), - consensus_state: MockConsensusState(MockHeader(Height(42))).into(), + client_state: MockClientState(MockHeader(42_u64.try_into().unwrap())).into(), + consensus_state: MockConsensusState(MockHeader(42_u64.try_into().unwrap())).into(), signer, }; @@ -164,7 +164,7 @@ mod tests { fn test_create_client_ok_multiple() { let existing_client_id: ClientId = "existingmockclient".parse().unwrap(); let signer = get_dummy_account_id(); - let height = Height(80); + let height = 80_u64.try_into().unwrap(); let mut ctx = MockClientContext::default(); ctx.with_client_consensus_state(&existing_client_id, height); @@ -172,22 +172,22 @@ mod tests { MsgCreateAnyClient { client_id: "newmockclient1".parse().unwrap(), client_type: ClientType::Mock, - client_state: MockClientState(MockHeader(Height(42))).into(), - consensus_state: MockConsensusState(MockHeader(Height(42))).into(), + client_state: MockClientState(MockHeader(42_u64.try_into().unwrap())).into(), + consensus_state: MockConsensusState(MockHeader(42_u64.try_into().unwrap())).into(), signer, }, MsgCreateAnyClient { client_id: "newmockclient2".parse().unwrap(), client_type: ClientType::Mock, - client_state: MockClientState(MockHeader(Height(42))).into(), - consensus_state: MockConsensusState(MockHeader(Height(42))).into(), + client_state: MockClientState(MockHeader(42_u64.try_into().unwrap())).into(), + consensus_state: MockConsensusState(MockHeader(42_u64.try_into().unwrap())).into(), signer, }, MsgCreateAnyClient { client_id: "newmockclient3".parse().unwrap(), client_type: ClientType::Tendermint, - client_state: MockClientState(MockHeader(Height(50))).into(), - consensus_state: MockConsensusState(MockHeader(Height(50))).into(), + client_state: MockClientState(MockHeader(50_u64.try_into().unwrap())).into(), + consensus_state: MockConsensusState(MockHeader(50_u64.try_into().unwrap())).into(), signer, }, ] @@ -237,7 +237,9 @@ mod tests { unbonding_period: Duration::from_secs(128000), max_clock_drift: Duration::from_millis(3000), latest_height: tm_header.signed_header.header.height, - frozen_height: 0_u64.into(), + frozen_height: 0_u64.try_into().unwrap(), + allow_update_after_expiry: false, + allow_update_after_misbehaviour: false, }); let msg = MsgCreateAnyClient { diff --git a/modules/src/ics02_client/handler/update_client.rs b/modules/src/ics02_client/handler/update_client.rs index bac2842acc..741da28099 100644 --- a/modules/src/ics02_client/handler/update_client.rs +++ b/modules/src/ics02_client/handler/update_client.rs @@ -63,6 +63,7 @@ pub fn keep(keeper: &mut dyn ClientKeeper, result: UpdateClientResult) -> Result #[cfg(test)] mod tests { + use std::convert::TryInto; use tendermint::block::Height; use super::*; @@ -77,11 +78,11 @@ mod tests { let signer = get_dummy_account_id(); let mut ctx = MockClientContext::default(); - ctx.with_client(&client_id, ClientType::Mock, Height(42)); + ctx.with_client(&client_id, ClientType::Mock, 42_u64.try_into().unwrap()); let msg = MsgUpdateAnyClient { client_id, - header: MockHeader(Height(46)).into(), + header: MockHeader(46_u64.try_into().unwrap()).into(), signer, }; @@ -111,11 +112,11 @@ mod tests { let signer = get_dummy_account_id(); let mut ctx = MockClientContext::default(); - ctx.with_client_consensus_state(&client_id, Height(42)); + ctx.with_client_consensus_state(&client_id, 42_u64.try_into().unwrap()); let msg = MsgUpdateAnyClient { client_id: "nonexistingclient".parse().unwrap(), - header: MockHeader(Height(46)).into(), + header: MockHeader(46_u64.try_into().unwrap()).into(), signer, }; @@ -140,8 +141,8 @@ mod tests { ]; let signer = get_dummy_account_id(); - let initial_height = Height(45); - let update_height = Height(49); + let initial_height: Height = 45_u64.try_into().unwrap(); + let update_height: Height = 49_u64.try_into().unwrap(); let mut ctx = MockClientContext::default(); diff --git a/modules/src/ics02_client/msgs.rs b/modules/src/ics02_client/msgs.rs index b398e842ab..d2f3f23953 100644 --- a/modules/src/ics02_client/msgs.rs +++ b/modules/src/ics02_client/msgs.rs @@ -3,7 +3,7 @@ //! handles these messages in two layers: first with the general ICS 02 client handler, which //! subsequently calls into the chain-specific (e.g., ICS 07) client handler. See: //! https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create. -use std::convert::{TryFrom, TryInto}; +use std::convert::TryFrom; use crate::ics02_client::client_def::{AnyClientState, AnyConsensusState, AnyHeader}; use crate::ics02_client::client_type::ClientType; @@ -12,6 +12,7 @@ use crate::ics24_host::identifier::ClientId; use crate::tx_msg::Msg; use ibc_proto::ibc::client::MsgCreateClient as RawMsgCreateClient; +use std::str::FromStr; use tendermint::account::Id as AccountId; use tendermint_proto::{DomainType, Error, Kind}; @@ -109,7 +110,8 @@ impl TryFrom for MsgCreateAnyClient { client_type, client_state: AnyClientState::try_from(raw_client_state).unwrap(), consensus_state: AnyConsensusState::try_from(raw_consensus_state).unwrap(), - signer: AccountId::new(raw.signer[..20].try_into().unwrap()), + signer: AccountId::from_str(raw.signer.as_str()) + .map_err(|e| Kind::DecodeMessage.context(e))?, }) } } @@ -120,7 +122,7 @@ impl From for RawMsgCreateClient { client_id: ics_msg.client_id.to_string(), client_state: Some(ics_msg.client_state.into()), consensus_state: Some(ics_msg.consensus_state.into()), - signer: Vec::from(ics_msg.signer.as_bytes()), + signer: ics_msg.signer.to_string(), } } } @@ -136,7 +138,7 @@ pub struct MsgUpdateAnyClient { #[cfg(test)] mod tests { use ibc_proto::ibc::client::MsgCreateClient; - use std::convert::TryFrom; + use std::convert::{TryFrom, TryInto}; use std::time::Duration; use crate::ics02_client::client_def::{AnyClientState, AnyConsensusState}; @@ -159,7 +161,9 @@ mod tests { unbonding_period: Duration::from_secs(128000), max_clock_drift: Duration::from_millis(3000), latest_height: tm_header.signed_header.header.height, - frozen_height: 0_u64.into(), + frozen_height: 0_u64.try_into().unwrap(), + allow_update_after_expiry: false, + allow_update_after_misbehaviour: false, }); let msg = MsgCreateAnyClient { diff --git a/modules/src/ics02_client/state.rs b/modules/src/ics02_client/state.rs index 1af84df7d0..75500faacd 100644 --- a/modules/src/ics02_client/state.rs +++ b/modules/src/ics02_client/state.rs @@ -7,9 +7,6 @@ pub trait ConsensusState: Clone + std::fmt::Debug { /// Type of client associated with this consensus state (eg. Tendermint) fn client_type(&self) -> ClientType; - /// Height of consensus state - fn height(&self) -> Height; - /// Commitment root of the consensus state, which is used for key-value pair verification. fn root(&self) -> &CommitmentRoot; diff --git a/modules/src/ics03_connection/context_mock.rs b/modules/src/ics03_connection/context_mock.rs index f54aaee3b9..5da9f68452 100644 --- a/modules/src/ics03_connection/context_mock.rs +++ b/modules/src/ics03_connection/context_mock.rs @@ -9,6 +9,7 @@ use crate::ics03_connection::error::Error; use crate::ics23_commitment::commitment::CommitmentPrefix; use crate::ics24_host::identifier::{ClientId, ConnectionId}; use std::collections::HashMap; +use std::convert::TryInto; use tendermint::block::Height; #[derive(Clone, Debug, Default)] @@ -37,7 +38,9 @@ impl MockConnectionContext { pub fn with_client_state(self, client_id: &ClientId, latest_client_height: u64) -> Self { let mut client_context = self.client_context().clone(); - client_context.with_client_consensus_state(client_id, Height(latest_client_height)); + client_context + .with_client_consensus_state(client_id, latest_client_height.try_into().unwrap()); + Self { client_context, ..self diff --git a/modules/src/ics03_connection/msgs.rs b/modules/src/ics03_connection/msgs.rs index 3ed0a8801f..a37abe1e79 100644 --- a/modules/src/ics03_connection/msgs.rs +++ b/modules/src/ics03_connection/msgs.rs @@ -35,7 +35,7 @@ pub enum ConnectionMsg { #[cfg(test)] pub mod test_util { - use std::str::{from_utf8, FromStr}; + use std::str::FromStr; use tendermint::account::Id as AccountId; use ibc_proto::ibc::commitment::MerklePrefix; @@ -47,14 +47,12 @@ pub mod test_util { .to_vec() } - pub fn get_dummy_account_id_bytes() -> Vec { - "0CDA3F47EF3C4906693B170EF650EB968C5F4B2C" - .as_bytes() - .to_vec() + pub fn get_dummy_account_id_raw() -> String { + "0CDA3F47EF3C4906693B170EF650EB968C5F4B2C".to_string() } pub fn get_dummy_account_id() -> AccountId { - AccountId::from_str(from_utf8(&get_dummy_account_id_bytes()).unwrap()).unwrap() + AccountId::from_str(&get_dummy_account_id_raw()).unwrap() } pub fn get_dummy_counterparty() -> RawCounterparty { diff --git a/modules/src/ics03_connection/msgs/conn_open_ack.rs b/modules/src/ics03_connection/msgs/conn_open_ack.rs index a8430b1082..55ca52af5e 100644 --- a/modules/src/ics03_connection/msgs/conn_open_ack.rs +++ b/modules/src/ics03_connection/msgs/conn_open_ack.rs @@ -13,6 +13,7 @@ use crate::ics03_connection::error::{Error, Kind}; use crate::ics24_host::identifier::ConnectionId; use crate::proofs::{ConsensusProof, Proofs}; use crate::tx_msg::Msg; +use std::str::FromStr; /// Message type for the `MsgConnectionOpenAck` message. pub const TYPE_MSG_CONNECTION_OPEN_ACK: &str = "connection_open_ack"; @@ -54,7 +55,7 @@ impl MsgConnectionOpenAck { /// value `0` if this field is not set. pub fn consensus_height(&self) -> Height { match self.proofs.consensus_proof() { - None => Height(0), + None => 0_u64.try_into().unwrap(), Some(p) => p.height(), } } @@ -124,11 +125,8 @@ impl TryFrom for MsgConnectionOpenAck { proof_height, ) .map_err(|e| Kind::InvalidProof.context(e))?, - signer: AccountId::new( - msg.signer[..20] - .try_into() - .map_err(|e| Kind::InvalidSigner.context(e))?, - ), + signer: AccountId::from_str(msg.signer.as_str()) + .map_err(|e| Kind::InvalidSigner.context(e))?, }) } } @@ -164,7 +162,7 @@ impl From for RawMsgConnectionOpenAck { }) }, ), - signer: Vec::from(ics_msg.signer.as_bytes()), + signer: ics_msg.signer.to_string(), } } } @@ -174,7 +172,7 @@ pub mod test_util { use ibc_proto::ibc::client::Height; use ibc_proto::ibc::connection::MsgConnectionOpenAck as RawMsgConnectionOpenAck; - use crate::ics03_connection::msgs::test_util::{get_dummy_account_id, get_dummy_proof}; + use crate::ics03_connection::msgs::test_util::{get_dummy_account_id_raw, get_dummy_proof}; pub fn get_dummy_msg_conn_open_ack() -> RawMsgConnectionOpenAck { RawMsgConnectionOpenAck { @@ -192,7 +190,7 @@ pub mod test_util { }), client_state: None, proof_client: vec![], - signer: Vec::from(get_dummy_account_id().as_bytes()), + signer: get_dummy_account_id_raw(), } } } diff --git a/modules/src/ics03_connection/msgs/conn_open_confirm.rs b/modules/src/ics03_connection/msgs/conn_open_confirm.rs index 670a5a9c53..ab49c2785b 100644 --- a/modules/src/ics03_connection/msgs/conn_open_confirm.rs +++ b/modules/src/ics03_connection/msgs/conn_open_confirm.rs @@ -1,5 +1,5 @@ use serde_derive::{Deserialize, Serialize}; -use std::convert::{TryFrom, TryInto}; +use std::convert::TryFrom; use ibc_proto::ibc::connection::MsgConnectionOpenConfirm as RawMsgConnectionOpenConfirm; use tendermint_proto::DomainType; @@ -10,6 +10,7 @@ use crate::ics03_connection::error::{Error, Kind}; use crate::ics24_host::identifier::ConnectionId; use crate::proofs::Proofs; use crate::tx_msg::Msg; +use std::str::FromStr; /// Message type for the `MsgConnectionOpenConfirm` message. pub const TYPE_MSG_CONNECTION_OPEN_CONFIRM: &str = "connection_open_confirm"; @@ -77,11 +78,8 @@ impl TryFrom for MsgConnectionOpenConfirm { .map_err(|e| Kind::IdentifierError.context(e))?, proofs: Proofs::new(msg.proof_ack.into(), None, None, proof_height) .map_err(|e| Kind::InvalidProof.context(e))?, - signer: AccountId::new( - msg.signer[..20] - .try_into() - .map_err(|e| Kind::InvalidSigner.context(e))?, - ), + signer: AccountId::from_str(msg.signer.as_str()) + .map_err(|e| Kind::InvalidSigner.context(e))?, }) } } @@ -95,7 +93,7 @@ impl From for RawMsgConnectionOpenConfirm { epoch_number: 0, epoch_height: ics_msg.proofs.height().value(), }), - signer: Vec::from(ics_msg.signer.as_bytes()), + signer: ics_msg.signer.to_string(), } } } @@ -105,7 +103,7 @@ pub mod test_util { use ibc_proto::ibc::client::Height; use ibc_proto::ibc::connection::MsgConnectionOpenConfirm as RawMsgConnectionOpenConfirm; - use crate::ics03_connection::msgs::test_util::{get_dummy_account_id, get_dummy_proof}; + use crate::ics03_connection::msgs::test_util::{get_dummy_account_id_raw, get_dummy_proof}; pub fn get_dummy_msg_conn_open_confirm() -> RawMsgConnectionOpenConfirm { RawMsgConnectionOpenConfirm { @@ -115,7 +113,7 @@ pub mod test_util { epoch_number: 0, epoch_height: 10, }), - signer: Vec::from(get_dummy_account_id().as_bytes()), + signer: get_dummy_account_id_raw(), } } } diff --git a/modules/src/ics03_connection/msgs/conn_open_init.rs b/modules/src/ics03_connection/msgs/conn_open_init.rs index 662312bc27..68f12a4d39 100644 --- a/modules/src/ics03_connection/msgs/conn_open_init.rs +++ b/modules/src/ics03_connection/msgs/conn_open_init.rs @@ -10,6 +10,7 @@ use crate::ics03_connection::connection::Counterparty; use crate::ics03_connection::error::{Error, Kind}; use crate::ics24_host::identifier::{ClientId, ConnectionId}; use crate::tx_msg::Msg; +use std::str::FromStr; /// Message type for the `MsgConnectionOpenInit` message. pub const TYPE_MSG_CONNECTION_OPEN_INIT: &str = "connection_open_init"; @@ -90,11 +91,8 @@ impl TryFrom for MsgConnectionOpenInit { .counterparty .ok_or_else(|| Kind::MissingCounterparty)? .try_into()?, - signer: AccountId::new( - msg.signer[..20] - .try_into() - .map_err(|e| Kind::InvalidSigner.context(e))?, - ), + signer: AccountId::from_str(msg.signer.as_str()) + .map_err(|e| Kind::InvalidSigner.context(e))?, }) } } @@ -105,7 +103,7 @@ impl From for RawMsgConnectionOpenInit { client_id: ics_msg.client_id.as_str().to_string(), connection_id: ics_msg.connection_id.as_str().to_string(), counterparty: Some(ics_msg.counterparty.into()), - signer: Vec::from(ics_msg.signer.as_bytes()), + signer: ics_msg.signer.to_string(), } } } @@ -114,7 +112,9 @@ impl From for RawMsgConnectionOpenInit { pub mod test_util { use ibc_proto::ibc::connection::MsgConnectionOpenInit as RawMsgConnectionOpenInit; - use crate::ics03_connection::msgs::test_util::{get_dummy_account_id, get_dummy_counterparty}; + use crate::ics03_connection::msgs::test_util::{ + get_dummy_account_id_raw, get_dummy_counterparty, + }; /// Returns a dummy message, for testing only. /// Other unit tests may import this if they depend on a MsgConnectionOpenInit. @@ -123,7 +123,7 @@ pub mod test_util { client_id: "srcclient".to_string(), connection_id: "srcconnection".to_string(), counterparty: Some(get_dummy_counterparty()), - signer: Vec::from(get_dummy_account_id().as_bytes()), + signer: get_dummy_account_id_raw(), } } } diff --git a/modules/src/ics03_connection/msgs/conn_open_try.rs b/modules/src/ics03_connection/msgs/conn_open_try.rs index 01a470fc47..ea930132ef 100644 --- a/modules/src/ics03_connection/msgs/conn_open_try.rs +++ b/modules/src/ics03_connection/msgs/conn_open_try.rs @@ -13,6 +13,7 @@ use crate::ics03_connection::error::{Error, Kind}; use crate::ics24_host::identifier::{ClientId, ConnectionId}; use crate::proofs::{ConsensusProof, Proofs}; use crate::tx_msg::Msg; +use std::str::FromStr; /// Message type for the `MsgConnectionOpenTry` message. pub const TYPE_MSG_CONNECTION_OPEN_TRY: &str = "connection_open_try"; @@ -66,7 +67,7 @@ impl MsgConnectionOpenTry { /// value `0` if this field is not set. pub fn consensus_height(&self) -> Height { match self.proofs.consensus_proof() { - None => Height(0), + None => 0_u64.try_into().unwrap(), Some(p) => p.height(), } } @@ -147,11 +148,8 @@ impl TryFrom for MsgConnectionOpenTry { proof_height, ) .map_err(|e| Kind::InvalidProof.context(e))?, - signer: AccountId::new( - msg.signer[..20] - .try_into() - .map_err(|e| Kind::InvalidSigner.context(e))?, - ), + signer: AccountId::from_str(msg.signer.as_str()) + .map_err(|e| Kind::InvalidSigner.context(e))?, }) } } @@ -189,7 +187,7 @@ impl From for RawMsgConnectionOpenTry { }) }, ), - signer: Vec::from(ics_msg.signer.as_bytes()), + signer: ics_msg.signer.to_string(), } } } @@ -200,7 +198,7 @@ pub mod test_util { use ibc_proto::ibc::connection::MsgConnectionOpenTry as RawMsgConnectionOpenTry; use crate::ics03_connection::msgs::test_util::{ - get_dummy_account_id, get_dummy_counterparty, get_dummy_proof, + get_dummy_account_id_raw, get_dummy_counterparty, get_dummy_proof, }; pub fn get_dummy_msg_conn_open_try( @@ -224,7 +222,7 @@ pub mod test_util { epoch_height: consensus_height, }), proof_client: vec![], - signer: Vec::from(get_dummy_account_id().as_bytes()), + signer: get_dummy_account_id_raw(), } } } diff --git a/modules/src/ics07_tendermint/client_state.rs b/modules/src/ics07_tendermint/client_state.rs index bff18ef4e7..365673b02f 100644 --- a/modules/src/ics07_tendermint/client_state.rs +++ b/modules/src/ics07_tendermint/client_state.rs @@ -2,10 +2,8 @@ use crate::ics02_client::client_type::ClientType; use crate::ics07_tendermint::error::{Error, Kind}; use serde_derive::{Deserialize, Serialize}; -use std::{ - convert::{TryFrom, TryInto}, - time::Duration, -}; +use std::convert::{TryFrom, TryInto}; +use std::time::Duration; use ibc_proto::ibc::tendermint::ClientState as RawClientState; use tendermint::block::Height; @@ -20,11 +18,14 @@ pub struct ClientState { pub max_clock_drift: Duration, pub latest_height: Height, pub frozen_height: Height, + pub allow_update_after_expiry: bool, + pub allow_update_after_misbehaviour: bool, } impl DomainType for ClientState {} impl ClientState { + #[allow(clippy::too_many_arguments)] pub fn new( chain_id: String, // trust_level: TrustLevel, @@ -33,7 +34,8 @@ impl ClientState { max_clock_drift: Duration, latest_height: Height, frozen_height: Height, - // proof_specs: Specs + allow_update_after_expiry: bool, + allow_update_after_misbehaviour: bool, // proof_specs: Specs ) -> Result { // Basic validation of trusting period and unbonding period: each should be non-zero. if trusting_period <= Duration::new(0, 0) { @@ -53,14 +55,14 @@ impl ClientState { } // Basic validation for the frozen_height parameter. - if frozen_height != Height(0) { + if frozen_height != 0_u64.try_into().unwrap() { return Err(Kind::ValidationError .context("ClientState cannot be frozen at creation time") .into()); } // Basic validation for the frozen_height parameter. - if latest_height <= Height(0) { + if latest_height <= 0_u64.try_into().unwrap() { return Err(Kind::ValidationError .context("ClientState latest height cannot be smaller than zero") .into()); @@ -74,8 +76,13 @@ impl ClientState { max_clock_drift, frozen_height, latest_height, + allow_update_after_expiry, + allow_update_after_misbehaviour, }) } + pub fn latest_height(&self) -> Height { + self.latest_height + } } impl crate::ics02_client::state::ClientState for ClientState { @@ -93,7 +100,7 @@ impl crate::ics02_client::state::ClientState for ClientState { fn is_frozen(&self) -> bool { // If 'frozen_height' is set to a non-zero value, then the client state is frozen. - self.frozen_height != Height(0) + self.frozen_height != 0_u64.try_into().unwrap() } } @@ -126,6 +133,8 @@ impl TryFrom for ClientState { raw.frozen_height .ok_or_else(|| Kind::InvalidRawClientState.context("missing frozen height"))?, ), + allow_update_after_expiry: raw.allow_update_after_expiry, + allow_update_after_misbehaviour: raw.allow_update_after_misbehaviour, }) } } @@ -133,7 +142,7 @@ impl TryFrom for ClientState { impl From for RawClientState { fn from(value: ClientState) -> Self { RawClientState { - chain_id: value.chain_id, + chain_id: value.chain_id.clone(), trust_level: None, // Todo: Why is trust_level commented out? trusting_period: Some(value.trusting_period.into()), unbonding_period: Some(value.unbonding_period.into()), @@ -144,22 +153,27 @@ impl From for RawClientState { }), // Todo: upgrade to tendermint v0.17.0 Height latest_height: Some(ibc_proto::ibc::client::Height { epoch_number: 0, - epoch_height: value.latest_height.value(), + epoch_height: value.latest_height().value(), }), // Todo: upgrade to tendermint v0.17.0 Height proof_specs: vec![], // Todo: Why is that not stored? + allow_update_after_expiry: false, + allow_update_after_misbehaviour: false, } } } fn decode_height(height: ibc_proto::ibc::client::Height) -> Height { - Height(height.epoch_height) // FIXME: This is wrong as it does not take the epoch into account + height.epoch_height.try_into().unwrap() // FIXME: This is wrong as it does not take the epoch into account } #[cfg(test)] mod tests { + use std::convert::TryInto; + use std::time::Duration; + use crate::ics07_tendermint::client_state::ClientState; use crate::test::test_serialization_roundtrip; - use std::time::Duration; + use tendermint::block::Height; use tendermint_rpc::endpoint::abci_query::AbciQuery; @@ -188,6 +202,8 @@ mod tests { max_clock_drift: Duration, latest_height: Height, frozen_height: Height, + allow_update_after_expiry: bool, + allow_update_after_misbehaviour: bool, } // Define a "default" set of parameters to reuse throughout these tests. @@ -196,8 +212,10 @@ mod tests { trusting_period: Duration::new(64000, 0), unbonding_period: Duration::new(128000, 0), max_clock_drift: Duration::new(3, 0), - latest_height: Height(10), - frozen_height: Height(0), + latest_height: 10_u64.try_into().unwrap(), + frozen_height: 0_u64.try_into().unwrap(), + allow_update_after_expiry: false, + allow_update_after_misbehaviour: false, }; struct Test { @@ -215,7 +233,7 @@ mod tests { Test { name: "Invalid frozen height parameter (should be 0)".to_string(), params: ClientStateParams { - frozen_height: Height(1), + frozen_height: 1_u64.try_into().unwrap(), ..default_params.clone() }, want_pass: false, @@ -259,6 +277,8 @@ mod tests { p.max_clock_drift, p.latest_height, p.frozen_height, + p.allow_update_after_expiry, + p.allow_update_after_misbehaviour, ); assert_eq!( diff --git a/modules/src/ics07_tendermint/consensus_state.rs b/modules/src/ics07_tendermint/consensus_state.rs index e698e019ff..c7354a9832 100644 --- a/modules/src/ics07_tendermint/consensus_state.rs +++ b/modules/src/ics07_tendermint/consensus_state.rs @@ -16,22 +16,15 @@ use crate::ics23_commitment::commitment::CommitmentRoot; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct ConsensusState { - pub height: crate::Height, pub timestamp: Time, pub root: CommitmentRoot, pub next_validators_hash: Hash, } impl ConsensusState { - pub fn new( - root: CommitmentRoot, - height: crate::Height, - timestamp: Time, - next_validators_hash: Hash, - ) -> Self { + pub fn new(root: CommitmentRoot, timestamp: Time, next_validators_hash: Hash) -> Self { Self { root, - height, timestamp, next_validators_hash, } @@ -43,10 +36,6 @@ impl crate::ics02_client::state::ConsensusState for ConsensusState { ClientType::Tendermint } - fn height(&self) -> crate::Height { - self.height - } - fn root(&self) -> &CommitmentRoot { &self.root } @@ -74,15 +63,10 @@ impl TryFrom for ConsensusState { .ok_or_else(|| Kind::InvalidRawConsensusState.context("missing commitment root"))? .hash .into(), - height: raw - .height - .ok_or_else(|| Kind::InvalidRawConsensusState.context("missing height"))? - .epoch_height - .into(), timestamp: Utc .timestamp(proto_timestamp.seconds, proto_timestamp.nanos as u32) .into(), - next_validators_hash: Hash::new(Algorithm::Sha256, &raw.next_validators_hash) + next_validators_hash: Hash::from_bytes(Algorithm::Sha256, &raw.next_validators_hash) .map_err(|e| Kind::InvalidRawConsensusState.context(e.to_string()))?, }) } @@ -93,10 +77,6 @@ impl From for RawConsensusState { RawConsensusState { timestamp: Some(value.timestamp.to_system_time().unwrap().into()), root: Some(ibc_proto::ibc::commitment::MerkleRoot { hash: value.root.0 }), - height: Some(ibc_proto::ibc::client::Height { - epoch_number: 0, - epoch_height: value.height.value(), - }), next_validators_hash: value.next_validators_hash.as_bytes().to_vec(), } } @@ -105,8 +85,7 @@ impl From for RawConsensusState { impl From for ConsensusState { fn from(header: SignedHeader) -> Self { Self { - root: CommitmentRoot::from_bytes(&header.header.app_hash), - height: header.header.height, + root: CommitmentRoot::from_bytes(header.header.app_hash.as_ref()), timestamp: header.header.time, next_validators_hash: header.header.next_validators_hash, } diff --git a/modules/src/ics07_tendermint/header.rs b/modules/src/ics07_tendermint/header.rs index 411bc6a7b1..2c36f333cd 100644 --- a/modules/src/ics07_tendermint/header.rs +++ b/modules/src/ics07_tendermint/header.rs @@ -1,12 +1,12 @@ use serde_derive::{Deserialize, Serialize}; use tendermint::block::signed_header::SignedHeader; +use tendermint::block::Height; use tendermint::validator::Set as ValidatorSet; use crate::ics02_client::client_type::ClientType; use crate::ics07_tendermint::consensus_state::ConsensusState; use crate::ics23_commitment::commitment::CommitmentRoot; -use tendermint::block::Height; /// Tendermint consensus header #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -20,9 +20,8 @@ pub struct Header { impl Header { pub(crate) fn consensus_state(&self) -> ConsensusState { ConsensusState { - height: self.signed_header.header.height, timestamp: self.signed_header.header.time, - root: CommitmentRoot::from_bytes(&self.signed_header.header.app_hash), + root: CommitmentRoot::from_bytes(self.signed_header.header.app_hash.as_ref()), next_validators_hash: self.signed_header.header.next_validators_hash, } } @@ -44,10 +43,12 @@ impl crate::ics02_client::header::Header for Header { #[cfg(test)] pub mod test_util { - use crate::ics07_tendermint::header::Header; + use std::convert::TryInto; use subtle_encoding::hex; + + use crate::ics07_tendermint::header::Header; + use tendermint::block::signed_header::SignedHeader; - use tendermint::block::Height; use tendermint::validator::Info as ValidatorInfo; use tendermint::validator::Set as ValidatorSet; use tendermint::{vote, PublicKey}; @@ -81,7 +82,7 @@ pub mod test_util { Header { signed_header: shdr, validator_set: vs.clone(), - trusted_height: Height(9), + trusted_height: 9_u64.try_into().unwrap(), trusted_validator_set: vs, } } diff --git a/modules/src/ics18_relayer/utils.rs b/modules/src/ics18_relayer/utils.rs index db1ce23c98..f8b979cecf 100644 --- a/modules/src/ics18_relayer/utils.rs +++ b/modules/src/ics18_relayer/utils.rs @@ -59,18 +59,19 @@ mod tests { use crate::ics18_relayer::utils::create_client_update_datagram; use crate::ics24_host::identifier::ClientId; use crate::ics26_routing::msgs::ICS26Envelope; + + use std::convert::TryInto; use std::str::FromStr; - use tendermint::block::Height; #[test] /// Serves to test both ICS 26 `dispatch` & `create_client_update_datagram` function. /// Implements a "ping pong" of client update messages, so that two chains repeatedly /// process a client update message and update their height in succession. fn client_update_ping_pong() { - let chain_a_start_height = Height(11); - let chain_b_start_height = Height(20); - let client_on_b_for_a_height = Height(10); // Should be smaller than `chain_a_start_height` - let client_on_a_for_b_height = Height(20); // Should be smaller than `chain_b_start_height` + let chain_a_start_height = 11_u64.try_into().unwrap(); + let chain_b_start_height = 20_u64.try_into().unwrap(); + let client_on_b_for_a_height = 10_u64.try_into().unwrap(); // Should be smaller than `chain_a_start_height` + let client_on_a_for_b_height = 20_u64.try_into().unwrap(); // Should be smaller than `chain_b_start_height` let max_history_size = 3; let num_iterations = 4; diff --git a/modules/src/ics24_host/path.rs b/modules/src/ics24_host/path.rs index 62a485f403..719d2714f3 100644 --- a/modules/src/ics24_host/path.rs +++ b/modules/src/ics24_host/path.rs @@ -11,7 +11,11 @@ pub const IBC_QUERY_PATH: &str = "store/ibc/key"; pub enum Path { ClientType(ClientId), ClientState(ClientId), - ClientConsensusState(ClientId, u64), + ClientConsensusState { + client_id: ClientId, + epoch: u64, + height: u64, + }, ClientConnections(ClientId), Connections(ConnectionId), Ports(PortId), @@ -19,8 +23,16 @@ pub enum Path { SeqSends(PortId, ChannelId), SeqRecvs(PortId, ChannelId), SeqAcks(PortId, ChannelId), - Commitments(PortId, ChannelId, u64), - Acks(PortId, ChannelId, u64), + Commitments { + port_id: PortId, + channel_id: ChannelId, + sequence: u64, + }, + Acks { + port_id: PortId, + channel_id: ChannelId, + sequence: u64, + }, } impl Path { @@ -44,14 +56,20 @@ impl Path { impl Display for Path { fn fmt(&self, f: &mut Formatter<'_>) -> Result { match &self { - Path::ClientType(id) => write!(f, "clients/{}/clientType", id), - Path::ClientState(id) => write!(f, "clients/{}/clientState", id), - Path::ClientConsensusState(id, height) => { - write!(f, "clients/{}/consensusState/{}", id, height) - } - Path::ClientConnections(id) => write!(f, "clients/{}/connections", id), - Path::Connections(id) => write!(f, "connections/{}", id), - Path::Ports(id) => write!(f, "ports/{}", id), + Path::ClientType(client_id) => write!(f, "clients/{}/clientType", client_id), + Path::ClientState(client_id) => write!(f, "clients/{}/clientState", client_id), + Path::ClientConsensusState { + client_id, + epoch, + height, + } => write!( + f, + "clients/{}/consensusState/{}-{}", + client_id, epoch, height + ), + Path::ClientConnections(client_id) => write!(f, "clients/{}/connections", client_id), + Path::Connections(connection_id) => write!(f, "connections/{}", connection_id), + Path::Ports(port_id) => write!(f, "ports/{}", port_id), Path::ChannelEnds(port_id, channel_id) => { write!(f, "channelEnds/ports/{}/channels/{}", port_id, channel_id) } @@ -70,15 +88,23 @@ impl Display for Path { "seqAcks/ports/{}/channels/{}/nextSequenceAck", port_id, channel_id ), - Path::Commitments(port_id, channel_id, seq) => write!( + Path::Commitments { + port_id, + channel_id, + sequence, + } => write!( f, "commitments/ports/{}/channels/{}/packets/{}", - port_id, channel_id, seq + port_id, channel_id, sequence ), - Path::Acks(port_id, channel_id, seq) => write!( + Path::Acks { + port_id, + channel_id, + sequence, + } => write!( f, "acks/ports/{}/channels/{}/acknowledgements/{}", - port_id, channel_id, seq + port_id, channel_id, sequence ), } } diff --git a/modules/src/ics26_routing/context_mock.rs b/modules/src/ics26_routing/context_mock.rs index 5ab77348c2..79bb2b6667 100644 --- a/modules/src/ics26_routing/context_mock.rs +++ b/modules/src/ics26_routing/context_mock.rs @@ -142,10 +142,11 @@ impl ClientKeeper for MockICS26Context { fn store_consensus_state( &mut self, client_id: ClientId, + height: Height, consensus_state: AnyConsensusState, ) -> Result<(), ICS2Error> { self.client_context - .store_consensus_state(client_id, consensus_state)?; + .store_consensus_state(client_id, height, consensus_state)?; Ok(()) } } diff --git a/modules/src/ics26_routing/handler.rs b/modules/src/ics26_routing/handler.rs index 90b62eaa26..4e0b2e2cd3 100644 --- a/modules/src/ics26_routing/handler.rs +++ b/modules/src/ics26_routing/handler.rs @@ -69,8 +69,9 @@ mod tests { use crate::ics26_routing::msgs::ICS26Envelope; use crate::mock_client::header::MockHeader; use crate::mock_client::state::{MockClientState, MockConsensusState}; + + use std::convert::TryInto; use std::str::FromStr; - use tendermint::block::Height; #[test] fn routing_dispatch() { @@ -87,8 +88,12 @@ mod tests { let msg = MsgCreateAnyClient { client_id: ClientId::from_str("client_id").unwrap(), client_type: ClientType::Mock, - client_state: AnyClientState::from(MockClientState(MockHeader(Height(42)))), - consensus_state: AnyConsensusState::from(MockConsensusState(MockHeader(Height(42)))), + client_state: AnyClientState::from(MockClientState(MockHeader( + 42_u64.try_into().unwrap(), + ))), + consensus_state: AnyConsensusState::from(MockConsensusState(MockHeader( + 42_u64.try_into().unwrap(), + ))), signer: get_dummy_account_id(), }; let envelope = ICS26Envelope::ICS2Msg(ClientMsg::CreateClient(msg)); diff --git a/modules/src/mock_client/client_def.rs b/modules/src/mock_client/client_def.rs index 8c189da0a8..5dfb82edd3 100644 --- a/modules/src/mock_client/client_def.rs +++ b/modules/src/mock_client/client_def.rs @@ -1,7 +1,7 @@ +use crate::ics23_commitment::commitment::CommitmentProof; use crate::ics23_commitment::{commitment::CommitmentPrefix, merkle::apply_prefix}; use crate::ics24_host::identifier::ConnectionId; use crate::{ics02_client::client_def::ClientDef, ics24_host::identifier::ClientId}; -use crate::{ics02_client::state::ClientState, ics23_commitment::commitment::CommitmentProof}; use crate::{ics03_connection::connection::ConnectionEnd, ics24_host::Path}; use crate::mock_client::header::MockHeader; @@ -42,7 +42,8 @@ impl ClientDef for MockClient { _expected_consensus_state: &AnyConsensusState, ) -> Result<(), Box> { let client_prefixed_path = - Path::ClientConsensusState(client_id.clone(), height.value()).to_string(); + // TODO - will pick epoch from new type Height + Path::ClientConsensusState{client_id: client_id.clone(), epoch: 0, height: height.value()}.to_string(); let _path = apply_prefix(prefix, client_prefixed_path)?; diff --git a/modules/src/mock_client/header.rs b/modules/src/mock_client/header.rs index 665d13ec35..97dc87bf4c 100644 --- a/modules/src/mock_client/header.rs +++ b/modules/src/mock_client/header.rs @@ -5,7 +5,7 @@ use crate::ics02_client::header::Header; use ibc_proto::ibc::mock::Header as RawMockHeader; use serde_derive::{Deserialize, Serialize}; -use std::convert::TryFrom; +use std::convert::{TryFrom, TryInto}; use tendermint::block::Height; use tendermint_proto::DomainType; @@ -23,7 +23,14 @@ impl TryFrom for MockHeader { .context("no height in header") .into()); } - Ok(MockHeader(Height(raw.height.unwrap().epoch_height))) + + Ok(MockHeader( + raw.height + .unwrap() + .epoch_height + .try_into() + .map_err(|e| error::Kind::InvalidRawHeader.context(e))?, + )) } } diff --git a/modules/src/mock_client/state.rs b/modules/src/mock_client/state.rs index fe0f123565..dc2ec1dac6 100644 --- a/modules/src/mock_client/state.rs +++ b/modules/src/mock_client/state.rs @@ -40,6 +40,10 @@ pub struct MockClientState(pub MockHeader); impl DomainType for MockClientState {} impl MockClientState { + pub fn latest_height(&self) -> Height { + (self.0).0 + } + pub fn check_header_and_update_state( &self, header: AnyHeader, @@ -136,7 +140,7 @@ impl From for RawMockConsensusState { header: Some(ibc_proto::ibc::mock::Header { height: Some(ibc_proto::ibc::client::Height { epoch_number: 0, - epoch_height: value.height().value(), + epoch_height: value.0.height().into(), }), }), } @@ -155,10 +159,6 @@ impl ConsensusState for MockConsensusState { todo!() } - fn height(&self) -> Height { - self.0.height() - } - fn root(&self) -> &CommitmentRoot { todo!() } diff --git a/modules/src/proofs.rs b/modules/src/proofs.rs index 6983261cf7..e79cac3145 100644 --- a/modules/src/proofs.rs +++ b/modules/src/proofs.rs @@ -1,7 +1,9 @@ use crate::ics23_commitment::commitment::CommitmentProof; -use serde_derive::{Deserialize, Serialize}; use tendermint::block::Height; +use serde_derive::{Deserialize, Serialize}; +use std::convert::TryInto; + #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Proofs { object_proof: CommitmentProof, @@ -30,7 +32,7 @@ impl Proofs { object_proof, client_proof, consensus_proof, - height: Height(height), + height: height.try_into().unwrap(), }) } @@ -73,7 +75,7 @@ impl ConsensusProof { Ok(Self { proof: consensus_proof, - height: Height(consensus_height), + height: consensus_height.try_into().unwrap(), // FIXME: unwrap }) } diff --git a/proto/Cargo.toml b/proto/Cargo.toml index 14ef9c53f1..ca7e1214c2 100644 --- a/proto/Cargo.toml +++ b/proto/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ibc-proto" -version = "0.3.0" +version = "0.4.0" authors = ["Greg Szabo "] edition = "2018" license = "Apache-2.0" diff --git a/proto/src/prost/cosmos.base.abci.v1beta1.rs b/proto/src/prost/cosmos.base.abci.v1beta1.rs index 46a6885fc4..a7c3d20d39 100644 --- a/proto/src/prost/cosmos.base.abci.v1beta1.rs +++ b/proto/src/prost/cosmos.base.abci.v1beta1.rs @@ -17,7 +17,8 @@ pub struct TxResponse { /// Result bytes, if any. #[prost(string, tag="5")] pub data: std::string::String, - /// The output of the application's logger (raw string). May be non-deterministic. + /// The output of the application's logger (raw string). May be + /// non-deterministic. #[prost(string, tag="6")] pub raw_log: std::string::String, /// The output of the application's logger (typed). May be non-deterministic. @@ -35,8 +36,9 @@ pub struct TxResponse { /// The request transaction bytes. #[prost(message, optional, tag="11")] pub tx: ::std::option::Option<::prost_types::Any>, - /// Time of the previous block. For heights > 1, it's the weighted median of the - /// timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. + /// Time of the previous block. For heights > 1, it's the weighted median of + /// the timestamps of the valid votes in the block.LastCommit. For height == 1, + /// it's genesis time. #[prost(string, tag="12")] pub timestamp: std::string::String, } @@ -83,15 +85,15 @@ pub struct GasInfo { /// Result is the union of ResponseFormat and ResponseCheckTx. #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { - /// Data is any data returned from message or handler execution. It MUST be length - /// prefixed in order to separate data from multiple message executions. + /// Data is any data returned from message or handler execution. It MUST be + /// length prefixed in order to separate data from multiple message executions. #[prost(bytes, tag="1")] pub data: std::vec::Vec, /// Log contains the log information from message or handler execution. #[prost(string, tag="2")] pub log: std::string::String, - /// Events contains a slice of Event objects that were emitted during message or - /// handler execution. + /// Events contains a slice of Event objects that were emitted during message + /// or handler execution. #[prost(message, repeated, tag="3")] pub events: ::std::vec::Vec, } @@ -104,7 +106,8 @@ pub struct SimulationResponse { #[prost(message, optional, tag="2")] pub result: ::std::option::Option, } -/// MsgData defines the data returned in a Result object during message execution. +/// MsgData defines the data returned in a Result object during message +/// execution. #[derive(Clone, PartialEq, ::prost::Message)] pub struct MsgData { #[prost(string, tag="1")] @@ -112,10 +115,32 @@ pub struct MsgData { #[prost(bytes, tag="2")] pub data: std::vec::Vec, } -/// TxMsgData defines a list of MsgData. A transaction will have a MsgData object for -/// each message. +/// TxMsgData defines a list of MsgData. A transaction will have a MsgData object +/// for each message. #[derive(Clone, PartialEq, ::prost::Message)] pub struct TxMsgData { #[prost(message, repeated, tag="1")] pub data: ::std::vec::Vec, } +/// SearchTxsResult defines a structure for querying txs pageable +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SearchTxsResult { + /// Count of all txs + #[prost(uint64, tag="1")] + pub total_count: u64, + /// Count of txs in current page + #[prost(uint64, tag="2")] + pub count: u64, + /// Index of current page, start from 1 + #[prost(uint64, tag="3")] + pub page_number: u64, + /// Count of total pages + #[prost(uint64, tag="4")] + pub page_total: u64, + /// Max count txs per page + #[prost(uint64, tag="5")] + pub limit: u64, + /// List of txs in current page + #[prost(message, repeated, tag="6")] + pub txs: ::std::vec::Vec, +} diff --git a/proto/src/prost/cosmos.base.crypto.v1beta1.rs b/proto/src/prost/cosmos.base.crypto.v1beta1.rs index 209bb8fadb..cc977fed42 100644 --- a/proto/src/prost/cosmos.base.crypto.v1beta1.rs +++ b/proto/src/prost/cosmos.base.crypto.v1beta1.rs @@ -27,8 +27,8 @@ pub mod public_key { AnyPubkey(::prost_types::Any), } } -/// PubKeyMultisigThreshold specifies a public key type which nests multiple public -/// keys and a threshold +/// PubKeyMultisigThreshold specifies a public key type which nests multiple +/// public keys and a threshold #[derive(Clone, PartialEq, ::prost::Message)] pub struct PubKeyMultisigThreshold { #[prost(uint32, tag="1")] @@ -37,8 +37,8 @@ pub struct PubKeyMultisigThreshold { pub public_keys: ::std::vec::Vec, } /// MultiSignature wraps the signatures from a PubKeyMultisigThreshold. -/// See cosmos.tx.v1betata1.ModeInfo.Multi for how to specify which signers signed and -/// with which modes. +/// See cosmos.tx.v1betata1.ModeInfo.Multi for how to specify which signers +/// signed and with which modes. #[derive(Clone, PartialEq, ::prost::Message)] pub struct MultiSignature { #[prost(bytes, repeated, tag="1")] diff --git a/proto/src/prost/cosmos.base.query.v1beta1.rs b/proto/src/prost/cosmos.base.query.v1beta1.rs index fa2095aba8..dc782f4683 100644 --- a/proto/src/prost/cosmos.base.query.v1beta1.rs +++ b/proto/src/prost/cosmos.base.query.v1beta1.rs @@ -22,13 +22,14 @@ pub struct PageRequest { #[prost(uint64, tag="3")] pub limit: u64, /// count_total is set to true to indicate that the result set should include - /// a count of the total number of items available for pagination in UIs. count_total - /// is only respected when offset is used. It is ignored when key is set. + /// a count of the total number of items available for pagination in UIs. + /// count_total is only respected when offset is used. It is ignored when key + /// is set. #[prost(bool, tag="4")] pub count_total: bool, } -/// PageResponse is to be embedded in gRPC response messages where the corresponding -/// request message has used PageRequest. +/// PageResponse is to be embedded in gRPC response messages where the +/// corresponding request message has used PageRequest. /// /// message SomeResponse { /// repeated Bar results = 1; diff --git a/proto/src/prost/cosmos.base.reflection.v1beta1.rs b/proto/src/prost/cosmos.base.reflection.v1beta1.rs index 5efb6fed77..876de47b3e 100644 --- a/proto/src/prost/cosmos.base.reflection.v1beta1.rs +++ b/proto/src/prost/cosmos.base.reflection.v1beta1.rs @@ -9,14 +9,16 @@ pub struct ListAllInterfacesResponse { #[prost(string, repeated, tag="1")] pub interface_names: ::std::vec::Vec, } -/// ListImplementationsRequest is the request type of the ListImplementations RPC. +/// ListImplementationsRequest is the request type of the ListImplementations +/// RPC. #[derive(Clone, PartialEq, ::prost::Message)] pub struct ListImplementationsRequest { /// interface_name defines the interface to query the implementations for. #[prost(string, tag="1")] pub interface_name: std::string::String, } -/// ListImplementationsResponse is the response type of the ListImplementations RPC. +/// ListImplementationsResponse is the response type of the ListImplementations +/// RPC. #[derive(Clone, PartialEq, ::prost::Message)] pub struct ListImplementationsResponse { #[prost(string, repeated, tag="1")] diff --git a/proto/src/prost/cosmos.base.store.v1beta1.rs b/proto/src/prost/cosmos.base.store.v1beta1.rs index 4879075575..0021d3b1a0 100644 --- a/proto/src/prost/cosmos.base.store.v1beta1.rs +++ b/proto/src/prost/cosmos.base.store.v1beta1.rs @@ -25,3 +25,38 @@ pub struct CommitId { #[prost(bytes, tag="2")] pub hash: std::vec::Vec, } +/// SnapshotItem is an item contained in a rootmulti.Store snapshot. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SnapshotItem { + /// item is the specific type of snapshot item. + #[prost(oneof="snapshot_item::Item", tags="1, 2")] + pub item: ::std::option::Option, +} +pub mod snapshot_item { + /// item is the specific type of snapshot item. + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Item { + #[prost(message, tag="1")] + Store(super::SnapshotStoreItem), + #[prost(message, tag="2")] + Iavl(super::SnapshotIavlItem), + } +} +/// SnapshotStoreItem contains metadata about a snapshotted store. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SnapshotStoreItem { + #[prost(string, tag="1")] + pub name: std::string::String, +} +/// SnapshotIAVLItem is an exported IAVL node. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SnapshotIavlItem { + #[prost(bytes, tag="1")] + pub key: std::vec::Vec, + #[prost(bytes, tag="2")] + pub value: std::vec::Vec, + #[prost(int64, tag="3")] + pub version: i64, + #[prost(int32, tag="4")] + pub height: i32, +} diff --git a/proto/src/prost/cosmos.tx.signing.v1beta1.rs b/proto/src/prost/cosmos.tx.signing.v1beta1.rs index 411407cbed..1108a57a13 100644 --- a/proto/src/prost/cosmos.tx.signing.v1beta1.rs +++ b/proto/src/prost/cosmos.tx.signing.v1beta1.rs @@ -5,14 +5,15 @@ pub struct SignatureDescriptors { #[prost(message, repeated, tag="1")] pub signatures: ::std::vec::Vec, } -/// SignatureDescriptor is a convenience type which represents the full data for a -/// signature including the public key of the signer, signing modes and the signature -/// itself. It is primarily used for coordinating signatures between clients. +/// SignatureDescriptor is a convenience type which represents the full data for +/// a signature including the public key of the signer, signing modes and the +/// signature itself. It is primarily used for coordinating signatures between +/// clients. #[derive(Clone, PartialEq, ::prost::Message)] pub struct SignatureDescriptor { /// public_key is the public key of the signer #[prost(message, optional, tag="1")] - pub public_key: ::std::option::Option, + pub public_key: ::std::option::Option<::prost_types::Any>, #[prost(message, optional, tag="2")] pub data: ::std::option::Option, /// sequence is the sequence of the account, which describes the @@ -66,13 +67,15 @@ pub mod signature_descriptor { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum SignMode { - /// SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected + /// SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be + /// rejected Unspecified = 0, - /// SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified - /// with raw bytes from Tx + /// SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is + /// verified with raw bytes from Tx Direct = 1, - /// SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable - /// textual representation on top of the binary representation from SIGN_MODE_DIRECT + /// SIGN_MODE_TEXTUAL is a future signing mode that will verify some + /// human-readable textual representation on top of the binary representation + /// from SIGN_MODE_DIRECT Textual = 2, /// SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses /// Amino JSON and will be removed in the future diff --git a/proto/src/prost/cosmos.tx.v1beta1.rs b/proto/src/prost/cosmos.tx.v1beta1.rs index fec4a7a5d7..a452c1e442 100644 --- a/proto/src/prost/cosmos.tx.v1beta1.rs +++ b/proto/src/prost/cosmos.tx.v1beta1.rs @@ -4,39 +4,46 @@ pub struct Tx { /// body is the processable content of the transaction #[prost(message, optional, tag="1")] pub body: ::std::option::Option, - /// auth_info is the authorization related content of the transaction, specifically - /// signers, signer modes and fee + /// auth_info is the authorization related content of the transaction, + /// specifically signers, signer modes and fee #[prost(message, optional, tag="2")] pub auth_info: ::std::option::Option, - /// signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to - /// allow connecting signature meta information like public key and signing mode by position. + /// signatures is a list of signatures that matches the length and order of + /// AuthInfo's signer_infos to allow connecting signature meta information like + /// public key and signing mode by position. #[prost(bytes, repeated, tag="3")] pub signatures: ::std::vec::Vec>, } -/// TxRaw is a variant of Tx that pins the signer's exact binary representation of body and -/// auth_info. This is used for signing, broadcasting and verification. The binary -/// `serialize(tx: TxRaw)` is stored in Tendermint and the hash `sha256(serialize(tx: TxRaw))` -/// becomes the "txhash", commonly used as the transaction ID. +/// TxRaw is a variant of Tx that pins the signer's exact binary representation +/// of body and auth_info. This is used for signing, broadcasting and +/// verification. The binary `serialize(tx: TxRaw)` is stored in Tendermint and +/// the hash `sha256(serialize(tx: TxRaw))` becomes the "txhash", commonly used +/// as the transaction ID. #[derive(Clone, PartialEq, ::prost::Message)] pub struct TxRaw { - /// body_bytes is a protobuf serialization of a TxBody that matches the representation in SignDoc. + /// body_bytes is a protobuf serialization of a TxBody that matches the + /// representation in SignDoc. #[prost(bytes, tag="1")] pub body_bytes: std::vec::Vec, - /// auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in SignDoc. + /// auth_info_bytes is a protobuf serialization of an AuthInfo that matches the + /// representation in SignDoc. #[prost(bytes, tag="2")] pub auth_info_bytes: std::vec::Vec, - /// signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to - /// allow connecting signature meta information like public key and signing mode by position. + /// signatures is a list of signatures that matches the length and order of + /// AuthInfo's signer_infos to allow connecting signature meta information like + /// public key and signing mode by position. #[prost(bytes, repeated, tag="3")] pub signatures: ::std::vec::Vec>, } /// SignDoc is the type used for generating sign bytes for SIGN_MODE_DIRECT. #[derive(Clone, PartialEq, ::prost::Message)] pub struct SignDoc { - /// body_bytes is protobuf serialization of a TxBody that matches the representation in TxRaw. + /// body_bytes is protobuf serialization of a TxBody that matches the + /// representation in TxRaw. #[prost(bytes, tag="1")] pub body_bytes: std::vec::Vec, - /// auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in TxRaw. + /// auth_info_bytes is a protobuf serialization of an AuthInfo that matches the + /// representation in TxRaw. #[prost(bytes, tag="2")] pub auth_info_bytes: std::vec::Vec, /// chain_id is the unique identifier of the chain this transaction targets. @@ -51,12 +58,14 @@ pub struct SignDoc { /// TxBody is the body of a transaction that all signers sign over. #[derive(Clone, PartialEq, ::prost::Message)] pub struct TxBody { - /// messages is a list of messages to be executed. The required signers of those messages define - /// the number and order of elements in AuthInfo's signer_infos and Tx's signatures. - /// Each required signer address is added to the list only the first time it occurs. + /// messages is a list of messages to be executed. The required signers of + /// those messages define the number and order of elements in AuthInfo's + /// signer_infos and Tx's signatures. Each required signer address is added to + /// the list only the first time it occurs. /// - /// By convention, the first required signer (usually from the first message) is referred - /// to as the primary signer and pays the fee for the whole transaction. + /// By convention, the first required signer (usually from the first message) + /// is referred to as the primary signer and pays the fee for the whole + /// transaction. #[prost(message, repeated, tag="1")] pub messages: ::std::vec::Vec<::prost_types::Any>, /// memo is any arbitrary memo to be added to the transaction @@ -77,12 +86,14 @@ pub struct TxBody { #[prost(message, repeated, tag="2047")] pub non_critical_extension_options: ::std::vec::Vec<::prost_types::Any>, } -/// AuthInfo describes the fee and signer modes that are used to sign a transaction. +/// AuthInfo describes the fee and signer modes that are used to sign a +/// transaction. #[derive(Clone, PartialEq, ::prost::Message)] pub struct AuthInfo { /// signer_infos defines the signing modes for the required signers. The number - /// and order of elements must match the required signers from TxBody's messages. - /// The first element is the primary signer and the one which pays the fee. + /// and order of elements must match the required signers from TxBody's + /// messages. The first element is the primary signer and the one which pays + /// the fee. #[prost(message, repeated, tag="1")] pub signer_infos: ::std::vec::Vec, /// Fee is the fee and gas limit for the transaction. The first signer is the @@ -92,21 +103,22 @@ pub struct AuthInfo { #[prost(message, optional, tag="2")] pub fee: ::std::option::Option, } -/// SignerInfo describes the public key and signing mode of a single top-level signer. +/// SignerInfo describes the public key and signing mode of a single top-level +/// signer. #[derive(Clone, PartialEq, ::prost::Message)] pub struct SignerInfo { /// public_key is the public key of the signer. It is optional for accounts /// that already exist in state. If unset, the verifier can use the required \ /// signer address for this position and lookup the public key. #[prost(message, optional, tag="1")] - pub public_key: ::std::option::Option, + pub public_key: ::std::option::Option<::prost_types::Any>, /// mode_info describes the signing mode of the signer and is a nested /// structure to support nested multisig pubkey's #[prost(message, optional, tag="2")] pub mode_info: ::std::option::Option, /// sequence is the sequence of the account, which describes the - /// number of committed transactions signed by a given address. It is used to prevent - /// replay attacks. + /// number of committed transactions signed by a given address. It is used to + /// prevent replay attacks. #[prost(uint64, tag="3")] pub sequence: u64, } @@ -120,7 +132,8 @@ pub struct ModeInfo { } pub mod mode_info { /// Single is the mode info for a single signer. It is structured as a message - /// to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the future + /// to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the + /// future #[derive(Clone, PartialEq, ::prost::Message)] pub struct Single { /// mode is the signing mode of the single signer diff --git a/proto/src/prost/ibc.channel.rs b/proto/src/prost/ibc.channel.rs index 59f348ba9f..d62adea59a 100644 --- a/proto/src/prost/ibc.channel.rs +++ b/proto/src/prost/ibc.channel.rs @@ -8,8 +8,8 @@ pub struct MsgChannelOpenInit { pub channel_id: std::string::String, #[prost(message, optional, tag="3")] pub channel: ::std::option::Option, - #[prost(bytes, tag="4")] - pub signer: std::vec::Vec, + #[prost(string, tag="4")] + pub signer: std::string::String, } /// MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel /// on Chain B. @@ -27,8 +27,8 @@ pub struct MsgChannelOpenTry { pub proof_init: std::vec::Vec, #[prost(message, optional, tag="6")] pub proof_height: ::std::option::Option, - #[prost(bytes, tag="7")] - pub signer: std::vec::Vec, + #[prost(string, tag="7")] + pub signer: std::string::String, } /// MsgChannelOpenAck defines a msg sent by a Relayer to Chain A to acknowledge /// the change of channel state to TRYOPEN on Chain B. @@ -44,8 +44,8 @@ pub struct MsgChannelOpenAck { pub proof_try: std::vec::Vec, #[prost(message, optional, tag="5")] pub proof_height: ::std::option::Option, - #[prost(bytes, tag="6")] - pub signer: std::vec::Vec, + #[prost(string, tag="6")] + pub signer: std::string::String, } /// MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to /// acknowledge the change of channel state to OPEN on Chain A. @@ -59,10 +59,10 @@ pub struct MsgChannelOpenConfirm { pub proof_ack: std::vec::Vec, #[prost(message, optional, tag="4")] pub proof_height: ::std::option::Option, - #[prost(bytes, tag="5")] - pub signer: std::vec::Vec, + #[prost(string, tag="5")] + pub signer: std::string::String, } -/// MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain A +/// MsgChannelCloseInit defines a msg sent by a Relayer to Chain A /// to close a channel with Chain B. #[derive(Clone, PartialEq, ::prost::Message)] pub struct MsgChannelCloseInit { @@ -70,8 +70,8 @@ pub struct MsgChannelCloseInit { pub port_id: std::string::String, #[prost(string, tag="2")] pub channel_id: std::string::String, - #[prost(bytes, tag="3")] - pub signer: std::vec::Vec, + #[prost(string, tag="3")] + pub signer: std::string::String, } /// MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B /// to acknowledge the change of channel state to CLOSED on Chain A. @@ -85,8 +85,8 @@ pub struct MsgChannelCloseConfirm { pub proof_init: std::vec::Vec, #[prost(message, optional, tag="4")] pub proof_height: ::std::option::Option, - #[prost(bytes, tag="5")] - pub signer: std::vec::Vec, + #[prost(string, tag="5")] + pub signer: std::string::String, } /// MsgRecvPacket receives incoming IBC packet #[derive(Clone, PartialEq, ::prost::Message)] @@ -97,8 +97,8 @@ pub struct MsgRecvPacket { pub proof: std::vec::Vec, #[prost(message, optional, tag="3")] pub proof_height: ::std::option::Option, - #[prost(bytes, tag="4")] - pub signer: std::vec::Vec, + #[prost(string, tag="4")] + pub signer: std::string::String, } /// MsgTimeout receives timed-out packet #[derive(Clone, PartialEq, ::prost::Message)] @@ -111,8 +111,8 @@ pub struct MsgTimeout { pub proof_height: ::std::option::Option, #[prost(uint64, tag="4")] pub next_sequence_recv: u64, - #[prost(bytes, tag="5")] - pub signer: std::vec::Vec, + #[prost(string, tag="5")] + pub signer: std::string::String, } /// MsgTimeoutOnClose timed-out packet upon counterparty channel closure. #[derive(Clone, PartialEq, ::prost::Message)] @@ -127,8 +127,8 @@ pub struct MsgTimeoutOnClose { pub proof_height: ::std::option::Option, #[prost(uint64, tag="5")] pub next_sequence_recv: u64, - #[prost(bytes, tag="6")] - pub signer: std::vec::Vec, + #[prost(string, tag="6")] + pub signer: std::string::String, } /// MsgAcknowledgement receives incoming IBC acknowledgement #[derive(Clone, PartialEq, ::prost::Message)] @@ -141,8 +141,8 @@ pub struct MsgAcknowledgement { pub proof: std::vec::Vec, #[prost(message, optional, tag="4")] pub proof_height: ::std::option::Option, - #[prost(bytes, tag="5")] - pub signer: std::vec::Vec, + #[prost(string, tag="5")] + pub signer: std::string::String, } /// Channel defines pipeline for exactly-once packet delivery between specific /// modules on separate blockchains, which has at least one end capable of @@ -158,8 +158,8 @@ pub struct Channel { /// counterparty channel end #[prost(message, optional, tag="3")] pub counterparty: ::std::option::Option, - /// list of connection identifiers, in order, along which packets sent on this - /// channel will travel + /// list of connection identifiers, in order, along which packets sent on + /// this channel will travel #[prost(string, repeated, tag="4")] pub connection_hops: ::std::vec::Vec, /// opaque channel version, which is agreed upon during the handshake @@ -179,8 +179,8 @@ pub struct IdentifiedChannel { /// counterparty channel end #[prost(message, optional, tag="3")] pub counterparty: ::std::option::Option, - /// list of connection identifiers, in order, along which packets sent on this - /// channel will travel + /// list of connection identifiers, in order, along which packets sent on + /// this channel will travel #[prost(string, repeated, tag="4")] pub connection_hops: ::std::vec::Vec, /// opaque channel version, which is agreed upon during the handshake @@ -206,9 +206,9 @@ pub struct Counterparty { /// Packet defines a type that carries data across different chains through IBC #[derive(Clone, PartialEq, ::prost::Message)] pub struct Packet { - /// number corresponds to the order of sends and receives, where a Packet with - /// an earlier sequence number must be sent and received before a Packet with a - /// later sequence number. + /// number corresponds to the order of sends and receives, where a Packet + /// with an earlier sequence number must be sent and received before a Packet + /// with a later sequence number. #[prost(uint64, tag="1")] pub sequence: u64, /// identifies the port on the sending chain. @@ -250,6 +250,29 @@ pub struct PacketAckCommitment { #[prost(bytes, tag="4")] pub hash: std::vec::Vec, } +/// Acknowledgement is the recommended acknowledgement format to be used by +/// app-specific protocols. +/// NOTE: The field numbers 21 and 22 were explicitly chosen to avoid accidental +/// conflicts with other protobuf message formats used for acknowledgements. +/// The first byte of any message with this format will be the non-ASCII values +/// `0xaa` (result) or `0xb2` (error). Implemented as defined by ICS: +/// https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics#acknowledgement-envelope +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Acknowledgement { + /// response contains either a result or an error and must be non-empty + #[prost(oneof="acknowledgement::Response", tags="21, 22")] + pub response: ::std::option::Option, +} +pub mod acknowledgement { + /// response contains either a result or an error and must be non-empty + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Response { + #[prost(bytes, tag="21")] + Result(std::vec::Vec), + #[prost(string, tag="22")] + Error(std::string::String), + } +} /// State defines if a channel is in one of the following states: /// CLOSED, INIT, TRYOPEN, OPEN or UNINITIALIZED. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] @@ -536,10 +559,10 @@ pub struct QueryPacketAcknowledgementResponse { #[prost(message, optional, tag="4")] pub proof_height: ::std::option::Option, } -/// QueryUnrelayedPacketsRequest is the request type for the -/// Query/UnrelayedPackets RPC method +/// QueryUnreceivedPacketsRequest is the request type for the +/// Query/UnreceivedPackets RPC method #[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryUnrelayedPacketsRequest { +pub struct QueryUnreceivedPacketsRequest { /// port unique identifier #[prost(string, tag="1")] pub port_id: std::string::String, @@ -549,16 +572,37 @@ pub struct QueryUnrelayedPacketsRequest { /// list of packet sequences #[prost(uint64, repeated, tag="3")] pub packet_commitment_sequences: ::std::vec::Vec, - /// flag indicating if the return value is packet commitments or - /// acknowledgements - #[prost(bool, tag="4")] - pub acknowledgements: bool, } -/// QueryUnrelayedPacketsResponse is the request type for the -/// Query/UnrelayedPacketCommitments RPC method +/// QueryUnreceivedPacketsResponse is the response type for the +/// Query/UnreceivedPacketCommitments RPC method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryUnreceivedPacketsResponse { + /// list of unreceived packet sequences + #[prost(uint64, repeated, tag="1")] + pub sequences: ::std::vec::Vec, + /// query block height + #[prost(message, optional, tag="2")] + pub height: ::std::option::Option, +} +/// QueryUnrelayedAcksRequest is the request type for the +/// Query/UnrelayedAcks RPC method +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryUnrelayedAcksRequest { + /// port unique identifier + #[prost(string, tag="1")] + pub port_id: std::string::String, + /// channel unique identifier + #[prost(string, tag="2")] + pub channel_id: std::string::String, + /// list of commitment sequences + #[prost(uint64, repeated, tag="3")] + pub packet_commitment_sequences: ::std::vec::Vec, +} +/// QueryUnrelayedAcksResponse is the response type for the +/// Query/UnrelayedAcks RPC method #[derive(Clone, PartialEq, ::prost::Message)] -pub struct QueryUnrelayedPacketsResponse { - /// list of unrelayed packet sequences +pub struct QueryUnrelayedAcksResponse { + /// list of unrelayed acknowledgement sequences #[prost(uint64, repeated, tag="1")] pub sequences: ::std::vec::Vec, /// query block height diff --git a/proto/src/prost/ibc.client.rs b/proto/src/prost/ibc.client.rs index 9d8f23dd56..0c94b8366e 100644 --- a/proto/src/prost/ibc.client.rs +++ b/proto/src/prost/ibc.client.rs @@ -1,4 +1,4 @@ -/// IdentifiedClientState defines a client state with additional client +/// IdentifiedClientState defines a client state with an additional client /// identifier field. #[derive(Clone, PartialEq, ::prost::Message)] pub struct IdentifiedClientState { @@ -9,6 +9,16 @@ pub struct IdentifiedClientState { #[prost(message, optional, tag="2")] pub client_state: ::std::option::Option<::prost_types::Any>, } +/// ConsensusStateWithHeight defines a consensus state with an additional height field. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ConsensusStateWithHeight { + /// consensus state height + #[prost(message, optional, tag="1")] + pub height: ::std::option::Option, + /// consensus state + #[prost(message, optional, tag="2")] + pub consensus_state: ::std::option::Option<::prost_types::Any>, +} /// ClientConsensusStates defines all the stored consensus states for a given /// client. #[derive(Clone, PartialEq, ::prost::Message)] @@ -16,9 +26,27 @@ pub struct ClientConsensusStates { /// client identifier #[prost(string, tag="1")] pub client_id: std::string::String, - /// consensus states associated with the client + /// consensus states and their heights associated with the client #[prost(message, repeated, tag="2")] - pub consensus_states: ::std::vec::Vec<::prost_types::Any>, + pub consensus_states: ::std::vec::Vec, +} +/// ClientUpdateProposal is a governance proposal. If it passes, the client is +/// updated with the provided header. The update may fail if the header is not +/// valid given certain conditions specified by the client implementation. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ClientUpdateProposal { + /// the title of the update proposal + #[prost(string, tag="1")] + pub title: std::string::String, + /// the description of the proposal + #[prost(string, tag="2")] + pub description: std::string::String, + /// the client identifier for the client to be updated if the proposal passes + #[prost(string, tag="3")] + pub client_id: std::string::String, + /// the header used to update the client if the proposal passes + #[prost(message, optional, tag="4")] + pub header: ::std::option::Option<::prost_types::Any>, } /// MsgCreateClient defines a message to create an IBC client #[derive(Clone, PartialEq, ::prost::Message)] @@ -34,8 +62,8 @@ pub struct MsgCreateClient { #[prost(message, optional, tag="3")] pub consensus_state: ::std::option::Option<::prost_types::Any>, /// signer address - #[prost(bytes, tag="4")] - pub signer: std::vec::Vec, + #[prost(string, tag="4")] + pub signer: std::string::String, } /// MsgUpdateClient defines an sdk.Msg to update a IBC client state using /// the given header. @@ -48,8 +76,8 @@ pub struct MsgUpdateClient { #[prost(message, optional, tag="2")] pub header: ::std::option::Option<::prost_types::Any>, /// signer address - #[prost(bytes, tag="3")] - pub signer: std::vec::Vec, + #[prost(string, tag="3")] + pub signer: std::string::String, } /// MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for /// light client misbehaviour. @@ -62,8 +90,8 @@ pub struct MsgSubmitMisbehaviour { #[prost(message, optional, tag="2")] pub misbehaviour: ::std::option::Option<::prost_types::Any>, /// signer address - #[prost(bytes, tag="3")] - pub signer: std::vec::Vec, + #[prost(string, tag="3")] + pub signer: std::string::String, } /// Height is a monotonically increasing data type /// that can be compared against another Height for the purposes of updating and @@ -141,24 +169,27 @@ pub struct QueryClientStatesResponse { #[prost(message, optional, tag="2")] pub pagination: ::std::option::Option, } -/// QueryConsensusStateRequest is the request type for the Query/ConsensusState RPC method. Besides -/// the consensus state, it includes a proof and the height from which the proof was retrieved. +/// QueryConsensusStateRequest is the request type for the Query/ConsensusState +/// RPC method. Besides the consensus state, it includes a proof and the height +/// from which the proof was retrieved. #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryConsensusStateRequest { /// client identifier #[prost(string, tag="1")] pub client_id: std::string::String, - /// consensus state epoch number + /// consensus state epoch number #[prost(uint64, tag="2")] pub epoch_number: u64, /// consensus state epoch height #[prost(uint64, tag="3")] pub epoch_height: u64, - /// latest_height overrrides the height field and queries the latest stored ConsensusState + /// latest_height overrrides the height field and queries the latest stored + /// ConsensusState #[prost(bool, tag="4")] pub latest_height: bool, } -/// QueryConsensusStateResponse is the response type for the Query/ConsensusState RPC method +/// QueryConsensusStateResponse is the response type for the Query/ConsensusState +/// RPC method #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryConsensusStateResponse { /// consensus state associated with the client identifier at the given height @@ -174,7 +205,8 @@ pub struct QueryConsensusStateResponse { #[prost(message, optional, tag="4")] pub proof_height: ::std::option::Option, } -/// QueryConsensusStatesRequest is the request type for the Query/ConsensusStates RPC method. +/// QueryConsensusStatesRequest is the request type for the Query/ConsensusStates +/// RPC method. #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryConsensusStatesRequest { /// client identifier @@ -184,12 +216,13 @@ pub struct QueryConsensusStatesRequest { #[prost(message, optional, tag="2")] pub pagination: ::std::option::Option, } -/// QueryConsensusStatesResponse is the response type for the Query/ConsensusStates RPC method +/// QueryConsensusStatesResponse is the response type for the +/// Query/ConsensusStates RPC method #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryConsensusStatesResponse { /// consensus states associated with the identifier #[prost(message, repeated, tag="1")] - pub consensus_states: ::std::vec::Vec<::prost_types::Any>, + pub consensus_states: ::std::vec::Vec, /// pagination response #[prost(message, optional, tag="2")] pub pagination: ::std::option::Option, diff --git a/proto/src/prost/ibc.commitment.rs b/proto/src/prost/ibc.commitment.rs index 41064feb1c..1bee8a0fdd 100644 --- a/proto/src/prost/ibc.commitment.rs +++ b/proto/src/prost/ibc.commitment.rs @@ -6,23 +6,24 @@ pub struct MerkleRoot { pub hash: std::vec::Vec, } /// MerklePrefix is merkle path prefixed to the key. -/// The constructed key from the Path and the key will be append(Path.KeyPath, append(Path.KeyPrefix, key...)) +/// The constructed key from the Path and the key will be append(Path.KeyPath, +/// append(Path.KeyPrefix, key...)) #[derive(Clone, PartialEq, ::prost::Message)] pub struct MerklePrefix { #[prost(bytes, tag="1")] pub key_prefix: std::vec::Vec, } -/// MerklePath is the path used to verify commitment proofs, which can be an arbitrary -/// structured object (defined by a commitment type). +/// MerklePath is the path used to verify commitment proofs, which can be an +/// arbitrary structured object (defined by a commitment type). #[derive(Clone, PartialEq, ::prost::Message)] pub struct MerklePath { #[prost(message, optional, tag="1")] pub key_path: ::std::option::Option, } /// MerkleProof is a wrapper type that contains a merkle proof. -/// It demonstrates membership or non-membership for an element or set of elements, -/// verifiable in conjunction with a known commitment root. Proofs should be -/// succinct. +/// It demonstrates membership or non-membership for an element or set of +/// elements, verifiable in conjunction with a known commitment root. Proofs +/// should be succinct. #[derive(Clone, PartialEq, ::prost::Message)] pub struct MerkleProof { #[prost(message, optional, tag="1")] diff --git a/proto/src/prost/ibc.connection.rs b/proto/src/prost/ibc.connection.rs index e58709b876..4ad6835591 100644 --- a/proto/src/prost/ibc.connection.rs +++ b/proto/src/prost/ibc.connection.rs @@ -8,8 +8,8 @@ pub struct MsgConnectionOpenInit { pub connection_id: std::string::String, #[prost(message, optional, tag="3")] pub counterparty: ::std::option::Option, - #[prost(bytes, tag="4")] - pub signer: std::vec::Vec, + #[prost(string, tag="4")] + pub signer: std::string::String, } /// MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a /// connection on Chain B. @@ -39,8 +39,8 @@ pub struct MsgConnectionOpenTry { pub proof_consensus: std::vec::Vec, #[prost(message, optional, tag="10")] pub consensus_height: ::std::option::Option, - #[prost(bytes, tag="11")] - pub signer: std::vec::Vec, + #[prost(string, tag="11")] + pub signer: std::string::String, } /// MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to /// acknowledge the change of connection state to TRYOPEN on Chain B. @@ -66,8 +66,8 @@ pub struct MsgConnectionOpenAck { pub proof_consensus: std::vec::Vec, #[prost(message, optional, tag="8")] pub consensus_height: ::std::option::Option, - #[prost(bytes, tag="9")] - pub signer: std::vec::Vec, + #[prost(string, tag="9")] + pub signer: std::string::String, } /// MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to /// acknowledge the change of connection state to OPEN on Chain A. @@ -80,8 +80,8 @@ pub struct MsgConnectionOpenConfirm { pub proof_ack: std::vec::Vec, #[prost(message, optional, tag="3")] pub proof_height: ::std::option::Option, - #[prost(bytes, tag="4")] - pub signer: std::vec::Vec, + #[prost(string, tag="4")] + pub signer: std::string::String, } // ICS03 - Connection Data Structures as defined in // https://github.com/cosmos/ics/tree/master/spec/ics-003-connection-semantics#data-structures diff --git a/proto/src/prost/ibc.lightclients.solomachine.v1.rs b/proto/src/prost/ibc.lightclients.solomachine.v1.rs index 8c4ec7ca48..34d45af3cb 100644 --- a/proto/src/prost/ibc.lightclients.solomachine.v1.rs +++ b/proto/src/prost/ibc.lightclients.solomachine.v1.rs @@ -2,21 +2,30 @@ /// state and if the client is frozen. #[derive(Clone, PartialEq, ::prost::Message)] pub struct ClientState { - /// frozen sequence of the solo machine + /// latest sequence of the client state #[prost(uint64, tag="1")] + pub sequence: u64, + /// frozen sequence of the solo machine + #[prost(uint64, tag="2")] pub frozen_sequence: u64, - #[prost(message, optional, tag="2")] + #[prost(message, optional, tag="3")] pub consensus_state: ::std::option::Option, + /// when set to true, will allow governance to update a solo machine client. + /// The client will be unfrozen if it is frozen. + #[prost(bool, tag="4")] + pub allow_update_after_proposal: bool, } -/// ConsensusState defines a solo machine consensus state +/// ConsensusState defines a solo machine consensus state. The sequence of a consensus state +/// is contained in the "height" key used in storing the consensus state. #[derive(Clone, PartialEq, ::prost::Message)] pub struct ConsensusState { - /// current sequence of the consensus state - #[prost(uint64, tag="1")] - pub sequence: u64, /// public key of the solo machine - #[prost(message, optional, tag="2")] - pub public_key: ::std::option::Option, + #[prost(message, optional, tag="1")] + pub public_key: ::std::option::Option<::prost_types::Any>, + /// diversifier allows the same public key to be re-used across different solo machine clients + /// (potentially on different chains) without being considered misbehaviour. + #[prost(string, tag="2")] + pub diversifier: std::string::String, #[prost(uint64, tag="3")] pub timestamp: u64, } @@ -26,10 +35,14 @@ pub struct Header { /// sequence to update solo machine public key at #[prost(uint64, tag="1")] pub sequence: u64, - #[prost(bytes, tag="2")] + #[prost(uint64, tag="2")] + pub timestamp: u64, + #[prost(bytes, tag="3")] pub signature: std::vec::Vec, - #[prost(message, optional, tag="3")] - pub new_public_key: ::std::option::Option, + #[prost(message, optional, tag="4")] + pub new_public_key: ::std::option::Option<::prost_types::Any>, + #[prost(string, tag="5")] + pub new_diversifier: std::string::String, } /// Misbehaviour defines misbehaviour for a solo machine which consists /// of a sequence and two signatures over different messages at that sequence. @@ -62,3 +75,95 @@ pub struct TimestampedSignature { #[prost(uint64, tag="2")] pub timestamp: u64, } +/// SignBytes defines the signed bytes used for signature verification. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SignBytes { + #[prost(uint64, tag="1")] + pub sequence: u64, + #[prost(uint64, tag="2")] + pub timestamp: u64, + #[prost(string, tag="3")] + pub diversifier: std::string::String, + /// marshaled data + #[prost(bytes, tag="4")] + pub data: std::vec::Vec, +} +/// HeaderData returns the SignBytes data for misbehaviour verification. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct HeaderData { + /// header public key + #[prost(message, optional, tag="1")] + pub new_pub_key: ::std::option::Option<::prost_types::Any>, + /// header diversifier + #[prost(string, tag="2")] + pub new_diversifier: std::string::String, +} +/// ClientStateData returns the SignBytes data for client state verification. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ClientStateData { + #[prost(bytes, tag="1")] + pub path: std::vec::Vec, + #[prost(message, optional, tag="2")] + pub client_state: ::std::option::Option<::prost_types::Any>, +} +/// ConsensusStateSignBytes returns the SignBytes data for consensus state +/// verification. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ConsensusStateData { + #[prost(bytes, tag="1")] + pub path: std::vec::Vec, + #[prost(message, optional, tag="2")] + pub consensus_state: ::std::option::Option<::prost_types::Any>, +} +/// ConnectionStateSignBytes returns the SignBytes data for connection state +/// verification. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ConnectionStateData { + #[prost(bytes, tag="1")] + pub path: std::vec::Vec, + #[prost(message, optional, tag="2")] + pub connection: ::std::option::Option, +} +/// ChannelStateSignBytes returns the SignBytes data for channel state +/// verification. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ChannelStateData { + #[prost(bytes, tag="1")] + pub path: std::vec::Vec, + #[prost(message, optional, tag="2")] + pub channel: ::std::option::Option, +} +/// PacketCommitmentSignBytes returns the SignBytes data for packet commitment +/// verification. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PacketCommitmentData { + #[prost(bytes, tag="1")] + pub path: std::vec::Vec, + #[prost(bytes, tag="2")] + pub commitment: std::vec::Vec, +} +/// PacketAcknowledgementSignBytes returns the SignBytes data for acknowledgement +/// verification. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PacketAcknowledgementData { + #[prost(bytes, tag="1")] + pub path: std::vec::Vec, + #[prost(bytes, tag="2")] + pub acknowledgement: std::vec::Vec, +} +/// PacketAcknowledgementAbsenceSignBytes returns the SignBytes data for +/// acknowledgement absence verification. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PacketAcknowledgementAbsenseData { + #[prost(bytes, tag="1")] + pub path: std::vec::Vec, +} +/// NextSequenceRecv returns the SignBytes data for verification of the next +/// sequence to be received. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NextSequenceRecvData { + #[prost(bytes, tag="1")] + pub path: std::vec::Vec, + #[prost(uint64, tag="2")] + pub next_seq_recv: u64, +} diff --git a/proto/src/prost/ibc.tendermint.rs b/proto/src/prost/ibc.tendermint.rs index 3213c8b12d..a5ecd88ae2 100644 --- a/proto/src/prost/ibc.tendermint.rs +++ b/proto/src/prost/ibc.tendermint.rs @@ -25,6 +25,14 @@ pub struct ClientState { /// Proof specifications used in verifying counterparty state #[prost(message, repeated, tag="8")] pub proof_specs: ::std::vec::Vec, + /// This flag, when set to true, will allow governance to recover a client + /// which has expired + #[prost(bool, tag="9")] + pub allow_update_after_expiry: bool, + /// This flag, when set to true, will allow governance to unfreeze a client + /// whose chain has experienced a misbehaviour event + #[prost(bool, tag="10")] + pub allow_update_after_misbehaviour: bool, } /// ConsensusState defines the consensus state from Tendermint. #[derive(Clone, PartialEq, ::prost::Message)] @@ -36,10 +44,7 @@ pub struct ConsensusState { /// commitment root (i.e app hash) #[prost(message, optional, tag="2")] pub root: ::std::option::Option, - /// height at which the consensus state was stored. - #[prost(message, optional, tag="3")] - pub height: ::std::option::Option, - #[prost(bytes, tag="4")] + #[prost(bytes, tag="3")] pub next_validators_hash: std::vec::Vec, } /// Misbehaviour is a wrapper over two conflicting Headers diff --git a/proto/src/prost/ibc.transfer.rs b/proto/src/prost/ibc.transfer.rs index d86fec1e53..4c209a3d4f 100644 --- a/proto/src/prost/ibc.transfer.rs +++ b/proto/src/prost/ibc.transfer.rs @@ -13,8 +13,8 @@ pub struct MsgTransfer { #[prost(message, optional, tag="3")] pub token: ::std::option::Option, /// the sender address - #[prost(bytes, tag="4")] - pub sender: std::vec::Vec, + #[prost(string, tag="4")] + pub sender: std::string::String, /// the recipient address on the destination chain #[prost(string, tag="5")] pub receiver: std::string::String, @@ -45,23 +45,12 @@ pub struct FungibleTokenPacketData { #[prost(string, tag="4")] pub receiver: std::string::String, } -/// FungibleTokenPacketAcknowledgement contains a boolean success flag and an -/// optional error msg error msg is empty string on success See spec for -/// onAcknowledgePacket: -/// https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct FungibleTokenPacketAcknowledgement { - #[prost(bool, tag="1")] - pub success: bool, - #[prost(string, tag="2")] - pub error: std::string::String, -} -/// DenomTrace contains the base denomination for ICS20 fungible tokens and the source tracing -/// information path. +/// DenomTrace contains the base denomination for ICS20 fungible tokens and the +/// source tracing information path. #[derive(Clone, PartialEq, ::prost::Message)] pub struct DenomTrace { - /// path defines the chain of port/channel identifiers used for tracing the source of the fungible - /// token. + /// path defines the chain of port/channel identifiers used for tracing the + /// source of the fungible token. #[prost(string, tag="1")] pub path: std::string::String, /// base denomination of the relayed fungible token. @@ -69,39 +58,46 @@ pub struct DenomTrace { pub base_denom: std::string::String, } /// Params defines the set of IBC transfer parameters. -/// NOTE: To prevent a single token from being transferred, set the TransfersEnabled parameter to -/// true and then set the bank module's SendEnabled parameter for the denomination to false. +/// NOTE: To prevent a single token from being transferred, set the +/// TransfersEnabled parameter to true and then set the bank module's SendEnabled +/// parameter for the denomination to false. #[derive(Clone, PartialEq, ::prost::Message)] pub struct Params { - /// send_enabled enables or disables all cross-chain token transfers from this chain. + /// send_enabled enables or disables all cross-chain token transfers from this + /// chain. #[prost(bool, tag="1")] pub send_enabled: bool, - /// receive_enabled enables or disables all cross-chain token transfers to this chain. + /// receive_enabled enables or disables all cross-chain token transfers to this + /// chain. #[prost(bool, tag="2")] pub receive_enabled: bool, } -/// QueryDenomTraceRequest is the request type for the Query/DenomTrace RPC method +/// QueryDenomTraceRequest is the request type for the Query/DenomTrace RPC +/// method #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryDenomTraceRequest { /// hash (in hex format) of the denomination trace information. #[prost(string, tag="1")] pub hash: std::string::String, } -/// QueryDenomTraceResponse is the response type for the Query/DenomTrace RPC method. +/// QueryDenomTraceResponse is the response type for the Query/DenomTrace RPC +/// method. #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryDenomTraceResponse { /// denom_trace returns the requested denomination trace information. #[prost(message, optional, tag="1")] pub denom_trace: ::std::option::Option, } -/// QueryConnectionsRequest is the request type for the Query/DenomTraces RPC method +/// QueryConnectionsRequest is the request type for the Query/DenomTraces RPC +/// method #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryDenomTracesRequest { /// pagination defines an optional pagination for the request. #[prost(message, optional, tag="1")] pub pagination: ::std::option::Option, } -/// QueryConnectionsResponse is the response type for the Query/DenomTraces RPC method. +/// QueryConnectionsResponse is the response type for the Query/DenomTraces RPC +/// method. #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryDenomTracesResponse { /// denom_traces returns all denominations trace information. diff --git a/proto/src/prost/tendermint.abci.rs b/proto/src/prost/tendermint.abci.rs index 6bb352dff8..14dec5bb9f 100644 --- a/proto/src/prost/tendermint.abci.rs +++ b/proto/src/prost/tendermint.abci.rs @@ -505,8 +505,8 @@ pub struct VoteInfo { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Evidence { - #[prost(string, tag="1")] - pub r#type: std::string::String, + #[prost(enumeration="EvidenceType", tag="1")] + pub r#type: i32, /// The offending validator #[prost(message, optional, tag="2")] pub validator: ::std::option::Option, @@ -549,3 +549,10 @@ pub enum CheckTxType { New = 0, Recheck = 1, } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum EvidenceType { + Unknown = 0, + DuplicateVote = 1, + LightClientAttack = 2, +} diff --git a/proto/src/prost/tendermint.crypto.rs b/proto/src/prost/tendermint.crypto.rs index e459e853c8..928ddb94da 100644 --- a/proto/src/prost/tendermint.crypto.rs +++ b/proto/src/prost/tendermint.crypto.rs @@ -58,17 +58,3 @@ pub mod public_key { Ed25519(std::vec::Vec), } } -/// PrivateKey defines the keys available for use with Tendermint Validators -/// WARNING PrivateKey is used for internal purposes only -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PrivateKey { - #[prost(oneof="private_key::Sum", tags="1")] - pub sum: ::std::option::Option, -} -pub mod private_key { - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Sum { - #[prost(bytes, tag="1")] - Ed25519(std::vec::Vec), - } -} diff --git a/proto/src/prost/tendermint.types.rs b/proto/src/prost/tendermint.types.rs index fdfbd68c16..7cff7e0cb1 100644 --- a/proto/src/prost/tendermint.types.rs +++ b/proto/src/prost/tendermint.types.rs @@ -188,6 +188,13 @@ pub struct SignedHeader { pub commit: ::std::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] +pub struct LightBlock { + #[prost(message, optional, tag="1")] + pub signed_header: ::std::option::Option, + #[prost(message, optional, tag="2")] + pub validator_set: ::std::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] pub struct BlockMeta { #[prost(message, optional, tag="1")] pub block_id: ::std::option::Option, @@ -281,11 +288,6 @@ pub struct EvidenceParams { /// Default is 50 #[prost(uint32, tag="3")] pub max_num: u32, - /// Proof trial period dictates the time given for nodes accused of amnesia evidence, incorrectly - /// voting twice in two different rounds to respond with their respective proofs. - /// Default is half the max age in blocks: 50,000 - #[prost(int64, tag="4")] - pub proof_trial_period: i64, } /// ValidatorParams restrict the public key types validators can use. /// NOTE: uses ABCI pubkey naming, not Amino names. diff --git a/relayer-cli/src/commands/light/init.rs b/relayer-cli/src/commands/light/init.rs index c493b86c72..6d1c0de15b 100644 --- a/relayer-cli/src/commands/light/init.rs +++ b/relayer-cli/src/commands/light/init.rs @@ -38,7 +38,7 @@ struct InitOptions { impl InitOptions { fn from_init_cmd(cmd: &InitCmd) -> Result { - match (cmd.chain_id, cmd.hash, cmd.height) { + match (cmd.chain_id.clone(), cmd.hash, cmd.height) { (Some(chain_id), Some(hash), Some(height)) => Ok(Self { chain_id, trusted_hash: hash, @@ -72,11 +72,11 @@ impl InitCmd { )?; let mut config = LightConfig::load(LIGHT_CONFIG_PATH)?; - config.chains.insert(chain_config.id, trust_options); + config.chains.insert(chain_config.id.clone(), trust_options); config.save(LIGHT_CONFIG_PATH)?; status_ok!( - chain_config.id, + chain_config.id.clone(), "Set trusted options: hash={} height={}", options.trusted_hash, options.trusted_height diff --git a/relayer-cli/src/commands/query/channel.rs b/relayer-cli/src/commands/query/channel.rs index 8505171661..708c1b2ec1 100644 --- a/relayer-cli/src/commands/query/channel.rs +++ b/relayer-cli/src/commands/query/channel.rs @@ -13,6 +13,8 @@ use relayer::chain::{Chain, CosmosSDKChain}; use tendermint::chain::Id as ChainId; use tendermint_proto::DomainType; +use std::convert::TryInto; + #[derive(Clone, Command, Debug, Options)] pub struct QueryChannelEndCmd { #[options(free, help = "identifier of the chain to query")] @@ -46,6 +48,7 @@ impl QueryChannelEndCmd { ) -> Result<(ChainConfig, QueryChannelOptions), String> { let chain_id = self .chain_id + .clone() .ok_or_else(|| "missing chain identifier".to_string())?; let chain_config = config .chains @@ -102,7 +105,7 @@ impl Runnable for QueryChannelEndCmd { let res: Result = chain .query( ChannelEnds(opts.port_id, opts.channel_id), - opts.height, + opts.height.try_into().unwrap(), opts.proof, ) .map_err(|e| Kind::Query.context(e).into()) diff --git a/relayer-cli/src/commands/query/client.rs b/relayer-cli/src/commands/query/client.rs index 6a885692ea..fa604f80e7 100644 --- a/relayer-cli/src/commands/query/client.rs +++ b/relayer-cli/src/commands/query/client.rs @@ -14,6 +14,8 @@ use relayer::chain::CosmosSDKChain; use tendermint::chain::Id as ChainId; use tendermint_proto::DomainType; +use std::convert::TryInto; + /// Query client state command #[derive(Clone, Command, Debug, Options)] pub struct QueryClientStateCmd { @@ -82,7 +84,11 @@ impl Runnable for QueryClientStateCmd { let chain = CosmosSDKChain::from_config(chain_config).unwrap(); let res: Result = chain - .query(ClientState(opts.client_id), opts.height, opts.proof) + .query( + ClientState(opts.client_id), + opts.height.try_into().unwrap(), + opts.proof, + ) .map_err(|e| Kind::Query.context(e).into()) .and_then(|v| { AnyClientState::decode_vec(&v).map_err(|e| Kind::Query.context(e).into()) @@ -103,6 +109,9 @@ pub struct QueryClientConsensusCmd { #[options(free, help = "identifier of the client to query")] client_id: Option, + #[options(free, help = "epoch of the client's consensus state to query")] + consensus_epoch: Option, + #[options(free, help = "height of the client's consensus state to query")] consensus_height: Option, @@ -116,6 +125,7 @@ pub struct QueryClientConsensusCmd { #[derive(Debug)] struct QueryClientConsensusOptions { client_id: ClientId, + consensus_epoch: u64, consensus_height: u64, height: u64, proof: bool, @@ -129,10 +139,11 @@ impl QueryClientConsensusCmd { let (chain_config, client_id) = validate_common_options(&self.chain_id, &self.client_id, config)?; - match self.consensus_height { - Some(consensus_height) => { + match (self.consensus_epoch, self.consensus_height) { + (Some(consensus_epoch), Some(consensus_height)) => { let opts = QueryClientConsensusOptions { client_id, + consensus_epoch, consensus_height, height: match self.height { Some(h) => h, @@ -145,7 +156,9 @@ impl QueryClientConsensusCmd { }; Ok((chain_config, opts)) } - None => Err("missing client consensus height".to_string()), + (Some(consensus_epoch), None) => Err("missing client consensus height".to_string()), + + (None, _) => Err("missing client consensus epoch".to_string()), } } } @@ -172,8 +185,12 @@ impl Runnable for QueryClientConsensusCmd { let chain = CosmosSDKChain::from_config(chain_config).unwrap(); let res: Result = chain .query( - ClientConsensusState(opts.client_id, opts.consensus_height), - opts.height, + ClientConsensusState { + client_id: opts.client_id, + epoch: opts.consensus_epoch, + height: opts.consensus_height, + }, + opts.height.try_into().unwrap(), opts.proof, ) .map_err(|e| Kind::Query.context(e).into()) @@ -193,7 +210,9 @@ fn validate_common_options( client_id: &Option, config: &Config, ) -> Result<(ChainConfig, ClientId), String> { - let chain_id = chain_id.ok_or_else(|| "missing chain parameter".to_string())?; + let chain_id = chain_id + .clone() + .ok_or_else(|| "missing chain parameter".to_string())?; let chain_config = config .chains .iter() @@ -239,6 +258,7 @@ impl QueryClientConnectionsCmd { ) -> Result<(ChainConfig, QueryClientConnectionsOptions), String> { let chain_id = self .chain_id + .clone() .ok_or_else(|| "missing chain identifier".to_string())?; let chain_config = config .chains @@ -286,7 +306,11 @@ impl Runnable for QueryClientConnectionsCmd { let chain = CosmosSDKChain::from_config(chain_config).unwrap(); let res: Result = chain - .query(ClientConnections(opts.client_id), opts.height, opts.proof) + .query( + ClientConnections(opts.client_id), + opts.height.try_into().unwrap(), + opts.proof, + ) .map_err(|e| Kind::Query.context(e).into()) .and_then(|v| ConnectionIDs::decode_vec(&v).map_err(|e| Kind::Query.context(e).into())); match res { @@ -343,7 +367,7 @@ mod tests { name: "No client id specified".to_string(), params: QueryClientStateCmd { client_id: None, - ..default_params + ..default_params.clone() }, want_pass: false, }, @@ -429,7 +453,7 @@ mod tests { name: "No client id specified".to_string(), params: QueryClientConnectionsCmd { client_id: None, - ..default_params + ..default_params.clone() }, want_pass: false, }, diff --git a/relayer-cli/src/commands/query/connection.rs b/relayer-cli/src/commands/query/connection.rs index e9bc7a14c8..b8c3a4632a 100644 --- a/relayer-cli/src/commands/query/connection.rs +++ b/relayer-cli/src/commands/query/connection.rs @@ -4,6 +4,7 @@ use abscissa_core::{Command, Options, Runnable}; use relayer::config::{ChainConfig, Config}; use crate::error::{Error, Kind}; +use ibc::ics03_connection::connection::ConnectionEnd; use ibc::ics24_host::error::ValidationError; use ibc::ics24_host::identifier::ConnectionId; use ibc::ics24_host::Path::Connections; @@ -11,7 +12,7 @@ use relayer::chain::{Chain, CosmosSDKChain}; use tendermint::chain::Id as ChainId; use tendermint_proto::DomainType; -use ibc::ics03_connection::connection::ConnectionEnd; +use std::convert::TryInto; #[derive(Clone, Command, Debug, Options)] pub struct QueryConnectionEndCmd { @@ -42,6 +43,7 @@ impl QueryConnectionEndCmd { ) -> Result<(ChainConfig, QueryConnectionOptions), String> { let chain_id = self .chain_id + .clone() .ok_or_else(|| "missing chain identifier".to_string())?; let chain_config = config .chains @@ -88,7 +90,11 @@ impl Runnable for QueryConnectionEndCmd { // run without proof: // cargo run --bin relayer -- -c relayer/tests/config/fixtures/simple_config.toml query connection end ibc-test connectionidone --height 3 -p false let res: Result = chain - .query(Connections(opts.connection_id), opts.height, opts.proof) + .query( + Connections(opts.connection_id), + opts.height.try_into().unwrap(), + opts.proof, + ) .map_err(|e| Kind::Query.context(e).into()) .and_then(|v| ConnectionEnd::decode_vec(&v).map_err(|e| Kind::Query.context(e).into())); @@ -145,7 +151,7 @@ mod tests { name: "No connection id specified".to_string(), params: QueryConnectionEndCmd { connection_id: None, - ..default_params + ..default_params.clone() }, want_pass: false, }, @@ -153,7 +159,7 @@ mod tests { name: "Bad connection, non-alpha".to_string(), params: QueryConnectionEndCmd { connection_id: Some("conn01".to_string()), - ..default_params + ..default_params.clone() }, want_pass: false, }, diff --git a/relayer-cli/src/commands/start.rs b/relayer-cli/src/commands/start.rs index 848920f359..fbae896300 100644 --- a/relayer-cli/src/commands/start.rs +++ b/relayer-cli/src/commands/start.rs @@ -135,7 +135,7 @@ async fn create_client_task( let supervisor = create_client(chain, trust_options, reset).await?; let handle = supervisor.handle(); - let task = client_task(*chain.id(), supervisor); + let task = client_task(chain.id().clone(), supervisor); let light_client = client::tendermint::LightClient::new(handle); chain.set_light_client(light_client); @@ -176,7 +176,7 @@ async fn create_client( reset: bool, ) -> Result { let chain_config = chain.config(); - let id = chain_config.id; + let id = chain_config.id.clone(); let db_path = format!("store_{}.db", chain.id()); let store = store::sled::SledStore::new(sled::open(db_path)?); diff --git a/relayer-cli/tests/integration.rs b/relayer-cli/tests/integration.rs index 9c1a8612c9..9a10c7d372 100644 --- a/relayer-cli/tests/integration.rs +++ b/relayer-cli/tests/integration.rs @@ -17,16 +17,17 @@ use ibc::ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId}; use ibc::ics24_host::Path::{ChannelEnds, ClientConnections}; use relayer::chain::{Chain, CosmosSDKChain}; use relayer::config::{ChainConfig, Config}; -use std::str::FromStr; -use tendermint::chain::Id; use tendermint::net::Address; use tendermint_proto::DomainType; +use std::convert::TryInto; +use std::str::FromStr; + /// Configuration that connects to the informaldev/simd DockerHub image running on localhost. fn simd_config() -> Config { let mut config = Config::default(); config.chains = vec![ChainConfig { - id: Id::from("ibc-test"), + id: "ibc-test".try_into().unwrap(), rpc_addr: Address::from_str("127.0.0.1:26657").unwrap(), account_prefix: "cosmos".to_string(), key_name: "testkey".to_string(), @@ -84,7 +85,7 @@ fn query_channel_id() { PortId::from_str("firstport").unwrap(), ChannelId::from_str("firstchannel").unwrap(), ), - 0, + 0_u64.try_into().unwrap(), false, ) .unwrap(), @@ -108,7 +109,7 @@ fn query_client_id() { &chain .query( ClientConnections(ClientId::from_str("clientidone").unwrap()), - 0, + 0_u64.try_into().unwrap(), false, ) .unwrap(), diff --git a/relayer/Cargo.toml b/relayer/Cargo.toml index 4683e123f8..0b0c6f5ab0 100644 --- a/relayer/Cargo.toml +++ b/relayer/Cargo.toml @@ -8,7 +8,6 @@ authors = [ [dependencies] ibc = { path = "../modules" } -ibc-proto = "0.2.2" tendermint-proto = "0.1.0" anomaly = "0.2.0" diff --git a/relayer/src/chain.rs b/relayer/src/chain.rs index 6ec4a59d31..96cbc593d4 100644 --- a/relayer/src/chain.rs +++ b/relayer/src/chain.rs @@ -42,7 +42,7 @@ pub trait Chain { type Error: Into>; /// Perform a generic `query`, and return the corresponding response data. - fn query(&self, data: Path, height: u64, prove: bool) -> Result, Self::Error>; + fn query(&self, data: Path, height: Height, prove: bool) -> Result, Self::Error>; /// send a transaction with `msgs` to chain. fn send(&self, _msgs: &[Any], memo: String, timeout_height: u64) -> Result<(), Self::Error>; diff --git a/relayer/src/chain/cosmos.rs b/relayer/src/chain/cosmos.rs index cec9d71ef1..66fb46eda1 100644 --- a/relayer/src/chain/cosmos.rs +++ b/relayer/src/chain/cosmos.rs @@ -54,13 +54,15 @@ impl Chain for CosmosSDKChain { type ClientState = ClientState; type Error = Error; - fn query(&self, data: Path, height: u64, prove: bool) -> Result, Self::Error> { + fn query(&self, data: Path, height: Height, prove: bool) -> Result, Self::Error> { let path = TendermintABCIPath::from_str(IBC_QUERY_PATH).unwrap(); + if !data.is_provable() & prove { return Err(Kind::Store .context("requested proof for a path in the privateStore") .into()); } + let response = block_on(abci_query(&self, path, data.to_string(), height, prove))?; // Verify response proof, if requested. @@ -164,21 +166,19 @@ async fn abci_query( chain: &CosmosSDKChain, path: TendermintABCIPath, data: String, - height: u64, + height: Height, prove: bool, ) -> Result, anomaly::Error> { + let height = if height.value() == 0 { + None + } else { + Some(height) + }; + // Use the Tendermint-rs RPC client to do the query. let response = chain .rpc_client() - .abci_query( - Some(path), - data.into_bytes(), - match height { - 0 => None, - _ => Some(Height::from(height)), - }, - prove, - ) + .abci_query(Some(path), data.into_bytes(), height, prove) .await .map_err(|e| Kind::Rpc.context(e))?; diff --git a/relayer/src/event_handler.rs b/relayer/src/event_handler.rs index 3ad17be6b6..19ec06b6e9 100644 --- a/relayer/src/event_handler.rs +++ b/relayer/src/event_handler.rs @@ -26,7 +26,7 @@ impl EventHandler { loop { if let Some(events) = self.channel_from_monitors.recv().await { for event in events.1 { - self.handle(events.0, event); + self.handle(events.0.clone(), event); } } } diff --git a/relayer/src/event_monitor.rs b/relayer/src/event_monitor.rs index e90302fb84..d03f2b1eea 100644 --- a/relayer/src/event_monitor.rs +++ b/relayer/src/event_monitor.rs @@ -1,12 +1,16 @@ use ibc::events::IBCEvent; use tendermint::{chain, net, Error as TMError}; -use tendermint_rpc::Subscription; -use tendermint_rpc::{SubscriptionClient, WebSocketClient}; +use tendermint_rpc::{ + query::EventType, query::Query, Subscription, SubscriptionClient, WebSocketClient, +}; use tokio::stream::StreamExt; use tokio::sync::mpsc::Sender; -use futures::stream::select_all; -use tracing::{debug, info}; +use futures::{stream::select_all, Stream}; +use tracing::{debug, error, info}; + +type SubscriptionResult = Result; +type SubscriptionStream = dyn Stream + Send + Sync + Unpin; /// Connect to a TM node, receive push events over a websocket and filter them for the /// event handler. @@ -19,9 +23,9 @@ pub struct EventMonitor { /// Node Address node_addr: net::Address, /// Queries - event_queries: Vec, - /// Subscriptions - subscriptions: Vec, + event_queries: Vec, + /// All subscriptions combined in a single stream + subscriptions: Box, } impl EventMonitor { @@ -34,35 +38,29 @@ impl EventMonitor { let websocket_client = WebSocketClient::new(rpc_addr.clone()).await?; // TODO: move them to config file(?) - let event_queries = vec![ - "tm.event='NewTx'".to_string(), - "tm.event='NewBlock'".to_string(), - ]; + let event_queries = vec![Query::from(EventType::Tx), Query::from(EventType::NewBlock)]; Ok(EventMonitor { chain_id, websocket_client, channel_to_handler, node_addr: rpc_addr.clone(), - subscriptions: Vec::with_capacity(event_queries.len()), event_queries, + subscriptions: Box::new(futures::stream::empty()), }) } - /// Terminate and clear the current subscriptions, and subscribe again to all queries. + /// Clear the current subscriptions, and subscribe again to all queries. pub async fn subscribe(&mut self) -> Result<(), Box> { - let count = self.subscriptions.len(); - let subscriptions = std::mem::replace(&mut self.subscriptions, Vec::with_capacity(count)); - - for subscription in subscriptions { - subscription.terminate().await?; - } + let mut subscriptions = vec![]; for query in &self.event_queries { let subscription = self.websocket_client.subscribe(query.clone()).await?; - self.subscriptions.push(subscription); + subscriptions.push(subscription); } + self.subscriptions = Box::new(select_all(subscriptions)); + Ok(()) } @@ -75,20 +73,30 @@ impl EventMonitor { Ok(..) => continue, Err(err) => { debug!("Web socket error: {}", err); + // Try to reconnect - let websocket_client = WebSocketClient::new(self.node_addr.clone()) + let mut websocket_client = WebSocketClient::new(self.node_addr.clone()) .await .unwrap_or_else(|e| { - debug!("Error on reconnection {}", e); - panic!("Abort on failed reconnection") + debug!("Error on reconnection: {}", e); + panic!("Abort on failed reconnection"); }); + // Swap the new client with the previous one which failed, + // so that we can shut the latter down gracefully. + std::mem::swap(&mut self.websocket_client, &mut websocket_client); + debug!("Reconnected"); - self.websocket_client = websocket_client; + + // Shut down previous client + debug!("Gracefully shutting down previous client"); + websocket_client.close().await.unwrap_or_else(|e| { + error!("Failed to close previous WebSocket client: {}", e); + }); // Try to resubscribe if let Err(err) = self.subscribe().await { - debug!("Error on recreating subscriptions {}", err); + debug!("Error on recreating subscriptions: {}", err); panic!("Abort during reconnection"); }; } @@ -98,18 +106,22 @@ impl EventMonitor { /// Collect the IBC events from the subscriptions pub async fn collect_events(&mut self) -> Result<(), TMError> { - if let Some(event) = select_all(&mut self.subscriptions).next().await { - match event { - Ok(event) => { - if let Ok(ibc_events) = ibc::events::get_all_events(event) { - // TODO - send_timeout()? - self.channel_to_handler - .send((self.chain_id, ibc_events)) - .await?; + tokio::select! { + Some(event) = self.subscriptions.next() => { + match event { + Ok(event) => { + if let Ok(ibc_events) = ibc::events::get_all_events(event) { + // TODO - send_timeout()? + self.channel_to_handler + .send((self.chain_id.clone(), ibc_events)) + .await?; + } + } + Err(err) => { + error!("Error on collecting events from subscriptions: {}", err); } } - Err(_e) => (), // TODO, - } + }, } Ok(()) diff --git a/relayer/src/tx/client.rs b/relayer/src/tx/client.rs index 07221fbb3c..136f960de2 100644 --- a/relayer/src/tx/client.rs +++ b/relayer/src/tx/client.rs @@ -1,4 +1,5 @@ use prost_types::Any; +use std::convert::TryInto; use std::time::Duration; use ibc::ics02_client::client_def::{AnyClientState, AnyConsensusState}; @@ -27,10 +28,13 @@ pub fn create_client(opts: CreateClientOptions) -> Result<(), Error> { let dest_chain = CosmosSDKChain::from_config(opts.clone().dest_chain_config)?; // Query the client state on destination chain. - if dest_chain - .query(ClientStatePath(opts.clone().dest_client_id), 0, false) - .is_ok() - { + let response = dest_chain.query( + ClientStatePath(opts.clone().dest_client_id), + 0_u64.try_into().unwrap(), + false, + ); + + if response.is_ok() { return Err(Into::::into(Kind::CreateClient( opts.dest_client_id, "client already exists".into(), @@ -39,19 +43,22 @@ pub fn create_client(opts: CreateClientOptions) -> Result<(), Error> { // Get the latest header from the source chain and build the consensus state. let src_chain = CosmosSDKChain::from_config(opts.clone().src_chain_config)?; - let tm_consensus_state = block_on(query_latest_header::(&src_chain)) - .map_err(|e| { + let tm_latest_header = + block_on(query_latest_header::(&src_chain)).map_err(|e| { Kind::CreateClient( opts.dest_client_id.clone(), "failed to get the latest header".into(), ) .context(e) - }) - .map(|light_block| { - ibc::ics07_tendermint::consensus_state::ConsensusState::from(light_block.signed_header) })?; - let any_consensus_state = AnyConsensusState::Tendermint(tm_consensus_state.clone()); + let height = tm_latest_header.signed_header.header.height; + + let tm_consensus_state = ibc::ics07_tendermint::consensus_state::ConsensusState::from( + tm_latest_header.signed_header, + ); + + let any_consensus_state = AnyConsensusState::Tendermint(tm_consensus_state); // Build the client state. let any_client_state = ibc::ics07_tendermint::client_state::ClientState::new( @@ -59,8 +66,10 @@ pub fn create_client(opts: CreateClientOptions) -> Result<(), Error> { src_chain.trusting_period(), src_chain.unbonding_period(), Duration::from_millis(3000), - tm_consensus_state.height, - Height(0), + height, + 0_u64.try_into().unwrap(), + false, + false, ) .map_err(|e| { Kind::CreateClient(