Skip to content

Commit bce09ca

Browse files
Farhad-Shabaniriversyangrnbguy
authored
fix(ibc-client-tendermint-types): drop frozen height check in TryFrom of TmClientState (#1062)
* Fix issues related to frozen height of tendermint client. * fix: ease frozen height check within TryFrom for TmClientState * nit: set correct vallue for the frozen height in test * nit * use rstest cases * add check for is_frozen --------- Co-authored-by: Rivers Yang <[email protected]> Co-authored-by: Ranadeep Biswas <[email protected]>
1 parent 5e1a67d commit bce09ca

File tree

4 files changed

+43
-33
lines changed

4 files changed

+43
-33
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- [ibc-client-tendermint-types] Ease frozen Height check in the tendermint
2+
`ClientState` protobuf deserialization
3+
([\#1061](https://github.com/cosmos/ibc-rs/issues/1061))

ibc-clients/ics07-tendermint/src/client_state.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,11 @@ where
401401
_client_message: Any,
402402
_update_kind: &UpdateKind,
403403
) -> Result<(), ClientError> {
404+
// NOTE: frozen height is set to `Height {revision_height: 0,
405+
// revision_number: 1}` and it is the same for all misbehaviour. This
406+
// aligns with the
407+
// [`ibc-go`](https://github.com/cosmos/ibc-go/blob/0e3f428e66d6fc0fc6b10d2f3c658aaa5000daf7/modules/light-clients/07-tendermint/misbehaviour.go#L18-L19)
408+
// implementation.
404409
let frozen_client_state = self.0.clone().with_frozen_height(Height::min(0));
405410

406411
let wrapped_frozen_client_state = ClientState::from(frozen_client_state);

ibc-clients/ics07-tendermint/types/src/client_state.rs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use ibc_core_host_types::identifiers::ChainId;
1212
use ibc_primitives::prelude::*;
1313
use ibc_primitives::ZERO_DURATION;
1414
use ibc_proto::google::protobuf::Any;
15-
use ibc_proto::ibc::core::client::v1::Height as RawHeight;
1615
use ibc_proto::ibc::lightclients::tendermint::v1::ClientState as RawTmClientState;
1716
use ibc_proto::Protobuf;
1817
use tendermint::chain::id::MAX_LENGTH as MaxChainIdLen;
@@ -62,6 +61,7 @@ impl ClientState {
6261
latest_height: Height,
6362
proof_specs: ProofSpecs,
6463
upgrade_path: Vec<String>,
64+
frozen_height: Option<Height>,
6565
allow_update: AllowUpdate,
6666
) -> Self {
6767
Self {
@@ -74,11 +74,13 @@ impl ClientState {
7474
proof_specs,
7575
upgrade_path,
7676
allow_update,
77-
frozen_height: None,
77+
frozen_height,
7878
verifier: ProdVerifier::default(),
7979
}
8080
}
8181

82+
/// Constructs a new Tendermint `ClientState` by given parameters and checks
83+
/// if the parameters are valid.
8284
#[allow(clippy::too_many_arguments)]
8385
pub fn new(
8486
chain_id: ChainId,
@@ -100,6 +102,7 @@ impl ClientState {
100102
latest_height,
101103
proof_specs,
102104
upgrade_path,
105+
None, // New valid client must not be frozen.
103106
allow_update,
104107
);
105108
client_state.validate()?;
@@ -283,13 +286,7 @@ impl TryFrom<RawTmClientState> for ClientState {
283286
// In `RawClientState`, a `frozen_height` of `0` means "not frozen".
284287
// See:
285288
// https://github.com/cosmos/ibc-go/blob/8422d0c4c35ef970539466c5bdec1cd27369bab3/modules/light-clients/07-tendermint/types/client_state.go#L74
286-
if raw
287-
.frozen_height
288-
.and_then(|h| Height::try_from(h).ok())
289-
.is_some()
290-
{
291-
return Err(Error::FrozenHeightNotAllowed);
292-
}
289+
let frozen_height = raw.frozen_height.and_then(|h| Height::try_from(h).ok());
293290

294291
// We use set this deprecated field just so that we can properly convert
295292
// it back in its raw form
@@ -308,6 +305,7 @@ impl TryFrom<RawTmClientState> for ClientState {
308305
latest_height,
309306
raw.proof_specs.into(),
310307
raw.upgrade_path,
308+
frozen_height,
311309
allow_update,
312310
);
313311

@@ -324,12 +322,7 @@ impl From<ClientState> for RawTmClientState {
324322
trusting_period: Some(value.trusting_period.into()),
325323
unbonding_period: Some(value.unbonding_period.into()),
326324
max_clock_drift: Some(value.max_clock_drift.into()),
327-
frozen_height: Some(value.frozen_height.map(|height| height.into()).unwrap_or(
328-
RawHeight {
329-
revision_number: 0,
330-
revision_height: 0,
331-
},
332-
)),
325+
frozen_height: value.frozen_height.map(|height| height.into()),
333326
latest_height: Some(value.latest_height.into()),
334327
proof_specs: value.proof_specs.into(),
335328
upgrade_path: value.upgrade_path,

ibc-testkit/src/fixtures/clients/tendermint.rs

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -169,16 +169,27 @@ pub fn dummy_ics07_header() -> Header {
169169
mod tests {
170170

171171
use ibc::primitives::proto::Any;
172+
use rstest::rstest;
172173

173174
use super::*;
174175

175-
#[test]
176-
fn tm_client_state_conversions_healthy() {
176+
#[rstest]
177+
// try conversions for when the client is not frozen
178+
#[case::valid_client(0, 0, false)]
179+
// try conversions for when the client is frozen
180+
#[case::frozen_client(0, 1, true)]
181+
fn tm_client_state_conversions_healthy(
182+
#[case] revision_number: u64,
183+
#[case] revision_height: u64,
184+
#[case] is_frozen: bool,
185+
) {
186+
let frozen_height = RawHeight {
187+
revision_number,
188+
revision_height,
189+
};
190+
177191
// check client state creation path from a proto type
178-
let tm_client_state_from_raw = dummy_tm_client_state_from_raw(RawHeight {
179-
revision_number: 0,
180-
revision_height: 0,
181-
});
192+
let tm_client_state_from_raw = dummy_tm_client_state_from_raw(frozen_height);
182193
assert!(tm_client_state_from_raw.is_ok());
183194

184195
let any_from_tm_client_state = Any::from(
@@ -189,11 +200,21 @@ mod tests {
189200
);
190201
let tm_client_state_from_any = ClientStateType::try_from(any_from_tm_client_state);
191202
assert!(tm_client_state_from_any.is_ok());
203+
assert_eq!(
204+
Some(is_frozen),
205+
tm_client_state_from_any
206+
.as_ref()
207+
.map(|x| x.is_frozen())
208+
.ok()
209+
);
192210
assert_eq!(
193211
tm_client_state_from_raw.expect("Never fails"),
194212
tm_client_state_from_any.expect("Never fails").into()
195213
);
214+
}
196215

216+
#[test]
217+
fn tm_client_state_from_header_healthy() {
197218
// check client state creation path from a tendermint header
198219
let tm_header = dummy_tendermint_header();
199220
let tm_client_state_from_header = dummy_tm_client_state_from_header(tm_header);
@@ -205,16 +226,4 @@ mod tests {
205226
tm_client_state_from_any.expect("Never fails").into()
206227
);
207228
}
208-
209-
#[test]
210-
fn tm_client_state_malformed_with_frozen_height() {
211-
let tm_client_state_from_raw = dummy_tm_client_state_from_raw(RawHeight {
212-
revision_number: 0,
213-
revision_height: 10,
214-
});
215-
match tm_client_state_from_raw {
216-
Err(Error::FrozenHeightNotAllowed) => {}
217-
_ => panic!("Expected to fail with FrozenHeightNotAllowed error"),
218-
}
219-
}
220229
}

0 commit comments

Comments
 (0)