diff --git a/relayer/crates/starknet-chain-components/src/impls/events/send_packet.rs b/relayer/crates/starknet-chain-components/src/impls/events/send_packet.rs index 0108275f..e4965851 100644 --- a/relayer/crates/starknet-chain-components/src/impls/events/send_packet.rs +++ b/relayer/crates/starknet-chain-components/src/impls/events/send_packet.rs @@ -20,7 +20,6 @@ use ibc::core::channel::types::packet::Packet; use ibc::core::channel::types::timeout::{TimeoutHeight, TimeoutTimestamp}; use ibc::core::client::types::Height; use ibc::core::host::types::error::{DecodingError, IdentifierError}; -use ibc::primitives::Timestamp; use starknet::core::types::Felt; use crate::impls::events::UseStarknetEvents; @@ -57,13 +56,11 @@ where .map(TimeoutHeight::At) .unwrap_or_else(|_| TimeoutHeight::Never); - let timeout_timestamp_on_b = (event.timeout_timestamp_on_b.timestamp > 0) - .then(|| { - TimeoutTimestamp::At(Timestamp::from_nanoseconds( - event.timeout_timestamp_on_b.timestamp * 1_000_000_000, - )) - }) - .unwrap_or(TimeoutTimestamp::Never); + let timeout_timestamp_on_b = if event.timeout_timestamp_on_b.nanoseconds() > 0 { + TimeoutTimestamp::At(event.timeout_timestamp_on_b) + } else { + TimeoutTimestamp::Never + }; /* FIXME: the packet data format in Cairo is incompatible with the packet data on Cosmos. diff --git a/relayer/crates/starknet-chain-components/src/impls/packet_fields.rs b/relayer/crates/starknet-chain-components/src/impls/packet_fields.rs index 946b8ec8..f538778e 100644 --- a/relayer/crates/starknet-chain-components/src/impls/packet_fields.rs +++ b/relayer/crates/starknet-chain-components/src/impls/packet_fields.rs @@ -14,6 +14,6 @@ where + HasChannelIdType, { fn packet_src_channel_id(packet: &Packet) -> ChannelId { - packet.chan_id_on_b.clone() + packet.chan_id_on_a.clone() } } diff --git a/relayer/crates/starknet-chain-components/src/impls/payload_builders/create_client.rs b/relayer/crates/starknet-chain-components/src/impls/payload_builders/create_client.rs index e816da8e..27f858b7 100644 --- a/relayer/crates/starknet-chain-components/src/impls/payload_builders/create_client.rs +++ b/relayer/crates/starknet-chain-components/src/impls/payload_builders/create_client.rs @@ -27,6 +27,7 @@ where > + HasCreateClientPayloadType + CanQueryChainStatus + HasChainId + + CanRaiseAsyncError<&'static str> + CanRaiseAsyncError, { async fn build_create_client_payload( @@ -40,7 +41,10 @@ where let consensus_state = WasmStarknetConsensusState { consensus_state: StarknetConsensusState { root: root.into(), - time: Timestamp::now(), + time: u64::try_from(chain_status.time.unix_timestamp_nanos()) + .ok() + .map(Timestamp::from_nanoseconds) + .ok_or_else(|| Chain::raise_error("invalid timestamp"))?, }, }; diff --git a/relayer/crates/starknet-chain-components/src/impls/payload_builders/update_client.rs b/relayer/crates/starknet-chain-components/src/impls/payload_builders/update_client.rs index 4c521766..03a28601 100644 --- a/relayer/crates/starknet-chain-components/src/impls/payload_builders/update_client.rs +++ b/relayer/crates/starknet-chain-components/src/impls/payload_builders/update_client.rs @@ -40,18 +40,20 @@ where .await .map_err(Chain::raise_error)?; - let block_hash = match block_info { - MaybePendingBlockWithTxHashes::Block(block) => block.block_hash, + let block = match block_info { + MaybePendingBlockWithTxHashes::Block(block) => block, MaybePendingBlockWithTxHashes::PendingBlock(_block) => { return Err(Chain::raise_error("pending block is not supported")) } }; + let block_hash = block.block_hash; + let root = Vec::from(block_hash.to_bytes_be()); let consensus_state = StarknetConsensusState { root: root.into(), - time: Timestamp::now(), + time: Timestamp::from_nanoseconds(block.timestamp * 1_000_000_000), }; let height = Height::new(0, *target_height).unwrap(); diff --git a/relayer/crates/starknet-chain-components/src/impls/queries/client_state.rs b/relayer/crates/starknet-chain-components/src/impls/queries/client_state.rs index 9c2ced21..fc4e47cc 100644 --- a/relayer/crates/starknet-chain-components/src/impls/queries/client_state.rs +++ b/relayer/crates/starknet-chain-components/src/impls/queries/client_state.rs @@ -37,6 +37,7 @@ where + HasBlobType> + HasEncoding + CanQueryContractAddress + + CanRaiseAsyncError<&'static str> + CanRaiseAsyncError, Counterparty: HasClientStateType, Encoding: CanEncode @@ -57,10 +58,10 @@ where let client_id_seq = client_id .as_str() .rsplit_once('-') - .expect("valid client id") + .ok_or_else(|| Chain::raise_error("invalid client id"))? .1 .parse::() - .expect("valid sequence"); + .map_err(|_| Chain::raise_error("invalid sequence"))?; let calldata = encoding .encode(&client_id_seq) diff --git a/relayer/crates/starknet-chain-components/src/impls/queries/consensus_state.rs b/relayer/crates/starknet-chain-components/src/impls/queries/consensus_state.rs index 2471f130..ca4b4641 100644 --- a/relayer/crates/starknet-chain-components/src/impls/queries/consensus_state.rs +++ b/relayer/crates/starknet-chain-components/src/impls/queries/consensus_state.rs @@ -45,6 +45,7 @@ where + HasEncoding + CanQueryContractAddress + CanRaiseAsyncError + + CanRaiseAsyncError<&'static str> + CanRaiseAsyncError, Counterparty: HasConsensusStateType + HasHeightFields, @@ -72,10 +73,10 @@ where let client_id_seq = client_id .as_str() .rsplit_once('-') - .expect("valid client id") + .ok_or_else(|| Chain::raise_error("invalid client id"))? .1 .parse::() - .expect("valid sequence"); + .map_err(|_| Chain::raise_error("invalid sequence"))?; let calldata = encoding .encode(&(client_id_seq, height.clone())) diff --git a/relayer/crates/starknet-chain-components/src/impls/queries/status.rs b/relayer/crates/starknet-chain-components/src/impls/queries/status.rs index 5259f136..2ea75431 100644 --- a/relayer/crates/starknet-chain-components/src/impls/queries/status.rs +++ b/relayer/crates/starknet-chain-components/src/impls/queries/status.rs @@ -28,7 +28,10 @@ where MaybePendingBlockWithTxHashes::Block(block) => Ok(StarknetChainStatus { height: block.block_number, block_hash: block.block_hash, - time: Time::now(), + time: i64::try_from(block.timestamp) + .ok() + .and_then(|ts| Time::from_unix_timestamp(ts, 0).ok()) + .ok_or_else(|| Chain::raise_error("invalid timestamp"))?, }), MaybePendingBlockWithTxHashes::PendingBlock(_) => Err(Chain::raise_error( "expected finalized block, but given pending block", diff --git a/relayer/crates/starknet-chain-components/src/types/client_id.rs b/relayer/crates/starknet-chain-components/src/types/client_id.rs index 502a3af0..24a5307c 100644 --- a/relayer/crates/starknet-chain-components/src/types/client_id.rs +++ b/relayer/crates/starknet-chain-components/src/types/client_id.rs @@ -10,7 +10,7 @@ pub struct EncodeClientId; impl MutEncoder for EncodeClientId where - Encoding: CanEncodeMut, + Encoding: CanEncodeMut + CanRaiseError<&'static str>, { fn encode_mut( encoding: &Encoding, @@ -18,9 +18,15 @@ where buffer: &mut Encoding::EncodeBuffer, ) -> Result<(), Encoding::Error> { // FIXME: add `sequence_number` method at `ibc-rs` - let (client_type, sequence) = value.as_str().rsplit_once('-').expect("valid client id"); - let seq_u64 = sequence.parse::().expect("valid sequence"); - let client_type_felt = string_to_felt(client_type).expect("valid client type"); + let (client_type, sequence) = value + .as_str() + .rsplit_once('-') + .ok_or_else(|| Encoding::raise_error("invalid client id"))?; + let seq_u64 = sequence + .parse::() + .map_err(|_| Encoding::raise_error("invalid sequence"))?; + let client_type_felt = string_to_felt(client_type) + .ok_or_else(|| Encoding::raise_error("invalid client type"))?; encoding.encode_mut(&product![client_type_felt, seq_u64], buffer)?; Ok(()) } diff --git a/relayer/crates/starknet-chain-components/src/types/cosmos/timestamp.rs b/relayer/crates/starknet-chain-components/src/types/cosmos/timestamp.rs index 943d5952..2c6100e2 100644 --- a/relayer/crates/starknet-chain-components/src/types/cosmos/timestamp.rs +++ b/relayer/crates/starknet-chain-components/src/types/cosmos/timestamp.rs @@ -1,35 +1,34 @@ -use cgp::core::component::UseContext; use cgp::prelude::*; -use hermes_encoding_components::impls::encode_mut::combine::CombineEncoders; -use hermes_encoding_components::impls::encode_mut::field::EncodeField; -use hermes_encoding_components::impls::encode_mut::from::DecodeFrom; -use hermes_encoding_components::traits::decode_mut::MutDecoderComponent; -use hermes_encoding_components::traits::encode_mut::MutEncoderComponent; -use hermes_encoding_components::traits::transform::Transformer; - -#[derive(Debug, Clone, HasField)] -pub struct Timestamp { - pub timestamp: u64, -} +use hermes_encoding_components::traits::decode_mut::{CanDecodeMut, MutDecoder}; +use hermes_encoding_components::traits::encode_mut::{CanEncodeMut, MutEncoder}; +pub use ibc::primitives::Timestamp; pub struct EncodeTimestamp; -delegate_components! { - EncodeTimestamp { - MutEncoderComponent: CombineEncoders< - Product![ - EncodeField, - ], - >, - MutDecoderComponent: DecodeFrom, +impl MutEncoder for EncodeTimestamp +where + Encoding: CanEncodeMut, +{ + fn encode_mut( + encoding: &Encoding, + value: &Timestamp, + buffer: &mut Encoding::EncodeBuffer, + ) -> Result<(), Encoding::Error> { + let unix_secs = value.nanoseconds() / 1_000_000_000; + encoding.encode_mut(&product![unix_secs], buffer)?; + Ok(()) } } -impl Transformer for EncodeTimestamp { - type From = u64; - type To = Timestamp; - - fn transform(timestamp: Self::From) -> Timestamp { - Timestamp { timestamp } +impl MutDecoder for EncodeTimestamp +where + Encoding: CanDecodeMut, +{ + fn decode_mut<'a>( + encoding: &Encoding, + buffer: &mut Encoding::DecodeBuffer<'a>, + ) -> Result { + let product![unix_secs] = encoding.decode_mut(buffer)?; + Ok(Timestamp::from_nanoseconds(unix_secs * 1_000_000_000)) } } diff --git a/relayer/crates/starknet-integration-tests/src/tests/ics20.rs b/relayer/crates/starknet-integration-tests/src/tests/ics20.rs index 6e9d0a83..0b8cb07c 100644 --- a/relayer/crates/starknet-integration-tests/src/tests/ics20.rs +++ b/relayer/crates/starknet-integration-tests/src/tests/ics20.rs @@ -536,10 +536,10 @@ fn test_starknet_ics20_contract() -> Result<(), Error> { revision_number: 0, revision_height: 0, }, - timeout_timestamp_on_b: Timestamp { - timestamp: u64::try_from(current_starknet_time.unix_timestamp()).unwrap() - + 1800, - }, + timeout_timestamp_on_b: Timestamp::from_nanoseconds( + u64::try_from(current_starknet_time.unix_timestamp() + 1800).unwrap() + * 1_000_000_000, + ), } }; @@ -628,10 +628,10 @@ fn test_starknet_ics20_contract() -> Result<(), Error> { revision_number: 0, revision_height: 0, }, - timeout_timestamp_on_b: Timestamp { - timestamp: u64::try_from(current_starknet_time.unix_timestamp()).unwrap() - + 1800, - }, + timeout_timestamp_on_b: Timestamp::from_nanoseconds( + u64::try_from(current_starknet_time.unix_timestamp() + 1800).unwrap() + * 1_000_000_000, + ), } };