Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement upgrade client proposal handler #680

Merged
merged 13 commits into from
May 23, 2023
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Support for upgrade client proposal by featuring helper contexts and domain types
([#420](https://github.com/cosmos/ibc-rs/issues/420))
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Clarify usage of `upgrade_path` for handling upgrade proposals
([#141](https://github.com/cosmos/ibc-rs/issues/141))
5 changes: 2 additions & 3 deletions crates/ibc/src/applications/transfer/context.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
//! Defines the main context traits and IBC module callbacks

use crate::core::router::ModuleExtras;
use crate::core::ContextError;
use crate::prelude::*;

use sha2::{Digest, Sha256};
Expand All @@ -22,6 +19,8 @@ use crate::core::ics04_channel::context::{
use crate::core::ics04_channel::packet::{Acknowledgement, Packet};
use crate::core::ics04_channel::Version;
use crate::core::ics24_host::identifier::{ChannelId, ConnectionId, PortId};
use crate::core::router::ModuleExtras;
use crate::core::ContextError;
use crate::signer::Signer;

/// Methods required in token transfer validation, to be implemented by the host
Expand Down
8 changes: 4 additions & 4 deletions crates/ibc/src/clients/ics07_tendermint/client_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use crate::core::ics02_client::client_state::{
};
use crate::core::ics02_client::client_type::ClientType;
use crate::core::ics02_client::consensus_state::ConsensusState;
use crate::core::ics02_client::error::ClientError;
use crate::core::ics02_client::error::{ClientError, UpgradeClientError};
use crate::core::ics23_commitment::commitment::{
CommitmentPrefix, CommitmentProofBytes, CommitmentRoot,
};
Expand Down Expand Up @@ -251,7 +251,7 @@ impl ClientState {
}

// Resets custom fields to zero values (used in `update_client`)
fn zero_custom_fields(&mut self) {
pub fn zero_custom_fields(&mut self) {
self.trusting_period = ZERO_DURATION;
self.trust_level = TrustThreshold::ZERO;
self.allow_update.after_expiry = false;
Expand Down Expand Up @@ -436,10 +436,10 @@ impl Ics2ClientState for ClientState {
// the upgrade height This condition checks both the revision number and
// the height
if self.latest_height() >= upgraded_tm_client_state.latest_height() {
return Err(ClientError::LowUpgradeHeight {
return Err(UpgradeClientError::LowUpgradeHeight {
upgraded_height: self.latest_height(),
client_height: upgraded_tm_client_state.latest_height(),
});
})?;
}

// Check to see if the upgrade path is set
Expand Down
10 changes: 6 additions & 4 deletions crates/ibc/src/core/context.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::prelude::*;

use crate::signer::Signer;
use alloc::string::String;
use core::time::Duration;
use displaydoc::Display;
use ibc_proto::google::protobuf::Any;

use crate::prelude::*;
use crate::signer::Signer;

use crate::core::events::IbcEvent;
use crate::core::ics02_client::client_state::ClientState;
use crate::core::ics02_client::consensus_state::ConsensusState;
Expand All @@ -17,7 +18,8 @@ use crate::core::ics03_connection::version::{
use crate::core::ics04_channel::channel::ChannelEnd;
use crate::core::ics04_channel::commitment::{AcknowledgementCommitment, PacketCommitment};
use crate::core::ics04_channel::context::calculate_block_delay;
use crate::core::ics04_channel::error::{ChannelError, PacketError};
use crate::core::ics04_channel::error::ChannelError;
use crate::core::ics04_channel::error::PacketError;
use crate::core::ics04_channel::packet::{Receipt, Sequence};
use crate::core::ics23_commitment::commitment::CommitmentPrefix;
use crate::core::ics24_host::identifier::ClientId;
Expand Down
3 changes: 2 additions & 1 deletion crates/ibc/src/core/handler.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::context::RouterError;
use super::ics02_client::handler::{create_client, update_client, upgrade_client};
use super::ics02_client::msgs::{ClientMsg, MsgUpdateOrMisbehaviour};
use super::ics03_connection::handler::{
Expand Down Expand Up @@ -28,7 +29,7 @@ use super::ics04_channel::handler::timeout::{
};
use super::ics04_channel::msgs::{ChannelMsg, PacketMsg};
use super::ContextError;
use super::{msgs::MsgEnvelope, ExecutionContext, RouterError, ValidationContext};
use super::{msgs::MsgEnvelope, ExecutionContext, ValidationContext};

/// Entrypoint which performs both validation and message execution
pub fn dispatch(ctx: &mut impl ExecutionContext, msg: MsgEnvelope) -> Result<(), RouterError> {
Expand Down
52 changes: 40 additions & 12 deletions crates/ibc/src/core/ics02_client/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Defines the client error type

use crate::core::ContextError;
use crate::prelude::*;

use displaydoc::Display;
Expand All @@ -10,11 +9,14 @@ use crate::core::ics02_client::client_type::ClientType;
use crate::core::ics23_commitment::error::CommitmentError;
use crate::core::ics24_host::identifier::{ClientId, IdentifierError};
use crate::core::timestamp::Timestamp;
use crate::core::ContextError;
use crate::Height;

/// Encodes all the possible client errors
#[derive(Debug, Display)]
pub enum ClientError {
/// upgrade client error: `{0}`
Upgrade(UpgradeClientError),
/// Client identifier constructor failed for type `{client_type}` with counter `{counter}`, validation error: `{validation_error}`
ClientIdentifierConstructor {
client_type: ClientType,
Expand Down Expand Up @@ -76,10 +78,6 @@ pub enum ClientError {
latest_height: Height,
proof_height: Height,
},
/// invalid proof for the upgraded client state error: `{0}`
InvalidUpgradeClientProof(CommitmentError),
/// invalid proof for the upgraded consensus state error: `{0}`
InvalidUpgradeConsensusStateProof(CommitmentError),
/// invalid commitment proof bytes error: `{0}`
InvalidCommitmentProof(CommitmentError),
/// invalid packet timeout timestamp value error: `{0}`
Expand All @@ -91,11 +89,6 @@ pub enum ClientError {
header_height: Height,
latest_height: Height,
},
/// upgraded client height `{upgraded_height}` must be at greater than current client height `{client_height}`
LowUpgradeHeight {
upgraded_height: Height,
client_height: Height,
},
/// timestamp is invalid or missing, timestamp=`{time1}`, now=`{time2}`
InvalidConsensusStateTimestamp { time1: Timestamp, time2: Timestamp },
/// header not within trusting period: expires_at=`{latest_time}` now=`{update_time}`
Expand Down Expand Up @@ -140,12 +133,47 @@ impl std::error::Error for ClientError {
Self::InvalidClientIdentifier(e) => Some(e),
Self::InvalidRawHeader(e) => Some(e),
Self::InvalidRawMisbehaviour(e) => Some(e),
Self::InvalidUpgradeClientProof(e) => Some(e),
Self::InvalidUpgradeConsensusStateProof(e) => Some(e),
Self::InvalidCommitmentProof(e) => Some(e),
Self::InvalidPacketTimestamp(e) => Some(e),
Self::Ics23Verification(e) => Some(e),
_ => None,
}
}
}

/// Encodes all the possible upgrade client errors
#[derive(Debug, Display)]
pub enum UpgradeClientError {
/// invalid proof for the upgraded client state error: `{0}`
InvalidUpgradeClientProof(CommitmentError),
/// invalid proof for the upgraded consensus state error: `{0}`
InvalidUpgradeConsensusStateProof(CommitmentError),
/// upgraded client height `{upgraded_height}` must be at greater than current client height `{client_height}`
LowUpgradeHeight {
upgraded_height: Height,
client_height: Height,
},
/// invalid upgrade proposal: `{reason}`
InvalidUpgradeProposal { reason: String },
/// invalid upgrade plan: `{reason}`
InvalidUpgradePlan { reason: String },
/// other upgrade client error: `{reason}`
Other { reason: String },
}

impl From<UpgradeClientError> for ClientError {
fn from(e: UpgradeClientError) -> Self {
ClientError::Upgrade(e)
}
}

#[cfg(feature = "std")]
impl std::error::Error for UpgradeClientError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match &self {
Self::InvalidUpgradeClientProof(e) => Some(e),
Self::InvalidUpgradeConsensusStateProof(e) => Some(e),
_ => None,
}
}
}
11 changes: 7 additions & 4 deletions crates/ibc/src/core/ics02_client/handler/upgrade_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ mod tests {
use crate::clients::ics07_tendermint::client_type;
use crate::clients::ics07_tendermint::header::test_util::get_dummy_tendermint_header;

use crate::core::ics02_client::error::UpgradeClientError;
use crate::core::ics03_connection::handler::test_util::{Expect, Fixture};
use crate::core::ics24_host::identifier::ClientId;
use crate::downcast;
Expand Down Expand Up @@ -233,12 +234,14 @@ mod tests {

#[test]
fn upgrade_client_fail_low_upgrade_height() {
let fxt = msg_upgrade_client_fixture(Ctx::WithClient, Msg::LowUpgradeHeight);
let expected_err = ContextError::ClientError(ClientError::LowUpgradeHeight {
let fxt: Fixture<MsgUpgradeClient> =
msg_upgrade_client_fixture(Ctx::WithClient, Msg::LowUpgradeHeight);
let expected_err: ClientError = UpgradeClientError::LowUpgradeHeight {
upgraded_height: Height::new(0, 26).unwrap(),
client_height: fxt.ctx.latest_height(),
});
upgrade_client_validate(&fxt, Expect::Failure(Some(expected_err)));
}
.into();
upgrade_client_validate(&fxt, Expect::Failure(Some(expected_err.into())));
}

#[test]
Expand Down
12 changes: 7 additions & 5 deletions crates/ibc/src/core/ics02_client/msgs/upgrade_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use ibc_proto::ibc::core::client::v1::MsgUpgradeClient as RawMsgUpgradeClient;
use ibc_proto::ibc::core::commitment::v1::MerkleProof as RawMerkleProof;
use ibc_proto::protobuf::Protobuf;

use crate::core::ics02_client::error::ClientError;
use crate::core::ics02_client::error::{ClientError, UpgradeClientError};
use crate::core::ics23_commitment::commitment::CommitmentProofBytes;
use crate::core::ics23_commitment::error::CommitmentError;
use crate::core::ics24_host::identifier::ClientId;
Expand Down Expand Up @@ -78,11 +78,13 @@ impl TryFrom<RawMsgUpgradeClient> for MsgUpgradeClient {

let c_bytes =
CommitmentProofBytes::try_from(proto_msg.proof_upgrade_client).map_err(|_| {
ClientError::InvalidUpgradeClientProof(CommitmentError::EmptyMerkleProof)
UpgradeClientError::InvalidUpgradeClientProof(CommitmentError::EmptyMerkleProof)
})?;
let cs_bytes = CommitmentProofBytes::try_from(proto_msg.proof_upgrade_consensus_state)
.map_err(|_| {
ClientError::InvalidUpgradeConsensusStateProof(CommitmentError::EmptyMerkleProof)
UpgradeClientError::InvalidUpgradeConsensusStateProof(
CommitmentError::EmptyMerkleProof,
)
})?;

Ok(MsgUpgradeClient {
Expand All @@ -91,9 +93,9 @@ impl TryFrom<RawMsgUpgradeClient> for MsgUpgradeClient {
client_state: raw_client_state,
consensus_state: raw_consensus_state,
proof_upgrade_client: RawMerkleProof::try_from(c_bytes)
.map_err(ClientError::InvalidUpgradeClientProof)?,
.map_err(UpgradeClientError::InvalidUpgradeClientProof)?,
proof_upgrade_consensus_state: RawMerkleProof::try_from(cs_bytes)
.map_err(ClientError::InvalidUpgradeConsensusStateProof)?,
.map_err(UpgradeClientError::InvalidUpgradeConsensusStateProof)?,
signer: proto_msg.signer.into(),
})
}
Expand Down
3 changes: 2 additions & 1 deletion crates/ibc/src/core/ics04_channel/handler/acknowledgement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use crate::core::ics24_host::path::Path;
use crate::core::ics24_host::path::{
AckPath, ChannelEndPath, ClientConsensusStatePath, CommitmentPath, SeqAckPath,
};
use crate::core::{events::IbcEvent, ics04_channel::events::AcknowledgePacket, router::ModuleId};
use crate::core::router::ModuleId;
use crate::core::{events::IbcEvent, ics04_channel::events::AcknowledgePacket};
use crate::core::{ContextError, ExecutionContext, ValidationContext};

pub(crate) fn acknowledgement_packet_validate<ValCtx>(
Expand Down
8 changes: 3 additions & 5 deletions crates/ibc/src/core/ics04_channel/handler/timeout.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::prelude::*;
use prost::Message;

use crate::core::events::IbcEvent;
use crate::core::events::MessageEvent;
use crate::core::ics03_connection::delay::verify_conn_delay_passed;
use crate::core::ics04_channel::channel::State;
Expand All @@ -11,15 +12,12 @@ use crate::core::ics04_channel::error::PacketError;
use crate::core::ics04_channel::events::ChannelClosed;
use crate::core::ics04_channel::msgs::timeout::MsgTimeout;
use crate::core::ics04_channel::msgs::timeout_on_close::MsgTimeoutOnClose;
use crate::core::ics04_channel::{events::TimeoutPacket, handler::timeout_on_close};
use crate::core::ics24_host::path::Path;
use crate::core::ics24_host::path::{
ChannelEndPath, ClientConsensusStatePath, CommitmentPath, ReceiptPath, SeqRecvPath,
};
use crate::core::{
events::IbcEvent,
ics04_channel::{events::TimeoutPacket, handler::timeout_on_close},
router::ModuleId,
};
use crate::core::router::ModuleId;
use crate::core::{ContextError, ExecutionContext, ValidationContext};

pub(crate) enum TimeoutMsgType {
Expand Down
2 changes: 1 addition & 1 deletion crates/ibc/src/core/msgs.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::core::RouterError;
use crate::prelude::*;

use ibc_proto::google::protobuf::Any;

use crate::core::context::RouterError;
use crate::core::ics02_client::msgs::{
create_client, misbehaviour, update_client, upgrade_client, ClientMsg,
};
Expand Down
13 changes: 7 additions & 6 deletions crates/ibc/src/core/router.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
//! Defines the `Router`, which binds modules to ports

use crate::{core::events::ModuleEvent, prelude::*};

use crate::prelude::*;
use alloc::borrow::Borrow;
use core::fmt::{Debug, Display, Error as FmtError, Formatter};

use crate::core::events::ModuleEvent;
use crate::core::ics04_channel::channel::{Counterparty, Order};
use crate::core::ics04_channel::error::{ChannelError, PacketError, PortError::UnknownPort};
use crate::core::ics04_channel::error::PortError::UnknownPort;
use crate::core::ics04_channel::error::{ChannelError, PacketError};
use crate::core::ics04_channel::msgs::ChannelMsg;
use crate::core::ics04_channel::msgs::PacketMsg;
use crate::core::ics04_channel::packet::{Acknowledgement, Packet};
use crate::core::ics04_channel::Version;
use crate::core::ics24_host::identifier::{ChannelId, ConnectionId, PortId};
use crate::core::ics24_host::identifier::PortId;
use crate::core::ics24_host::identifier::{ChannelId, ConnectionId};
use crate::signer::Signer;

use super::ics04_channel::msgs::PacketMsg;

/// Router as defined in ICS-26, which binds modules to ports.
pub trait Router {
/// Returns a reference to a `Module` registered against the specified `ModuleId`
Expand Down
1 change: 0 additions & 1 deletion crates/ibc/src/hosts/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
//! Provides convenience implementations for various hosts

pub mod tendermint;
12 changes: 12 additions & 0 deletions crates/ibc/src/hosts/tendermint/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! Provides convenience implementations for Tendermint-based hosts

pub mod upgrade_proposal;

mod validate_self_client;
pub use validate_self_client::ValidateSelfClientContext;

/// ABCI store/query path for the IBC sub-store
pub const IBC_QUERY_PATH: &str = "store/ibc/key";

/// ABCI store/query path for the upgrade sub-store
pub const SDK_UPGRADE_QUERY_PATH: &str = "store/upgrade/key";
Loading