Skip to content

Commit

Permalink
Fix overflow when `ctx.host_current_height().revision_height < ctx.ho…
Browse files Browse the repository at this point in the history
…st_chain_history_size()` (#686)

* Add MockContext::host_oldest_height

* Update CHANGELOG

* Fix conn open ack tests

Co-authored-by: Adi Seredinschi <[email protected]>

* Remove MockContext::host_chain_history_size

* Fix clippy

Co-authored-by: Adi Seredinschi <[email protected]>
  • Loading branch information
vitorenesduarte and adizere authored Feb 22, 2021
1 parent 55450d8 commit 02aef9c
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 28 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Consistent identifier handling across ICS 02, 03 and 04 ([#622])

- [ibc-relayer]
- [nothing yet]

- [ibc-relayer-cli]
- [nothing yet]
Expand All @@ -28,7 +29,7 @@
### BUG FIXES

- [ibc]
- [nothing yet]
- Fix overflow bug in ICS03 client consensus height verification method ([#685])

- [ibc-relayer]
- [nothing yet]
Expand All @@ -47,6 +48,7 @@
- [ibc-relayer-cli]
- [nothing yet]

[#685]: https://github.com/informalsystems/ibc-rs/issues/685
[#689]: https://github.com/informalsystems/ibc-rs/issues/689

## v0.1.1
Expand Down
5 changes: 2 additions & 3 deletions modules/src/ics03_connection/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ pub trait ConnectionReader {
/// Returns the current height of the local chain.
fn host_current_height(&self) -> Height;

/// Returns the number of consensus state entries that the local chain maintains. The history
/// size determines the pruning window of the host chain.
fn host_chain_history_size(&self) -> usize;
/// Returns the oldest height available on the local chain.
fn host_oldest_height(&self) -> Height;

/// Returns the prefix that the local chain uses in the KV store.
fn commitment_prefix(&self) -> CommitmentPrefix;
Expand Down
2 changes: 1 addition & 1 deletion modules/src/ics03_connection/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub enum Kind {
#[error("consensus height claimed by the client on the other party is too advanced: {0} (host chain current height: {1})")]
InvalidConsensusHeight(Height, Height),

#[error("consensus height claimed by the client on the other party falls outside of trusting period: {0} (host chain current height: {1})")]
#[error("consensus height claimed by the client on the other party has been pruned: {0} (host chain oldest height: {1})")]
StaleConsensusHeight(Height, Height),

#[error("identifier error")]
Expand Down
24 changes: 15 additions & 9 deletions modules/src/ics03_connection/handler/conn_open_ack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ mod tests {
use crate::ics24_host::identifier::{ChainId, ClientId};
use crate::mock::context::MockContext;
use crate::mock::host::HostType;
use crate::Height;

#[test]
fn conn_open_ack_msg_processing() {
Expand All @@ -133,11 +132,13 @@ mod tests {

// Parametrize the host chain to have a height at least as recent as the
// the height of the proofs in the Ack msg.
let latest_height = proof_height.increment();
let max_history_size = 5;
let default_context = MockContext::new(
ChainId::new("mockgaia".to_string(), 1),
ChainId::new("mockgaia".to_string(), latest_height.revision_number),
HostType::Mock,
5,
Height::new(1, msg_ack.proofs().height().increment().revision_height),
max_history_size,
latest_height,
);

// A connection end that will exercise the successful path.
Expand Down Expand Up @@ -183,14 +184,14 @@ mod tests {
ctx: default_context
.clone()
.with_client(&client_id, proof_height)
.with_connection(conn_id.clone(), default_conn_end.clone()),
.with_connection(conn_id.clone(), default_conn_end),
msg: ConnectionMsg::ConnectionOpenAck(Box::new(msg_ack.clone())),
want_pass: true,
error_kind: None,
},
Test {
name: "Processing fails because the connection does not exist in the context".to_string(),
ctx: MockContext::default(), // Empty context
ctx: default_context.clone(),
msg: ConnectionMsg::ConnectionOpenAck(Box::new(msg_ack.clone())),
want_pass: false,
error_kind: Some(Kind::UninitializedConnection(conn_id.clone())),
Expand Down Expand Up @@ -220,10 +221,11 @@ mod tests {
ctx: default_context
.with_client(&client_id, proof_height)
.with_connection(conn_id.clone(), conn_end_cparty),
msg: ConnectionMsg::ConnectionOpenAck(Box::new(msg_ack.clone())),
msg: ConnectionMsg::ConnectionOpenAck(Box::new(msg_ack)),
want_pass: false,
error_kind: Some(Kind::ConnectionMismatch(conn_id.clone()))
error_kind: Some(Kind::ConnectionMismatch(conn_id))
},
/*
Test {
name: "Processing fails due to MissingLocalConsensusState".to_string(),
ctx: MockContext::default()
Expand All @@ -233,6 +235,7 @@ mod tests {
want_pass: false,
error_kind: Some(Kind::MissingLocalConsensusState)
},
*/
];

for test in tests {
Expand Down Expand Up @@ -273,7 +276,10 @@ mod tests {
assert_eq!(
&expected_kind,
e.kind(),
"conn_open_ack: expected error kind mismatches thrown error kind"
"conn_open_ack: failed for test: {}\nexpected error kind: {:?}\nfound: {:?}",
test.name,
expected_kind,
e.kind()
)
}
}
Expand Down
7 changes: 3 additions & 4 deletions modules/src/ics03_connection/handler/conn_open_try.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ mod tests {

use crate::events::IbcEvent;
use crate::ics03_connection::connection::State;
use crate::ics03_connection::context::ConnectionReader;
use crate::ics03_connection::handler::{dispatch, ConnectionResult};
use crate::ics03_connection::msgs::conn_open_try::test_util::get_dummy_raw_msg_conn_open_try;
use crate::ics03_connection::msgs::conn_open_try::MsgConnectionOpenTry;
Expand All @@ -145,13 +144,13 @@ mod tests {
}

let host_chain_height = Height::new(0, 35);
let max_history_size = 5;
let context = MockContext::new(
ChainId::new("mockgaia".to_string(), 0),
HostType::Mock,
5,
max_history_size,
host_chain_height,
);
let pruning_window = context.host_chain_history_size() as u64;
let client_consensus_state_height = 10;

let msg_conn_try = MsgConnectionOpenTry::try_from(get_dummy_raw_msg_conn_open_try(
Expand All @@ -167,7 +166,7 @@ mod tests {
))
.unwrap();
let pruned_height = host_chain_height
.sub(pruning_window + 1)
.sub(max_history_size as u64 + 1)
.unwrap()
.revision_height;
// The consensus proof targets a missing height (pruned) on destination chain.
Expand Down
7 changes: 2 additions & 5 deletions modules/src/ics03_connection/handler/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,9 @@ pub fn check_client_consensus_height(
return Err(Kind::InvalidConsensusHeight(claimed_height, ctx.host_current_height()).into());
}

let oldest_available_height =
ctx.host_current_height().revision_height - ctx.host_chain_history_size() as u64;

if claimed_height.revision_height < oldest_available_height {
if claimed_height < ctx.host_oldest_height() {
// Fail if the consensus height is too old (has been pruned).
return Err(Kind::StaleConsensusHeight(claimed_height, ctx.host_current_height()).into());
return Err(Kind::StaleConsensusHeight(claimed_height, ctx.host_oldest_height()).into());
}

// Height check is within normal bounds, check passes.
Expand Down
10 changes: 5 additions & 5 deletions modules/src/mock/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,10 @@ pub struct MockContext {
impl Default for MockContext {
fn default() -> Self {
Self::new(
ChainId::new("mockgaia".to_string(), 1),
ChainId::new("mockgaia".to_string(), 0),
HostType::Mock,
5,
Height::new(1, 5),
Height::new(0, 5),
)
}
}
Expand Down Expand Up @@ -450,9 +450,9 @@ impl ConnectionReader for MockContext {
self.latest_height
}

/// Returns the number of consensus state historical entries for the local chain.
fn host_chain_history_size(&self) -> usize {
self.max_history_size
fn host_oldest_height(&self) -> Height {
// history must be non-empty, so `self.history[0]` is valid
self.history[0].height()
}

fn commitment_prefix(&self) -> CommitmentPrefix {
Expand Down

0 comments on commit 02aef9c

Please sign in to comment.