Skip to content

Commit

Permalink
fix(relayer): use starknet block timestamp (#244)
Browse files Browse the repository at this point in the history
* use starknet block timestamp

* use ibc-rs timestamp

* refactor for timestamp

* src chan id is of a

* avoid using expect in hermes components

* fix error message

* avoid expect in relayer comps
  • Loading branch information
rnbguy authored Jan 31, 2025
1 parent 76a83f4 commit a3248f9
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ where
+ HasChannelIdType<Counterparty, ChannelId = ChannelId>,
{
fn packet_src_channel_id(packet: &Packet) -> ChannelId {
packet.chan_id_on_b.clone()
packet.chan_id_on_a.clone()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ where
> + HasCreateClientPayloadType<Counterparty, CreateClientPayload = StarknetCreateClientPayload>
+ CanQueryChainStatus<ChainStatus = StarknetChainStatus>
+ HasChainId<ChainId = ChainId>
+ CanRaiseAsyncError<&'static str>
+ CanRaiseAsyncError<ClientError>,
{
async fn build_create_client_payload(
Expand All @@ -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"))?,
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ where
+ HasBlobType<Blob = Vec<Felt>>
+ HasEncoding<AsFelt, Encoding = Encoding>
+ CanQueryContractAddress<symbol!("ibc_client_contract_address")>
+ CanRaiseAsyncError<&'static str>
+ CanRaiseAsyncError<Encoding::Error>,
Counterparty: HasClientStateType<Chain, ClientState = CometClientState>,
Encoding: CanEncode<ViaCairo, u64>
Expand All @@ -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::<u64>()
.expect("valid sequence");
.map_err(|_| Chain::raise_error("invalid sequence"))?;

let calldata = encoding
.encode(&client_id_seq)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ where
+ HasEncoding<AsFelt, Encoding = Encoding>
+ CanQueryContractAddress<symbol!("ibc_client_contract_address")>
+ CanRaiseAsyncError<ConsensusStateNotFound>
+ CanRaiseAsyncError<&'static str>
+ CanRaiseAsyncError<Encoding::Error>,
Counterparty:
HasConsensusStateType<Chain, ConsensusState = CometConsensusState> + HasHeightFields,
Expand Down Expand Up @@ -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::<u64>()
.expect("valid sequence");
.map_err(|_| Chain::raise_error("invalid sequence"))?;

let calldata = encoding
.encode(&(client_id_seq, height.clone()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
14 changes: 10 additions & 4 deletions relayer/crates/starknet-chain-components/src/types/client_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,23 @@ pub struct EncodeClientId;

impl<Encoding, Strategy> MutEncoder<Encoding, Strategy, ClientId> for EncodeClientId
where
Encoding: CanEncodeMut<Strategy, Product![Felt, u64]>,
Encoding: CanEncodeMut<Strategy, Product![Felt, u64]> + CanRaiseError<&'static str>,
{
fn encode_mut(
encoding: &Encoding,
value: &ClientId,
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::<u64>().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::<u64>()
.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(())
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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<symbol!("timestamp"), UseContext>,
],
>,
MutDecoderComponent: DecodeFrom<Self, UseContext>,
impl<Encoding, Strategy> MutEncoder<Encoding, Strategy, Timestamp> for EncodeTimestamp
where
Encoding: CanEncodeMut<Strategy, Product![u64]>,
{
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<Encoding, Strategy> MutDecoder<Encoding, Strategy, Timestamp> for EncodeTimestamp
where
Encoding: CanDecodeMut<Strategy, Product![u64]>,
{
fn decode_mut<'a>(
encoding: &Encoding,
buffer: &mut Encoding::DecodeBuffer<'a>,
) -> Result<Timestamp, Encoding::Error> {
let product![unix_secs] = encoding.decode_mut(buffer)?;
Ok(Timestamp::from_nanoseconds(unix_secs * 1_000_000_000))
}
}
16 changes: 8 additions & 8 deletions relayer/crates/starknet-integration-tests/src/tests/ics20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
),
}
};

Expand Down Expand Up @@ -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,
),
}
};

Expand Down

0 comments on commit a3248f9

Please sign in to comment.