Skip to content

Commit

Permalink
ICS07: Add verification method for client update handler (#1321)
Browse files Browse the repository at this point in the history
* bla

* on going

* ongoing

* on going

* on going

* timestamp default changed from none to now

* failed ping pong - signs

* Update context.rs

* bla

* blabla

* fixed test client_update_ping_pong

* fmt + clippy

* Update context.rs

* Update context.rs

* remove comments

* Update host.rs

* Update to tendermint-rs v0.20.0

* Update changelog

* Fix tendermint-rs version in changelog

* Update predicates.rs

* Update context.rs

* tests

* tendermint stuff in

* Update Cargo.toml

* clippy + fmt

* moved predicates into ics07 header.rs

* Adapted to latest TM changes

* Fixed MockHeader test

* Fmt & clippy

* Removed irrelevant file

* Bit more cleanup

* fixed tests

* upgraded to new error  model

* fmt

* errors and timestamp changes

* Fix error notation and formatting

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Upgrade to tendermint-rs master

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Use tendermint-rs from branch thane/ibc-1252

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Refactor ICS07 update handler to reuse light client verifier

This commit makes use of the latest code from
informalsystems/tendermint-rs#960 in order to
reuse the light client's verification predicates instead of
reimplementing them in the `ibc` crate.

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Update Cargo.lock to address zeroize issue

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Bump tendermint-light-client dep to v0.22.0 for ibc module

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Refactor to accommodate new context API

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Fix missing import

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Fix imports

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Fix error check in test

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Output debug version of error

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Remove test as per #1321 (comment)

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Address comments from Adi

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Cosmetic tweaks

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Add revision number check

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Fix broken test

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Check incoming header height against chain ID version from client state

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Add revision_number consistency check when deserializing header

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Clarify MismatchedRevisions error message

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Add changelog entries

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Commented import no longer necessary

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Add in-the-middle monotonicity checks

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Fix broken dep tree relating to Prometheus

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Move next/prev consensus state search functionality to ClientReader trait

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Move impl of prev/next to the specific implementation and simplify signatures

* Disable `tendermint-light-client` default features, ie. RPC client, std and color-eyre

* Apply suggestions from code review

* Fix compilation

* Cleanup BTreeMap import

* Always show underlying reason in ics07_tendermint errors

* Update modules/src/ics02_client/handler/update_client.rs

* Fix compilation

Co-authored-by: cezarad <cezara@informal.systems>
Co-authored-by: Romain Ruetschi <romain@informal.systems>
Co-authored-by: cezarad <9439384+cezarad@users.noreply.github.com>
Co-authored-by: Adi Seredinschi <adi@informal.systems>
Co-authored-by: Anca Zamfir <zamfiranca@gmail.com>
  • Loading branch information
6 people authored Oct 19, 2021
1 parent 14aeb87 commit fde0a96
Show file tree
Hide file tree
Showing 24 changed files with 1,029 additions and 89 deletions.
3 changes: 3 additions & 0 deletions .changelog/unreleased/breaking-changes/ibc/1214-ics07.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- The `check_header_and_update_state` method of the `ClientDef`
trait (ICS02) has been expanded to facilitate ICS07
([#1214](https://github.com/informalsystems/ibc-rs/issues/1214))
2 changes: 2 additions & 0 deletions .changelog/unreleased/features/ibc/1214-ics07.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Add ICS07 verification functionality by using `tendermint-light-client`
([#1214](https://github.com/informalsystems/ibc-rs/issues/1214))
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion modules/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ description = """
default = ["std", "eyre_tracer"]
std = ["flex-error/std"]
eyre_tracer = ["flex-error/eyre_tracer"]

# This feature grants access to development-time mocking libraries, such as `MockContext` or `MockHeader`.
# Depends on the `testgen` suite for generating Tendermint light blocks.
mocks = [ "tendermint-testgen", "sha2" ]
mocks = ["tendermint-testgen", "sha2"]

[dependencies]
# Proto definitions for all IBC-related interfaces, e.g., connections or channels.
Expand All @@ -45,6 +46,10 @@ version = "=0.22.0"
[dependencies.tendermint-proto]
version = "=0.22.0"

[dependencies.tendermint-light-client]
version = "=0.22.0"
default-features = false

[dependencies.tendermint-testgen]
version = "=0.22.0"
optional = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,17 @@ impl From<MsgTransfer> for RawMsgTransfer {

#[cfg(test)]
pub mod test_util {
use std::ops::Add;
use std::time::Duration;

use crate::{
ics24_host::identifier::{ChannelId, PortId},
test_utils::get_dummy_account_id,
timestamp::Timestamp,
Height,
};

use super::MsgTransfer;
use crate::timestamp::Timestamp;

// Returns a dummy `RawMsgTransfer`, for testing only!
pub fn get_dummy_msg_transfer(height: u64) -> MsgTransfer {
Expand All @@ -120,7 +123,7 @@ pub mod test_util {
token: None,
sender: id.clone(),
receiver: id,
timeout_timestamp: Timestamp::from_nanoseconds(1).unwrap(),
timeout_timestamp: Timestamp::now().add(Duration::from_secs(10)).unwrap(),
timeout_height: Height {
revision_number: 0,
revision_height: height,
Expand Down
13 changes: 9 additions & 4 deletions modules/src/ics02_client/client_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::downcast;
use crate::ics02_client::client_consensus::{AnyConsensusState, ConsensusState};
use crate::ics02_client::client_state::{AnyClientState, ClientState};
use crate::ics02_client::client_type::ClientType;
use crate::ics02_client::context::ClientReader;
use crate::ics02_client::error::Error;
use crate::ics02_client::header::{AnyHeader, Header};
use crate::ics03_connection::connection::ConnectionEnd;
Expand All @@ -23,13 +24,15 @@ pub trait ClientDef: Clone {
type ClientState: ClientState;
type ConsensusState: ConsensusState;

/// TODO
fn check_header_and_update_state(
&self,
ctx: &dyn ClientReader,
client_id: ClientId,
client_state: Self::ClientState,
header: Self::Header,
) -> Result<(Self::ClientState, Self::ConsensusState), Error>;

/// TODO
fn verify_upgrade_and_update_state(
&self,
client_state: &Self::ClientState,
Expand Down Expand Up @@ -156,7 +159,7 @@ pub enum AnyClient {
impl AnyClient {
pub fn from_client_type(client_type: ClientType) -> AnyClient {
match client_type {
ClientType::Tendermint => Self::Tendermint(TendermintClient),
ClientType::Tendermint => Self::Tendermint(TendermintClient::default()),

#[cfg(any(test, feature = "mocks"))]
ClientType::Mock => Self::Mock(MockClient),
Expand All @@ -173,6 +176,8 @@ impl ClientDef for AnyClient {
/// Validates an incoming `header` against the latest consensus state of this client.
fn check_header_and_update_state(
&self,
ctx: &dyn ClientReader,
client_id: ClientId,
client_state: AnyClientState,
header: AnyHeader,
) -> Result<(AnyClientState, AnyConsensusState), Error> {
Expand All @@ -185,7 +190,7 @@ impl ClientDef for AnyClient {
.ok_or_else(|| Error::client_args_type_mismatch(ClientType::Tendermint))?;

let (new_state, new_consensus) =
client.check_header_and_update_state(client_state, header)?;
client.check_header_and_update_state(ctx, client_id, client_state, header)?;

Ok((
AnyClientState::Tendermint(new_state),
Expand All @@ -202,7 +207,7 @@ impl ClientDef for AnyClient {
.ok_or_else(|| Error::client_args_type_mismatch(ClientType::Mock))?;

let (new_state, new_consensus) =
client.check_header_and_update_state(client_state, header)?;
client.check_header_and_update_state(ctx, client_id, client_state, header)?;

Ok((
AnyClientState::Mock(new_state),
Expand Down
37 changes: 36 additions & 1 deletion modules/src/ics02_client/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use crate::ics02_client::client_consensus::AnyConsensusState;
use crate::ics02_client::client_state::AnyClientState;
use crate::ics02_client::client_type::ClientType;
use crate::ics02_client::error::Error;
use crate::ics02_client::error::{Error, ErrorDetail};
use crate::ics02_client::handler::ClientResult::{self, Create, Update, Upgrade};
use crate::ics24_host::identifier::ClientId;
use crate::Height;
Expand All @@ -14,12 +14,47 @@ use crate::Height;
pub trait ClientReader {
fn client_type(&self, client_id: &ClientId) -> Result<ClientType, Error>;
fn client_state(&self, client_id: &ClientId) -> Result<AnyClientState, Error>;

/// Retrieve the consensus state for the given client ID at the specified
/// height.
///
/// Returns an error if no such state exists.
fn consensus_state(
&self,
client_id: &ClientId,
height: Height,
) -> Result<AnyConsensusState, Error>;

/// Similar to `consensus_state`, attempt to retrieve the consensus state,
/// but return `None` if no state exists at the given height.
fn maybe_consensus_state(
&self,
client_id: &ClientId,
height: Height,
) -> Result<Option<AnyConsensusState>, Error> {
match self.consensus_state(client_id, height) {
Ok(cs) => Ok(Some(cs)),
Err(e) => match e.detail() {
ErrorDetail::ConsensusStateNotFound(_) => Ok(None),
_ => Err(e),
},
}
}

/// Search for the lowest consensus state higher than `height`.
fn next_consensus_state(
&self,
client_id: &ClientId,
height: Height,
) -> Result<Option<AnyConsensusState>, Error>;

/// Search for the highest consensus state lower than `height`.
fn prev_consensus_state(
&self,
client_id: &ClientId,
height: Height,
) -> Result<Option<AnyConsensusState>, Error>;

/// Returns a natural number, counting how many clients have been created thus far.
/// The value of this counter should increase only via method `ClientKeeper::increase_client_counter`.
fn client_counter(&self) -> Result<u64, Error>;
Expand Down
51 changes: 45 additions & 6 deletions modules/src/ics02_client/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ use crate::ics07_tendermint::error::Error as Ics07Error;
use crate::ics23_commitment::error::Error as Ics23Error;
use crate::ics24_host::error::ValidationError;
use crate::ics24_host::identifier::ClientId;
use crate::timestamp::Timestamp;
use crate::Height;

use tendermint::Error as TendermintError;
use tendermint_proto::Error as TendermintProtoError;

define_error! {
#[derive(Debug, PartialEq, Eq)]
Error {
Expand Down Expand Up @@ -58,7 +62,7 @@ define_error! {

FailedTrustThresholdConversion
{ numerator: u64, denominator: u64 }
[ tendermint::Error ]
[ TendermintError ]
| e | { format_args!("failed to build Tendermint domain type trust threshold from fraction: {}/{}", e.numerator, e.denominator) },

UnknownClientStateType
Expand Down Expand Up @@ -105,14 +109,14 @@ define_error! {
},

DecodeRawClientState
[ TraceError<tendermint_proto::Error> ]
[ TraceError<TendermintProtoError> ]
| _ | { "error decoding raw client state" },

MissingRawClientState
| _ | { "missing raw client state" },

InvalidRawConsensusState
[ TraceError<tendermint_proto::Error> ]
[ TraceError<TendermintProtoError> ]
| _ | { "invalid raw client consensus state" },

MissingRawConsensusState
Expand All @@ -134,14 +138,14 @@ define_error! {
| _ | { "invalid client identifier" },

InvalidRawHeader
[ TraceError<tendermint_proto::Error> ]
[ TraceError<TendermintProtoError> ]
| _ | { "invalid raw header" },

MissingRawHeader
| _ | { "missing raw header" },

DecodeRawMisbehaviour
[ TraceError<tendermint_proto::Error> ]
[ TraceError<TendermintProtoError> ]
| _ | { "invalid raw misbehaviour" },

InvalidRawMisbehaviour
Expand Down Expand Up @@ -180,6 +184,12 @@ define_error! {
e.client_type)
},

InsufficientVotingPower
{ reason: String }
| e | {
format_args!("Insufficient overlap {}", e.reason)
},

RawClientAndConsensusStateTypesMismatch
{
state_type: ClientType,
Expand All @@ -206,8 +216,37 @@ define_error! {
client_height: Height,
}
| e | {
format_args!("upgraded client height {0} must be at greater than current client height {1}",
format_args!("upgraded client height {} must be at greater than current client height {}",
e.upgraded_height, e.client_height)
},

InvalidConsensusStateTimestamp
{
time1: Timestamp,
time2: Timestamp,
}
| e | {
format_args!("timestamp is invalid or missing, timestamp={0}, now={1}", e.time1, e.time2)
},

HeaderNotWithinTrustPeriod
{
latest_time:Timestamp,
update_time: Timestamp,
}
| e | {
format_args!("header not withing trusting period: expires_at={0} now={1}", e.latest_time, e.update_time)
},

TendermintHandlerError
[ Ics07Error ]
| _ | { format_args!("Tendermint-specific handler error") },

}
}

impl From<Ics07Error> for Error {
fn from(e: Ics07Error) -> Error {
Error::tendermint_handler_error(e)
}
}
Loading

0 comments on commit fde0a96

Please sign in to comment.