diff --git a/Cargo.lock b/Cargo.lock index 082d564d0..59bed09c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -960,7 +960,7 @@ dependencies = [ [[package]] name = "ckb-ics-axon" version = "0.1.0" -source = "git+https://github.com/synapseweb3/ckb-ics.git?rev=ef124f9#ef124f9c0ed5b05e7b69d3b8c40c3d171082af4e" +source = "git+https://github.com/synapseweb3/ckb-ics.git?rev=cda7d4e#cda7d4ebbd89002fa983e43e79be722e83181304" dependencies = [ "bytes", "ethereum-types", diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index 66f26c1e0..0f33e3935 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -99,7 +99,7 @@ jsonrpc-core = "18.0" strum = { version = "0.24.1", features = ["derive"] } lazy_static = "1.4.0" -ckb-ics-axon = { git = "https://github.com/synapseweb3/ckb-ics.git", rev = "ef124f9" } +ckb-ics-axon = { git = "https://github.com/synapseweb3/ckb-ics.git", rev = "cda7d4e" } cstr_core = "0.2.6" rlp = "0.5.2" diff --git a/crates/relayer/src/chain.rs b/crates/relayer/src/chain.rs index 69b067948..b362f8d77 100644 --- a/crates/relayer/src/chain.rs +++ b/crates/relayer/src/chain.rs @@ -11,6 +11,8 @@ pub mod requests; pub mod runtime; pub mod tracking; +pub const SEC_TO_NANO: u64 = 1_000_000_000; + use serde::{de::Error, Deserialize, Serialize}; // NOTE(new): When adding a variant to `ChainType`, make sure to update diff --git a/crates/relayer/src/chain/axon/msg.rs b/crates/relayer/src/chain/axon/msg.rs index 2aacef53b..f041c6859 100644 --- a/crates/relayer/src/chain/axon/msg.rs +++ b/crates/relayer/src/chain/axon/msg.rs @@ -39,11 +39,8 @@ use ibc_relayer_types::{ Height, }; -use super::{ - contract, - utils::{to_timestamp, SEC_TO_NANO}, -}; -use crate::error::Error; +use super::{contract, utils::to_timestamp}; +use crate::{chain::SEC_TO_NANO, error::Error}; fn into_ethers_client_id(value: Option) -> String { match value { diff --git a/crates/relayer/src/chain/axon/utils.rs b/crates/relayer/src/chain/axon/utils.rs index e5c919394..639bc6bee 100644 --- a/crates/relayer/src/chain/axon/utils.rs +++ b/crates/relayer/src/chain/axon/utils.rs @@ -7,6 +7,7 @@ use ckb_ics_axon::proof::{ use rlp::Encodable; use crate::{ + chain::SEC_TO_NANO, client_state::{AnyClientState, IdentifiedAnyClientState}, consensus_state::AnyConsensusState, error::Error, @@ -21,8 +22,6 @@ use ibc_relayer_types::{ timestamp::Timestamp, }; -pub const SEC_TO_NANO: u64 = 1_000_000_000; - pub fn to_timestamp(seconds: u64) -> Result { Timestamp::from_nanoseconds(seconds * SEC_TO_NANO).map_err(convert_err) } diff --git a/crates/relayer/src/chain/ckb4ibc.rs b/crates/relayer/src/chain/ckb4ibc.rs index 7aff026b7..e16ac9f21 100644 --- a/crates/relayer/src/chain/ckb4ibc.rs +++ b/crates/relayer/src/chain/ckb4ibc.rs @@ -72,7 +72,7 @@ use self::extractor::{extract_connections_from_tx, extract_ibc_packet_from_tx}; use self::message::{convert_msg_to_ckb_tx, CkbTxInfo, Converter, MsgToTxConverter}; use self::monitor::Ckb4IbcEventMonitor; use self::utils::{ - convert_port_id_to_array, get_channel_idx, get_dummy_merkle_proof, get_encoded_object, + convert_port_id_to_array, get_channel_number, get_dummy_merkle_proof, get_encoded_object, get_search_key, }; @@ -227,7 +227,7 @@ impl Ckb4IbcChain { .hash_type(ScriptHashType::Type.into()) .args( PacketArgs { - channel_id: get_channel_idx(channel_id)?, + channel_id: get_channel_number(channel_id)?, port_id: port_id.as_str().as_bytes().try_into().unwrap(), sequence, } @@ -281,7 +281,7 @@ impl Ckb4IbcChain { let channel_args = ChannelArgs { client_id, open: is_open, - channel_id: get_channel_idx(&channel_id)?, + channel_id: get_channel_number(&channel_id)?, port_id: convert_port_id_to_array(&port_id)?, }; let script = Script::new_builder() @@ -1004,7 +1004,7 @@ impl ChainEndpoint for Ckb4IbcChain { } else { Ok(( PacketArgs { - channel_id: get_channel_idx(&request.channel_id)?, + channel_id: get_channel_number(&request.channel_id)?, port_id: ibc_packet .packet .source_port_id @@ -1046,7 +1046,7 @@ impl ChainEndpoint for Ckb4IbcChain { } else { Ok(( PacketArgs { - channel_id: get_channel_idx(&request.channel_id)?, + channel_id: get_channel_number(&request.channel_id)?, port_id: ibc_packet .packet .source_port_id diff --git a/crates/relayer/src/chain/ckb4ibc/message/chan.rs b/crates/relayer/src/chain/ckb4ibc/message/chan.rs index d539f32b3..838c2ff5a 100644 --- a/crates/relayer/src/chain/ckb4ibc/message/chan.rs +++ b/crates/relayer/src/chain/ckb4ibc/message/chan.rs @@ -23,7 +23,7 @@ use std::str::FromStr; use super::{CkbTxInfo, MsgToTxConverter, TxBuilder}; use crate::chain::ckb4ibc::utils::{ convert_port_id_to_array, convert_proof, extract_client_id_by_connection_id, - generate_channel_id, get_channel_capacity, get_channel_idx, get_channel_lock_script, + generate_channel_id, get_channel_capacity, get_channel_lock_script, get_channel_number, get_client_id_from_channel, get_client_outpoint, get_connection_capacity, get_connection_lock_script, get_encoded_object, }; @@ -217,7 +217,7 @@ pub fn convert_chan_open_ack_to_tx( msg: MsgChannelOpenAck, converter: &C, ) -> Result { - let channel_idx = get_channel_idx(&msg.channel_id)?; + let channel_idx = get_channel_number(&msg.channel_id)?; let old_channel = converter.get_ibc_channel(&msg.channel_id); let counterparty_port_id = PortId::from_str(&old_channel.counterparty.port_id).unwrap(); let mut new_channel = old_channel.clone(); @@ -298,7 +298,7 @@ pub fn convert_chan_open_confirm_to_tx( let channel_args = ChannelArgs { client_id: client_cell_type_args, open: true, - channel_id: get_channel_idx(&msg.channel_id)?, + channel_id: get_channel_number(&msg.channel_id)?, port_id: convert_port_id_to_array(&msg.port_id)?, }; diff --git a/crates/relayer/src/chain/ckb4ibc/message/packet.rs b/crates/relayer/src/chain/ckb4ibc/message/packet.rs index f1c5d9561..13a4fd82f 100644 --- a/crates/relayer/src/chain/ckb4ibc/message/packet.rs +++ b/crates/relayer/src/chain/ckb4ibc/message/packet.rs @@ -5,7 +5,7 @@ use ckb_ics_axon::message::Envelope; use ckb_ics_axon::message::MsgAckPacket as CkbMsgAckPacket; use ckb_ics_axon::message::MsgRecvPacket as CkbMsgRecvPacket; use ckb_ics_axon::message::MsgType; -use ckb_ics_axon::object::Packet as CkbPacket; +use ckb_ics_axon::object::{Ordering, Packet as CkbPacket}; use ckb_ics_axon::{ChannelArgs, PacketArgs}; use ckb_types::packed::BytesOpt; use ibc_relayer_types::core::ics04_channel::msgs::acknowledgement::MsgAcknowledgement; @@ -14,13 +14,14 @@ use ibc_relayer_types::core::ics04_channel::packet::Packet; use super::{CkbTxInfo, MsgToTxConverter, TxBuilder}; use crate::chain::ckb4ibc::utils::{ - convert_proof, extract_client_id_by_connection_id, get_channel_capacity, get_channel_idx, - get_channel_lock_script, get_client_outpoint, get_encoded_object, get_packet_capacity, - get_packet_lock_script, + convert_port_id_to_array, convert_proof, extract_client_id_by_connection_id, + get_channel_capacity, get_channel_lock_script, get_channel_number, get_client_outpoint, + get_encoded_object, get_packet_capacity, get_packet_lock_script, }; +use crate::chain::SEC_TO_NANO; use crate::error::Error; -fn convert_ibc_packet(packet: Packet) -> CkbPacket { +fn convert_ibc_packet(packet: &Packet) -> CkbPacket { let seq: u64 = packet.sequence.into(); let source_port_id = packet.source_port.to_string(); let source_channel_id = packet.source_channel.to_string(); @@ -32,129 +33,139 @@ fn convert_ibc_packet(packet: Packet) -> CkbPacket { source_channel_id, destination_port_id, destination_channel_id, - data: packet.data, + data: packet.data.clone(), timeout_height: packet.timeout_height.commitment_revision_height(), - timeout_timestamp: packet.timeout_timestamp.nanoseconds() / 100000, // use second as unit + timeout_timestamp: packet.timeout_timestamp.nanoseconds() / SEC_TO_NANO, } } -pub fn convert_ack_packet_to_tx( - msg: MsgAcknowledgement, +pub fn convert_recv_packet_to_tx( + msg: MsgRecvPacket, converter: &C, ) -> Result { - let channel_id = msg.packet.source_channel.clone(); + let channel_id = msg.packet.destination_channel.clone(); let old_channel_end = converter.get_ibc_channel(&channel_id); let mut new_channel_end = old_channel_end.clone(); - new_channel_end.sequence.next_sequence_acks += 1; - let old_channel = get_encoded_object(old_channel_end); - let new_channel = get_encoded_object(new_channel_end.clone()); - let ckb_msg = CkbMsgAckPacket { + let packet = convert_ibc_packet(&msg.packet); + match old_channel_end.order { + Ordering::Ordered => new_channel_end.sequence.next_sequence_recvs += 1, + Ordering::Unordered => { + new_channel_end + .sequence + .received_sequences + .push(packet.sequence); + } + Ordering::Unknown => return Err(Error::other("channel ordering must be Order or Unorder")), + } + + let recv_packet = CkbMsgRecvPacket { proofs: convert_proof(msg.proofs)?, - acknowledgement: msg.acknowledgement.as_ref().to_vec(), }; let envelope = Envelope { - msg_type: MsgType::MsgAckPacket, - content: rlp::encode(&ckb_msg).to_vec(), + msg_type: MsgType::MsgRecvPacket, + content: rlp::encode(&recv_packet).to_vec(), }; - let port_id = msg.packet.source_port.clone(); - let channel_input = converter.get_ibc_channel_input(&channel_id, &msg.packet.source_port); - let sequence = msg.packet.sequence; - let packet = convert_ibc_packet(msg.packet); - let seq = packet.sequence; - let new_ibc_packet = IbcPacket { - packet, - tx_hash: None, - status: PacketStatus::Ack, + let port_id = convert_port_id_to_array(&msg.packet.destination_port)?; + let channel_number = get_channel_number(&channel_id)?; + let packet_args = PacketArgs { + channel_id: channel_number, + port_id, + sequence: packet.sequence, }; - let new_packet = get_encoded_object(new_ibc_packet); - let old_ibc_packet_input = - converter.get_packet_cell_input(channel_id.clone(), port_id.clone(), sequence); - let channel_idx = get_channel_idx(&channel_id)?; - let port_id_in_args: [u8; 32] = port_id.as_bytes().try_into().unwrap(); let (client_cell_type_args, client_id) = extract_client_id_by_connection_id(&new_channel_end.connection_hops[0], converter)?; let channel_args = ChannelArgs { client_id: client_cell_type_args, open: true, - channel_id: channel_idx, - port_id: port_id_in_args, - }; - let packet_args = PacketArgs { - channel_id: channel_idx, - port_id: port_id_in_args, - sequence: seq, + channel_id: channel_number, + port_id, }; + let old_channel = get_encoded_object(old_channel_end); + let new_channel = get_encoded_object(new_channel_end); + let ibc_packet = get_encoded_object(IbcPacket { + packet, + tx_hash: None, + status: PacketStatus::Recv, + }); + + let channel_input = converter.get_ibc_channel_input(&channel_id, &msg.packet.source_port); let channel_lock = get_channel_lock_script(converter, channel_args.to_args()); let packet_lock = get_packet_lock_script(converter, packet_args.to_args()); let packed_tx = TxBuilder::default() .cell_dep(get_client_outpoint(converter, &client_id)?) - .cell_dep(converter.get_chan_contract_outpoint()) .input(channel_input) - .input(old_ibc_packet_input) + // TODO: fetch useless packet cell as input to save capacity + // .input() .output(channel_lock, get_channel_capacity(), new_channel.data) - .output(packet_lock, get_packet_capacity(), new_packet.data) + .output(packet_lock, get_packet_capacity(), ibc_packet.data) .witness(old_channel.witness, new_channel.witness) - .witness(BytesOpt::default(), new_packet.witness) + .witness(BytesOpt::default(), ibc_packet.witness) .build(); Ok(CkbTxInfo { unsigned_tx: Some(packed_tx), envelope, - input_capacity: CHANNEL_CELL_CAPACITY + PACKET_CELL_CAPACITY, + input_capacity: PACKET_CELL_CAPACITY, event: None, }) } -pub fn convert_recv_packet_to_tx( - msg: MsgRecvPacket, +pub fn convert_ack_packet_to_tx( + msg: MsgAcknowledgement, converter: &C, ) -> Result { - let channel_id = msg.packet.destination_channel.clone(); + let channel_id = msg.packet.source_channel.clone(); let old_channel_end = converter.get_ibc_channel(&channel_id); let mut new_channel_end = old_channel_end.clone(); - new_channel_end.sequence.next_sequence_recvs += 1; + + match old_channel_end.order { + Ordering::Ordered => new_channel_end.sequence.next_sequence_acks += 1, + Ordering::Unordered => {} + Ordering::Unknown => return Err(Error::other("channel ordering must be Order or Unorder")), + } let old_channel = get_encoded_object(old_channel_end); let new_channel = get_encoded_object(new_channel_end.clone()); - let ckb_msg = CkbMsgRecvPacket { + let ack_packet = CkbMsgAckPacket { proofs: convert_proof(msg.proofs)?, + acknowledgement: msg.acknowledgement.as_ref().to_vec(), }; let envelope = Envelope { - msg_type: MsgType::MsgRecvPacket, - content: rlp::encode(&ckb_msg).to_vec(), + msg_type: MsgType::MsgAckPacket, + content: rlp::encode(&ack_packet).to_vec(), }; - let port_id = msg.packet.destination_port.clone(); - let channel_input = converter.get_ibc_channel_input(&channel_id, &msg.packet.source_port); - let packet = convert_ibc_packet(msg.packet); - let seq = packet.sequence; - let ibc_packet = IbcPacket { + let channel_number = get_channel_number(&channel_id)?; + let packet = convert_ibc_packet(&msg.packet); + let port_id = convert_port_id_to_array(&msg.packet.source_port)?; + let packet_args = PacketArgs { + sequence: packet.sequence, + channel_id: channel_number, + port_id, + }; + + let new_packet = get_encoded_object(IbcPacket { packet, tx_hash: None, - status: PacketStatus::Recv, - }; - let packet = get_encoded_object(ibc_packet); - let channel_idx = get_channel_idx(&channel_id)?; - let port_id_in_args: [u8; 32] = port_id.as_str().as_bytes().try_into().unwrap(); + status: PacketStatus::Ack, + }); + let channel_input = converter.get_ibc_channel_input(&channel_id, &msg.packet.source_port); + let old_packet = + converter.get_packet_cell_input(channel_id, msg.packet.source_port, msg.packet.sequence); let (client_cell_type_args, client_id) = extract_client_id_by_connection_id(&new_channel_end.connection_hops[0], converter)?; let channel_args = ChannelArgs { client_id: client_cell_type_args, open: true, - channel_id: channel_idx, - port_id: port_id_in_args, - }; - let packet_args = PacketArgs { - channel_id: channel_idx, - port_id: port_id_in_args, - sequence: seq, + channel_id: channel_number, + port_id, }; let channel_lock = get_channel_lock_script(converter, channel_args.to_args()); @@ -162,17 +173,19 @@ pub fn convert_recv_packet_to_tx( let packed_tx = TxBuilder::default() .cell_dep(get_client_outpoint(converter, &client_id)?) + .cell_dep(converter.get_chan_contract_outpoint()) .input(channel_input) + .input(old_packet) .output(channel_lock, get_channel_capacity(), new_channel.data) - .output(packet_lock, get_packet_capacity(), packet.data) + .output(packet_lock, get_packet_capacity(), new_packet.data) .witness(old_channel.witness, new_channel.witness) - .witness(BytesOpt::default(), packet.witness) + .witness(BytesOpt::default(), new_packet.witness) .build(); Ok(CkbTxInfo { unsigned_tx: Some(packed_tx), envelope, - input_capacity: PACKET_CELL_CAPACITY, + input_capacity: CHANNEL_CELL_CAPACITY + PACKET_CELL_CAPACITY, event: None, }) } diff --git a/crates/relayer/src/chain/ckb4ibc/utils.rs b/crates/relayer/src/chain/ckb4ibc/utils.rs index c0289d114..05170b080 100644 --- a/crates/relayer/src/chain/ckb4ibc/utils.rs +++ b/crates/relayer/src/chain/ckb4ibc/utils.rs @@ -72,7 +72,7 @@ pub fn get_script_hash(type_args: &H256) -> Byte32 { script.calc_script_hash() } -pub fn get_channel_idx(id: &ChannelId) -> Result { +pub fn get_channel_number(id: &ChannelId) -> Result { let s = id.as_str(); let result = s .strip_prefix(CHANNEL_ID_PREFIX) diff --git a/tools/ckb4ibc-test/Cargo.toml b/tools/ckb4ibc-test/Cargo.toml index 03a9dd10b..4fe7b2d16 100644 --- a/tools/ckb4ibc-test/Cargo.toml +++ b/tools/ckb4ibc-test/Cargo.toml @@ -27,7 +27,7 @@ jsonrpc-core = "18.0" futures = "0.3.27" serde_json = { version = "1", default-features = false } serde = { version = "1.0", default-features = false } -ckb-ics-axon = { git = "https://github.com/synapseweb3/ckb-ics.git", rev = "ef124f9" } +ckb-ics-axon = { git = "https://github.com/synapseweb3/ckb-ics.git", rev = "cda7d4e" } rlp = "0.5.2" secp256k1 = "0.24" ckb-hash = "0.106"