From d5be5af711fff7e7101ee5b11189ae57edfd85f7 Mon Sep 17 00:00:00 2001 From: DaviRain-Su Date: Tue, 10 Aug 2021 11:09:43 +0800 Subject: [PATCH] Enable Event create Grandpa client (#44) * Update client_state, consensus_state * Pub client_state new function * Update consensus_stae new function * Update grandpa client implement * Update struct * Update ics02_client/client_state * format code * Add latest height * Add Ics10 Header height * Add Ics10 client_state chain * Add Ics10 client state frozen_height * remove println for debug * public OpenInit inner type, and Add MsgConnectionOpenInit new function Co-authored-by: DaviRain-Su --- modules/src/ics02_client/client_consensus.rs | 15 +- modules/src/ics02_client/client_def.rs | 165 ++++++++++++++++-- modules/src/ics02_client/client_state.rs | 21 ++- modules/src/ics02_client/client_type.rs | 1 - modules/src/ics02_client/error.rs | 5 + modules/src/ics02_client/header.rs | 18 ++ modules/src/ics02_client/misbehaviour.rs | 15 +- modules/src/ics03_connection/events.rs | 2 +- .../ics03_connection/msgs/conn_open_init.rs | 10 ++ modules/src/ics10_grandpa/client_def.rs | 4 +- modules/src/ics10_grandpa/client_state.rs | 56 +++--- modules/src/ics10_grandpa/consensus_state.rs | 56 +++--- modules/src/ics10_grandpa/error.rs | 18 ++ modules/src/ics10_grandpa/header.rs | 64 ++++--- modules/src/ics10_grandpa/misbehaviour.rs | 45 +++-- modules/src/ics10_grandpa/mod.rs | 2 +- proto/src/lib.rs | 5 + .../src/prost/ibc.lightclients.grandpa.v1.rs | 45 +++++ 18 files changed, 424 insertions(+), 123 deletions(-) create mode 100644 proto/src/prost/ibc.lightclients.grandpa.v1.rs diff --git a/modules/src/ics02_client/client_consensus.rs b/modules/src/ics02_client/client_consensus.rs index a44b1ac6b..e3007ed2c 100644 --- a/modules/src/ics02_client/client_consensus.rs +++ b/modules/src/ics02_client/client_consensus.rs @@ -25,6 +25,8 @@ use crate::mock::client_state::MockConsensusState; pub const TENDERMINT_CONSENSUS_STATE_TYPE_URL: &str = "/ibc.lightclients.tendermint.v1.ConsensusState"; +pub const GRANDPA_CONSENSUS_STATE_TYPE_URL: &str = "/ibc.lightclients.grandpa.v1.ConsensusState"; + pub const MOCK_CONSENSUS_STATE_TYPE_URL: &str = "/ibc.mock.ConsensusState"; pub trait ConsensusState: Clone + std::fmt::Debug + Send + Sync { @@ -95,6 +97,11 @@ impl TryFrom for AnyConsensusState { .map_err(Error::decode_raw_client_state)?, )), + GRANDPA_CONSENSUS_STATE_TYPE_URL => Ok(AnyConsensusState::Grandpa( + crate::ics10_grandpa::consensus_state::ConsensusState::decode_vec(&value.value) + .map_err(Error::decode_raw_client_state)?, + )), + #[cfg(any(test, feature = "mocks"))] MOCK_CONSENSUS_STATE_TYPE_URL => Ok(AnyConsensusState::Mock( MockConsensusState::decode_vec(&value.value) @@ -115,9 +122,13 @@ impl From for Any { .encode_vec() .expect("encoding to `Any` from `AnyConsensusState::Tendermint`"), }, - AnyConsensusState::Grandpa(value) => { - unimplemented!() + AnyConsensusState::Grandpa(value) => Any { + type_url: GRANDPA_CONSENSUS_STATE_TYPE_URL.to_string(), + value: value + .encode_vec() + .expect("encoding to 'Any' from 'AnyConsensusState::Grandpa'"), }, + #[cfg(any(test, feature = "mocks"))] AnyConsensusState::Mock(value) => Any { type_url: MOCK_CONSENSUS_STATE_TYPE_URL.to_string(), diff --git a/modules/src/ics02_client/client_def.rs b/modules/src/ics02_client/client_def.rs index c65537e97..17927812d 100644 --- a/modules/src/ics02_client/client_def.rs +++ b/modules/src/ics02_client/client_def.rs @@ -194,7 +194,21 @@ impl ClientDef for AnyClient { AnyConsensusState::Tendermint(new_consensus), )) } - Self::Grandpa(client) => unimplemented!(), + Self::Grandpa(client) => { + let (client_state, header) = downcast!( + client_state => AnyClientState::Grandpa, + header => AnyHeader::Grandpa, + ) + .ok_or_else(|| Error::client_args_type_mismatch(ClientType::Grandpa))?; + + let (new_state, new_consensus) = + client.check_header_and_update_state(client_state, header)?; + + Ok(( + AnyClientState::Grandpa(new_state), + AnyConsensusState::Grandpa(new_consensus), + )) + } #[cfg(any(test, feature = "mocks"))] Self::Mock(client) => { @@ -243,7 +257,22 @@ impl ClientDef for AnyClient { ) } - Self::Grandpa(client) => unimplemented!(), + Self::Grandpa(client) => { + let client_state = downcast!( + client_state => AnyClientState::Grandpa + ) + .ok_or_else(|| Error::client_args_type_mismatch(ClientType::Grandpa))?; + + client.verify_client_consensus_state( + client_state, + height, + prefix, + proof, + client_id, + consensus_height, + expected_consensus_state, + ) + } #[cfg(any(test, feature = "mocks"))] Self::Mock(client) => { @@ -288,7 +317,19 @@ impl ClientDef for AnyClient { expected_connection_end, ) } - Self::Grandpa(client) => unimplemented!(), + Self::Grandpa(client) => { + let client_state = downcast!(client_state => AnyClientState::Grandpa) + .ok_or_else(|| Error::client_args_type_mismatch(ClientType::Grandpa))?; + + client.verify_connection_state( + client_state, + height, + prefix, + proof, + connection_id, + expected_connection_end, + ) + } #[cfg(any(test, feature = "mocks"))] Self::Mock(client) => { @@ -332,7 +373,20 @@ impl ClientDef for AnyClient { expected_channel_end, ) } - Self::Grandpa(client) => unimplemented!(), + Self::Grandpa(client) => { + let client_state = downcast!(client_state => AnyClientState::Grandpa) + .ok_or_else(|| Error::client_args_type_mismatch(ClientType::Grandpa))?; + + client.verify_channel_state( + client_state, + height, + prefix, + proof, + port_id, + channel_id, + expected_channel_end, + ) + } #[cfg(any(test, feature = "mocks"))] Self::Mock(client) => { @@ -379,7 +433,22 @@ impl ClientDef for AnyClient { client_state_on_counterparty, ) } - Self::Grandpa(client) => unimplemented!(), + Self::Grandpa(client) => { + let client_state = downcast!( + client_state => AnyClientState::Grandpa + ) + .ok_or_else(|| Error::client_args_type_mismatch(ClientType::Grandpa))?; + + client.verify_client_full_state( + client_state, + height, + root, + prefix, + client_id, + proof, + client_state_on_counterparty, + ) + } #[cfg(any(test, feature = "mocks"))] Self::Mock(client) => { @@ -427,7 +496,22 @@ impl ClientDef for AnyClient { commitment, ) } - Self::Grandpa(client) => unimplemented!(), + Self::Grandpa(client) => { + let client_state = downcast!( + client_state => AnyClientState::Grandpa + ) + .ok_or_else(|| Error::client_args_type_mismatch(ClientType::Grandpa))?; + + client.verify_packet_data( + client_state, + height, + proof, + port_id, + channel_id, + seq, + commitment, + ) + } #[cfg(any(test, feature = "mocks"))] Self::Mock(client) => { @@ -476,7 +560,22 @@ impl ClientDef for AnyClient { ack, ) } - Self::Grandpa(client) => unimplemented!(), + Self::Grandpa(client) => { + let client_state = downcast!( + client_state => AnyClientState::Grandpa + ) + .ok_or_else(|| Error::client_args_type_mismatch(ClientType::Grandpa))?; + + client.verify_packet_acknowledgement( + client_state, + height, + proof, + port_id, + channel_id, + seq, + ack, + ) + } #[cfg(any(test, feature = "mocks"))] Self::Mock(client) => { @@ -524,7 +623,21 @@ impl ClientDef for AnyClient { ) } - Self::Grandpa(client) => unimplemented!(), + Self::Grandpa(client) => { + let client_state = downcast!( + client_state => AnyClientState::Grandpa + ) + .ok_or_else(|| Error::client_args_type_mismatch(ClientType::Grandpa))?; + + client.verify_next_sequence_recv( + client_state, + height, + proof, + port_id, + channel_id, + seq, + ) + } #[cfg(any(test, feature = "mocks"))] Self::Mock(client) => { @@ -569,7 +682,21 @@ impl ClientDef for AnyClient { seq, ) } - Self::Grandpa(client) => unimplemented!(), + Self::Grandpa(client) => { + let client_state = downcast!( + client_state => AnyClientState::Grandpa + ) + .ok_or_else(|| Error::client_args_type_mismatch(ClientType::Grandpa))?; + + client.verify_packet_receipt_absence( + client_state, + height, + proof, + port_id, + channel_id, + seq, + ) + } #[cfg(any(test, feature = "mocks"))] Self::Mock(client) => { @@ -617,7 +744,25 @@ impl ClientDef for AnyClient { AnyConsensusState::Tendermint(new_consensus), )) } - Self::Grandpa(client) => unimplemented!(), + Self::Grandpa(client) => { + let (client_state, consensus_state) = downcast!( + client_state => AnyClientState::Grandpa, + consensus_state => AnyConsensusState::Grandpa, + ) + .ok_or_else(|| Error::client_args_type_mismatch(ClientType::Grandpa))?; + + let (new_state, new_consensus) = client.verify_upgrade_and_update_state( + client_state, + consensus_state, + proof_upgrade_client, + proof_upgrade_consensus_state, + )?; + + Ok(( + AnyClientState::Grandpa(new_state), + AnyConsensusState::Grandpa(new_consensus), + )) + } #[cfg(any(test, feature = "mocks"))] Self::Mock(client) => { diff --git a/modules/src/ics02_client/client_state.rs b/modules/src/ics02_client/client_state.rs index 8bc60005c..56d629fd4 100644 --- a/modules/src/ics02_client/client_state.rs +++ b/modules/src/ics02_client/client_state.rs @@ -20,6 +20,8 @@ use crate::mock::client_state::MockClientState; use crate::Height; pub const TENDERMINT_CLIENT_STATE_TYPE_URL: &str = "/ibc.lightclients.tendermint.v1.ClientState"; +pub const GRANDPA_CLIENT_STATE_TYPE_URL: &str = "/ibc.ligheclients.grandpa.v1.ClientState"; + pub const MOCK_CLIENT_STATE_TYPE_URL: &str = "/ibc.mock.ClientState"; #[dyn_clonable::clonable] @@ -45,7 +47,6 @@ pub trait ClientState: Clone + std::fmt::Debug + Send + Sync { #[serde(tag = "type")] pub enum AnyClientState { Tendermint(client_state::ClientState), - Grandpa(ics10_grandpa::client_state::ClientState), #[cfg(any(test, feature = "mocks"))] @@ -56,7 +57,6 @@ impl AnyClientState { pub fn latest_height(&self) -> Height { match self { Self::Tendermint(tm_state) => tm_state.latest_height(), - Self::Grandpa(tm_state) => tm_state.latest_height(), #[cfg(any(test, feature = "mocks"))] @@ -77,7 +77,6 @@ impl AnyClientState { pub fn client_type(&self) -> ClientType { match self { Self::Tendermint(state) => state.client_type(), - Self::Grandpa(state) => state.client_type(), #[cfg(any(test, feature = "mocks"))] @@ -120,6 +119,11 @@ impl TryFrom for AnyClientState { .map_err(Error::decode_raw_client_state)?, )), + GRANDPA_CLIENT_STATE_TYPE_URL => Ok(AnyClientState::Grandpa( + crate::ics10_grandpa::client_state::ClientState::decode_vec(&raw.value) + .map_err(Error::decode_raw_client_state)?, + )), + #[cfg(any(test, feature = "mocks"))] MOCK_CLIENT_STATE_TYPE_URL => Ok(AnyClientState::Mock( MockClientState::decode_vec(&raw.value).map_err(Error::decode_raw_client_state)?, @@ -140,7 +144,12 @@ impl From for Any { .expect("encoding to `Any` from `AnyClientState::Tendermint`"), }, - AnyClientState::Grandpa(value) => unimplemented!(), + AnyClientState::Grandpa(value) => Any { + type_url: GRANDPA_CLIENT_STATE_TYPE_URL.to_string(), + value: value + .encode_vec() + .expect("encoding to `Any` from `AnyClientState::Grandpa`"), + }, #[cfg(any(test, feature = "mocks"))] AnyClientState::Mock(value) => Any { @@ -157,7 +166,7 @@ impl ClientState for AnyClientState { fn chain_id(&self) -> ChainId { match self { AnyClientState::Tendermint(tm_state) => tm_state.chain_id(), - AnyClientState::Grandpa(_tm_state) => unimplemented!(), + AnyClientState::Grandpa( tm_state) => tm_state.chain_id(), #[cfg(any(test, feature = "mocks"))] AnyClientState::Mock(mock_state) => mock_state.chain_id(), @@ -175,7 +184,7 @@ impl ClientState for AnyClientState { fn is_frozen(&self) -> bool { match self { AnyClientState::Tendermint(tm_state) => tm_state.is_frozen(), - AnyClientState::Grandpa(_tm_state) => unimplemented!(), + AnyClientState::Grandpa( tm_state) => tm_state.is_frozen(), #[cfg(any(test, feature = "mocks"))] AnyClientState::Mock(mock_state) => mock_state.is_frozen(), diff --git a/modules/src/ics02_client/client_type.rs b/modules/src/ics02_client/client_type.rs index 85bc626e7..75570e1e6 100644 --- a/modules/src/ics02_client/client_type.rs +++ b/modules/src/ics02_client/client_type.rs @@ -24,7 +24,6 @@ impl ClientType { /// Yields the identifier of this client type as a string pub fn as_str(&self) -> &'static str { match self { - Self::Tendermint => Self::TENDERMINT_STR, Self::Grandpa => Self::GRANDPA_STR, diff --git a/modules/src/ics02_client/error.rs b/modules/src/ics02_client/error.rs index 3e1144804..6060ed199 100644 --- a/modules/src/ics02_client/error.rs +++ b/modules/src/ics02_client/error.rs @@ -1,5 +1,6 @@ use crate::ics02_client::client_type::ClientType; use crate::ics07_tendermint::error::Error as Ics07Error; +use crate::ics10_grandpa::error::Error as Ics10Error; use crate::ics23_commitment::error::Error as Ics23Error; use crate::ics24_host::error::ValidationError; use crate::ics24_host::identifier::ClientId; @@ -157,6 +158,10 @@ define_error! { [ Ics07Error ] | _ | { "tendermint error" }, + Grandpa + [ Ics10Error ] + | _ | { "grandpa error" }, + InvalidPacketTimestamp [ TraceError ] | _ | { "invalid packet timeout timestamp value" }, diff --git a/modules/src/ics02_client/header.rs b/modules/src/ics02_client/header.rs index 16d962893..b93c41ff8 100644 --- a/modules/src/ics02_client/header.rs +++ b/modules/src/ics02_client/header.rs @@ -4,6 +4,7 @@ use std::ops::Deref; use crate::ics02_client::client_type::ClientType; use crate::ics02_client::error::Error; use crate::ics07_tendermint::header::{decode_header, Header as TendermintHeader}; +use crate::ics10_grandpa::header::Header as GrandpaHeader; #[cfg(any(test, feature = "mocks"))] use crate::mock::header::MockHeader; use crate::Height; @@ -12,6 +13,7 @@ use serde_derive::{Deserialize, Serialize}; use tendermint_proto::Protobuf; pub const TENDERMINT_HEADER_TYPE_URL: &str = "/ibc.lightclients.tendermint.v1.Header"; +pub const GRANDPA_HEADER_TYPE_URL: &str = "/ibc.lightclients.grandpa.v1.Header"; pub const MOCK_HEADER_TYPE_URL: &str = "/ibc.mock.Header"; /// Abstract of consensus state update information @@ -31,6 +33,7 @@ pub trait Header: Clone + std::fmt::Debug + Send + Sync { #[allow(clippy::large_enum_variant)] pub enum AnyHeader { Tendermint(TendermintHeader), + Grandpa(GrandpaHeader), #[cfg(any(test, feature = "mocks"))] Mock(MockHeader), @@ -40,6 +43,7 @@ impl Header for AnyHeader { fn client_type(&self) -> ClientType { match self { Self::Tendermint(header) => header.client_type(), + Self::Grandpa(header) => header.client_type(), #[cfg(any(test, feature = "mocks"))] Self::Mock(header) => header.client_type(), @@ -49,6 +53,7 @@ impl Header for AnyHeader { fn height(&self) -> Height { match self { Self::Tendermint(header) => header.height(), + Self::Grandpa(header) => header.height(), #[cfg(any(test, feature = "mocks"))] Self::Mock(header) => header.height(), @@ -72,6 +77,12 @@ impl TryFrom for AnyHeader { Ok(AnyHeader::Tendermint(val)) } + GRANDPA_HEADER_TYPE_URL => { + let val = crate::ics10_grandpa::header::decode_header(raw.value.deref()) + .map_err(Error::grandpa)?; + + Ok(AnyHeader::Grandpa(val)) + } #[cfg(any(test, feature = "mocks"))] MOCK_HEADER_TYPE_URL => Ok(AnyHeader::Mock( @@ -92,6 +103,13 @@ impl From for Any { .encode_vec() .expect("encoding to `Any` from `AnyHeader::Tendermint`"), }, + AnyHeader::Grandpa(header) => Any { + type_url: GRANDPA_HEADER_TYPE_URL.to_string(), + value: header + .encode_vec() + .expect("encoding to 'Any' from 'AnyHeader::Grandpa'"), + }, + #[cfg(any(test, feature = "mocks"))] AnyHeader::Mock(header) => Any { type_url: MOCK_HEADER_TYPE_URL.to_string(), diff --git a/modules/src/ics02_client/misbehaviour.rs b/modules/src/ics02_client/misbehaviour.rs index c9f49c01b..aa19e5cfc 100644 --- a/modules/src/ics02_client/misbehaviour.rs +++ b/modules/src/ics02_client/misbehaviour.rs @@ -5,7 +5,7 @@ use tendermint_proto::Protobuf; use crate::ics02_client::error::Error; use crate::ics07_tendermint::misbehaviour::Misbehaviour as TmMisbehaviour; -use crate::ics10_grandpa::misbehaviour::Misbehaviour as GpMisbehaviour; +use crate::ics10_grandpa::misbehaviour::Misbehaviour as GpMisbehaviour; #[cfg(any(test, feature = "mocks"))] use crate::mock::misbehaviour::Misbehaviour as MockMisbehaviour; @@ -16,6 +16,7 @@ use crate::Height; use super::header::AnyHeader; pub const TENDERMINT_MISBEHAVIOR_TYPE_URL: &str = "/ibc.lightclients.tendermint.v1.Misbehaviour"; +pub const GRANDPA_MISBEHAVIOR_TYPE_URL: &str = "/ibc.lightclients.grandpa.v1.Misbehaviour"; #[cfg(any(test, feature = "mocks"))] pub const MOCK_MISBEHAVIOUR_TYPE_URL: &str = "/ibc.mock.Misbehavior"; @@ -55,7 +56,7 @@ impl Misbehaviour for AnyMisbehaviour { fn height(&self) -> Height { match self { Self::Tendermint(misbehaviour) => misbehaviour.height(), - Self::Grandpa(misbehaviour ) => misbehaviour.height(), + Self::Grandpa(misbehaviour) => misbehaviour.height(), #[cfg(any(test, feature = "mocks"))] Self::Mock(misbehaviour) => misbehaviour.height(), @@ -77,6 +78,9 @@ impl TryFrom for AnyMisbehaviour { TENDERMINT_MISBEHAVIOR_TYPE_URL => Ok(AnyMisbehaviour::Tendermint( TmMisbehaviour::decode_vec(&raw.value).map_err(Error::decode_raw_misbehaviour)?, )), + GRANDPA_MISBEHAVIOR_TYPE_URL => Ok(AnyMisbehaviour::Grandpa( + GpMisbehaviour::decode_vec(&raw.value).map_err(Error::decode_raw_misbehaviour)?, + )), #[cfg(any(test, feature = "mocks"))] MOCK_MISBEHAVIOUR_TYPE_URL => Ok(AnyMisbehaviour::Mock( @@ -96,7 +100,12 @@ impl From for Any { .encode_vec() .expect("encoding to `Any` from `AnyMisbehavior::Tendermint`"), }, - AnyMisbehaviour::Grandpa(misbehaviour) => unimplemented!(), + AnyMisbehaviour::Grandpa(misbehaviour) => Any { + type_url: GRANDPA_MISBEHAVIOR_TYPE_URL.to_string(), + value: misbehaviour + .encode_vec() + .expect("encoding to 'Any' from 'AnyMisbehavior::Grandpa'"), + }, #[cfg(any(test, feature = "mocks"))] AnyMisbehaviour::Mock(misbehaviour) => Any { diff --git a/modules/src/ics03_connection/events.rs b/modules/src/ics03_connection/events.rs index fd5b1900d..87b9f123d 100644 --- a/modules/src/ics03_connection/events.rs +++ b/modules/src/ics03_connection/events.rs @@ -106,7 +106,7 @@ impl Default for Attributes { } #[derive(Debug, Deserialize, Serialize, Clone)] -pub struct OpenInit(Attributes); +pub struct OpenInit(pub Attributes); impl OpenInit { pub fn attributes(&self) -> &Attributes { diff --git a/modules/src/ics03_connection/msgs/conn_open_init.rs b/modules/src/ics03_connection/msgs/conn_open_init.rs index 06a93e2c8..5262b4bb8 100644 --- a/modules/src/ics03_connection/msgs/conn_open_init.rs +++ b/modules/src/ics03_connection/msgs/conn_open_init.rs @@ -26,6 +26,16 @@ pub struct MsgConnectionOpenInit { } impl MsgConnectionOpenInit { + pub fn new(client_id: ClientId, counterparty: Counterparty, version: Version, delay_period: Duration, signer: Signer) -> Self { + Self { + client_id, + counterparty, + version, + delay_period, + signer + } + } + /// Getter: borrow the `client_id` from this message. pub fn client_id(&self) -> &ClientId { &self.client_id diff --git a/modules/src/ics10_grandpa/client_def.rs b/modules/src/ics10_grandpa/client_def.rs index 780723bd3..34e565666 100644 --- a/modules/src/ics10_grandpa/client_def.rs +++ b/modules/src/ics10_grandpa/client_def.rs @@ -2,8 +2,8 @@ use ibc_proto::ibc::core::commitment::v1::MerkleProof; use crate::ics02_client::client_consensus::AnyConsensusState; use crate::ics02_client::client_def::ClientDef; -use crate::ics02_client::error::Error; use crate::ics02_client::client_state::AnyClientState; +use crate::ics02_client::error::Error; use crate::ics03_connection::connection::ConnectionEnd; use crate::ics04_channel::channel::ChannelEnd; use crate::ics04_channel::packet::Sequence; @@ -53,7 +53,7 @@ impl ClientDef for GrandpaClient { _connection_id: Option<&ConnectionId>, _expected_connection_end: &ConnectionEnd, ) -> Result<(), Error> { - todo!() + todo!() } fn verify_channel_state( diff --git a/modules/src/ics10_grandpa/client_state.rs b/modules/src/ics10_grandpa/client_state.rs index bb09d3eb9..a7bc62877 100644 --- a/modules/src/ics10_grandpa/client_state.rs +++ b/modules/src/ics10_grandpa/client_state.rs @@ -1,25 +1,27 @@ use std::convert::{TryFrom, TryInto}; +use std::str::FromStr; // mock grandpa as tendermint -// use ibc_proto::ibc::lightclients::tendermint::v1::ClientState as RawClientState; +use ibc_proto::ibc::lightclients::grandpa::v1::ClientState as RawClientState; -use serde::{Deserialize, Serialize}; -use crate::ics10_grandpa::error::Error; use crate::ics02_client::client_state::AnyClientState; use crate::ics02_client::client_type::ClientType; +use crate::ics10_grandpa::error::Error; use crate::ics24_host::identifier::ChainId; use crate::Height; +use serde::{Deserialize, Serialize}; +use tendermint_proto::Protobuf; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct ClientState{ +pub struct ClientState { pub chain_id: ChainId, pub latest_height: Height, pub frozen_height: Height, } impl ClientState { - fn new(chain_id: ChainId, latest_height: Height, frozen_height: Height) -> Result { - Ok(Self{ + pub fn new(chain_id: ChainId, latest_height: Height, frozen_height: Height) -> Result { + Ok(ClientState { chain_id, latest_height, frozen_height, @@ -31,7 +33,7 @@ impl ClientState { } } -// impl Protobuf for ClientState {} +impl Protobuf for ClientState {} impl crate::ics02_client::client_state::ClientState for ClientState { fn chain_id(&self) -> ChainId { @@ -56,16 +58,30 @@ impl crate::ics02_client::client_state::ClientState for ClientState { } } -// impl TryFrom for ClientState { -// type Error = Error; -// -// fn try_from(raw: RawClientState) -> Result { -// unimplemented!() -// } -// } -// -// impl From for RawClientState { -// fn from(value: ClientState) -> Self { -// unimplemented!() -// } -// } \ No newline at end of file +impl TryFrom for ClientState { + type Error = Error; + + fn try_from(raw: RawClientState) -> Result { + Ok(ClientState { + chain_id: ChainId::from_str(raw.chain_id.as_str()) + .map_err(Error::invalid_chain_identifier)?, + latest_height: raw.latest_height + .ok_or_else(Error::missing_latest_height)? + .into(), + frozen_height: raw + .frozen_height + .ok_or_else(Error::missing_frozen_height)? + .into(), + }) + } +} + +impl From for RawClientState { + fn from(value: ClientState) -> Self { + Self { + chain_id: value.chain_id.to_string(), + latest_height: Some(value.latest_height.into()), + frozen_height: Some(value.frozen_height.into()), + } + } +} diff --git a/modules/src/ics10_grandpa/consensus_state.rs b/modules/src/ics10_grandpa/consensus_state.rs index 9ec26b9d0..2c4ea139e 100644 --- a/modules/src/ics10_grandpa/consensus_state.rs +++ b/modules/src/ics10_grandpa/consensus_state.rs @@ -1,33 +1,28 @@ -use std::convert::{TryFrom, TryInto}; use std::convert::Infallible; +use std::convert::{TryFrom, TryInto}; use serde::Serialize; // use tendermint mock as grandpa -// use ibc_proto::ibc::lightclients::tendermint::v1::ConsensusState as RawConsensusState; +use ibc_proto::ibc::lightclients::grandpa::v1::ConsensusState as RawConsensusState; use crate::ics02_client::client_consensus::AnyConsensusState; use crate::ics02_client::client_type::ClientType; use crate::ics10_grandpa::error::Error; -use crate::ics23_commitment::commitment::CommitmentRoot; - use crate::ics10_grandpa::header::Header; +use crate::ics23_commitment::commitment::CommitmentRoot; +use tendermint_proto::Protobuf; #[derive(Clone, Debug, PartialEq, Eq, Serialize)] -pub struct ConsensusState{ - pub root: CommitmentRoot, -} - +pub struct ConsensusState {} impl ConsensusState { - pub fn new(root: CommitmentRoot) -> Self { - Self{ - root - } + pub fn new() -> Self { + Self {} } } -// impl Protobuf for ConsensusState {} +impl Protobuf for ConsensusState {} impl crate::ics02_client::client_consensus::ConsensusState for ConsensusState { type Error = Infallible; @@ -37,7 +32,7 @@ impl crate::ics02_client::client_consensus::ConsensusState for ConsensusState { } fn root(&self) -> &CommitmentRoot { - &self.root + unimplemented!() } fn validate_basic(&self) -> Result<(), Self::Error> { @@ -49,20 +44,19 @@ impl crate::ics02_client::client_consensus::ConsensusState for ConsensusState { } } -// -// impl TryFrom for ConsensusState { -// type Error = Error; -// -// fn try_from(raw: RawConsensusState) -> Result { -// unimplemented!() -// } -// } -// -// impl From for RawConsensusState { -// fn from(value: ConsensusState) -> Self { -// unimplemented!() -// } -// } +impl TryFrom for ConsensusState { + type Error = Error; + + fn try_from(_raw: RawConsensusState) -> Result { + Ok(ConsensusState {}) + } +} + +impl From for RawConsensusState { + fn from(_value: ConsensusState) -> Self { + Self {} + } +} // impl From for ConsensusState { // fn from(header: grandpa::block::Header) -> Self { @@ -71,7 +65,7 @@ impl crate::ics02_client::client_consensus::ConsensusState for ConsensusState { // } impl From
for ConsensusState { - fn from(header: Header) -> Self { - unimplemented!() + fn from(_header: Header) -> Self { + Self {} } -} \ No newline at end of file +} diff --git a/modules/src/ics10_grandpa/error.rs b/modules/src/ics10_grandpa/error.rs index b9b778fdb..954337958 100644 --- a/modules/src/ics10_grandpa/error.rs +++ b/modules/src/ics10_grandpa/error.rs @@ -1,8 +1,26 @@ use flex_error::{define_error, DisplayOnly, TraceError}; +use crate::ics24_host::error::ValidationError; define_error! { Error{ Dummy |_| { format_args!("dummy error") }, + + Decode + [ TraceError ] + | _ | { "decode error" }, + + MissingLatestHeight + | _ | { "missing latest height" }, + + MissingHeight + | _ | { "missing height" }, + + InvalidChainIdentifier + [ ValidationError ] + | _ | { "Invalid chain identifier" }, + + MissingFrozenHeight + | _ | { "missing frozen height" }, } } diff --git a/modules/src/ics10_grandpa/header.rs b/modules/src/ics10_grandpa/header.rs index 1eeda5ac3..b1e175a19 100644 --- a/modules/src/ics10_grandpa/header.rs +++ b/modules/src/ics10_grandpa/header.rs @@ -1,16 +1,21 @@ -use std::convert::{TryInto, TryFrom}; +use std::convert::{TryFrom, TryInto}; -// use ibc_proto::ibc::lightclients::tendermint::v1::Header as RawHeader; +use ibc_proto::ibc::lightclients::grandpa::v1::Header as RawHeader; -use serde::{Serialize, Deserialize}; use crate::ics02_client::client_type::ClientType; use crate::ics02_client::header::AnyHeader; use crate::ics10_grandpa::error::Error; use crate::ics24_host::identifier::ChainId; use crate::Height; +use bytes::Buf; +use prost::Message; +use serde::{Deserialize, Serialize}; +use tendermint_proto::Protobuf; #[derive(Clone, PartialEq, Deserialize, Serialize)] -pub struct Header; +pub struct Header { + pub height: u64, +} impl std::fmt::Debug for Header { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { @@ -18,9 +23,15 @@ impl std::fmt::Debug for Header { } } +impl Header { + pub fn height(&self) -> Height { + Height::new(0, self.height) + } +} + impl crate::ics02_client::header::Header for Header { fn client_type(&self) -> ClientType { - ClientType::Tendermint + ClientType::Grandpa } fn height(&self) -> Height { @@ -28,22 +39,33 @@ impl crate::ics02_client::header::Header for Header { } fn wrap_any(self) -> AnyHeader { - unimplemented!() + AnyHeader::Grandpa(self) } } -// impl Protobuf for Header {} - -// impl TryFrom for Header { -// type Error = Error; -// -// fn try_from(raw: RawHeader) -> Result { -// unimplemented!() -// } -// } -// -// impl From
for RawHeader { -// fn from(value: Header) -> Self { -// unimplemented!() -// } -// } +impl Protobuf for Header {} + +impl TryFrom for Header { + type Error = Error; + + fn try_from(raw: RawHeader) -> Result { + Ok(Header { + height: raw + .height + .ok_or_else(Error::missing_height)? + .revision_height, + }) + } +} + +pub fn decode_header(buf: B) -> Result { + RawHeader::decode(buf).map_err(Error::decode)?.try_into() +} + +impl From
for RawHeader { + fn from(value: Header) -> Self { + Self { + height: Some(Height::new(0, value.height).into()), + } + } +} diff --git a/modules/src/ics10_grandpa/misbehaviour.rs b/modules/src/ics10_grandpa/misbehaviour.rs index ddac36b3a..efd18e9ce 100644 --- a/modules/src/ics10_grandpa/misbehaviour.rs +++ b/modules/src/ics10_grandpa/misbehaviour.rs @@ -1,25 +1,20 @@ use std::convert::{TryFrom, TryInto}; -use tendermint_proto::Protobuf; - -// use ibc_proto::ibc::lightclients::tendermint::v1::Misbehaviour as RawMisbehaviour; +use ibc_proto::ibc::lightclients::grandpa::v1::Misbehaviour as RawMisbehaviour; use crate::ics02_client::misbehaviour::AnyMisbehaviour; use crate::ics10_grandpa::error::Error; use crate::ics10_grandpa::header::Header; use crate::ics24_host::identifier::ClientId; use crate::Height; +use tendermint_proto::Protobuf; #[derive(Clone, Debug, PartialEq)] -pub struct Misbehaviour { - pub client_id: ClientId, - pub header1: Header, - pub header2: Header, -} +pub struct Misbehaviour {} impl crate::ics02_client::misbehaviour::Misbehaviour for Misbehaviour { fn client_id(&self) -> &ClientId { - &self.client_id + unimplemented!() } fn height(&self) -> Height { @@ -31,24 +26,24 @@ impl crate::ics02_client::misbehaviour::Misbehaviour for Misbehaviour { } } -// impl Protobuf for Misbehaviour {} - -// impl TryFrom for Misbehaviour { -// type Error = Error; -// -// fn try_from(raw: RawMisbehaviour) -> Result { -// unimplemented!() -// } -// } -// -// impl From for RawMisbehaviour { -// fn from(value: Misbehaviour) -> Self { -// unimplemented!() -// } -// } +impl Protobuf for Misbehaviour {} + +impl TryFrom for Misbehaviour { + type Error = Error; + + fn try_from(raw: RawMisbehaviour) -> Result { + Ok(Misbehaviour {}) + } +} + +impl From for RawMisbehaviour { + fn from(value: Misbehaviour) -> Self { + Self {} + } +} impl std::fmt::Display for Misbehaviour { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - unimplemented!() + write!(f, "Misbehaviour") } } diff --git a/modules/src/ics10_grandpa/mod.rs b/modules/src/ics10_grandpa/mod.rs index f02f47c5d..2fc3c39ea 100644 --- a/modules/src/ics10_grandpa/mod.rs +++ b/modules/src/ics10_grandpa/mod.rs @@ -3,4 +3,4 @@ pub mod client_state; pub mod consensus_state; pub mod error; pub mod header; -pub mod misbehaviour; \ No newline at end of file +pub mod misbehaviour; diff --git a/proto/src/lib.rs b/proto/src/lib.rs index f7d49ff64..3d661b9b8 100644 --- a/proto/src/lib.rs +++ b/proto/src/lib.rs @@ -149,6 +149,11 @@ pub mod ibc { include!("prost/ibc.lightclients.tendermint.v1.rs"); } } + pub mod grandpa { + pub mod v1 { + include!("prost/ibc.lightclients.grandpa.v1.rs"); + } + } } pub mod mock { include!("prost/ibc.mock.rs"); diff --git a/proto/src/prost/ibc.lightclients.grandpa.v1.rs b/proto/src/prost/ibc.lightclients.grandpa.v1.rs new file mode 100644 index 000000000..8caf293d5 --- /dev/null +++ b/proto/src/prost/ibc.lightclients.grandpa.v1.rs @@ -0,0 +1,45 @@ +/// ClientState from Tendermint tracks the current validator set, latest height, +/// and a possible frozen height. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ClientState{ + #[prost(string, tag = "1")] + pub chain_id: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub latest_height: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub frozen_height: ::core::option::Option, +} + +/// ConsensusState defines the consensus state from Tendermint. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ConsensusState{ +} + +/// Misbehaviour is a wrapper over two conflicting Headers +/// that implements Misbehaviour interface expected by ICS-02 +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Misbehaviour{ +} + +/// Header defines the Tendermint client consensus Header. +/// It encapsulates all the information necessary to update from a trusted +/// Tendermint ConsensusState. The inclusion of TrustedHeight and +/// TrustedValidators allows this update to process correctly, so long as the +/// ConsensusState for the TrustedHeight exists, this removes race conditions +/// among relayers The SignedHeader and ValidatorSet are the new untrusted update +/// fields for the client. The TrustedHeight is the height of a stored +/// ConsensusState on the client that will be used to verify the new untrusted +/// header. The Trusted ConsensusState must be within the unbonding period of +/// current time in order to correctly verify, and the TrustedValidators must +/// hash to TrustedConsensusState.NextValidatorsHash since that is the last +/// trusted validator set at the TrustedHeight. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Header{ + #[prost(message, optional, tag="1")] + pub height: ::core::option::Option, +} + +/// Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Fraction{ +}