diff --git a/Cargo.lock b/Cargo.lock index ce018677d..0a8754d63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -350,6 +350,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "autotools" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8da1805e028a172334c3b680f93e71126f2327622faef2ec3d893c0a4ad77" +dependencies = [ + "cc", +] + [[package]] name = "axon-tools" version = "0.1.1" @@ -668,7 +677,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" dependencies = [ - "sha2 0.10.7", + "sha2 0.10.8", "tinyvec", ] @@ -1081,6 +1090,26 @@ dependencies = [ "blake2b-rs", ] +[[package]] +name = "ckb-ics-axon" +version = "0.1.0" +source = "git+https://github.com/synapseweb3/ckb-ics.git?rev=45cdaa470cb#45cdaa470cb328ce258711deec9c3a62277ff513" +dependencies = [ + "axon-tools", + "axon-types", + "bytes", + "ethereum-types", + "hex", + "molecule", + "prost 0.12.1", + "prost-build", + "protobuf-src", + "rlp", + "rlp-derive", + "sha2 0.10.8", + "tiny-keccak", +] + [[package]] name = "ckb-ics-axon" version = "0.1.0" @@ -1493,7 +1522,7 @@ dependencies = [ "hmac", "k256 0.13.1", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", ] @@ -1509,7 +1538,7 @@ dependencies = [ "once_cell", "pbkdf2 0.12.2", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", ] @@ -1528,7 +1557,7 @@ dependencies = [ "ripemd", "serde", "serde_derive", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "thiserror", ] @@ -2179,7 +2208,7 @@ dependencies = [ "derivation-path", "ed25519-dalek", "hmac", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -2380,7 +2409,7 @@ dependencies = [ "scrypt", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "thiserror", "uuid 0.8.2", @@ -2394,7 +2423,7 @@ dependencies = [ "cpufeatures", "lazy_static", "ring", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -2754,7 +2783,7 @@ dependencies = [ "eth-keystore", "ethers-core", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "tracing", ] @@ -2931,7 +2960,7 @@ dependencies = [ "async-stream", "bytes", "ckb-fixed-hash 0.111.0", - "ckb-ics-axon", + "ckb-ics-axon 0.1.0 (git+https://github.com/synapseweb3/ckb-ics.git?rev=bfd8ab46a1f1fc)", "ckb-jsonrpc-types", "ckb-sdk", "ckb-types", @@ -3718,7 +3747,7 @@ dependencies = [ "bs58 0.4.0", "bytes", "ckb-hash 0.111.0", - "ckb-ics-axon", + "ckb-ics-axon 0.1.0 (git+https://github.com/synapseweb3/ckb-ics.git?rev=45cdaa470cb)", "ckb-jsonrpc-types", "ckb-sdk", "ckb-types", @@ -3767,7 +3796,7 @@ dependencies = [ "serde_derive", "serde_json", "serial_test", - "sha2 0.10.7", + "sha2 0.10.8", "signature 1.6.4", "strum 0.24.1", "subtle-encoding", @@ -3926,7 +3955,7 @@ dependencies = [ "bytes", "ckb-chain-spec", "ckb-hash 0.106.0", - "ckb-ics-axon", + "ckb-ics-axon 0.1.0 (git+https://github.com/synapseweb3/ckb-ics.git?rev=45cdaa470cb)", "ckb-jsonrpc-types", "ckb-sdk", "ckb-types", @@ -3978,7 +4007,7 @@ dependencies = [ "serde_derive", "serde_json", "serde_yaml 0.9.25", - "sha2 0.10.7", + "sha2 0.10.8", "subtle-encoding", "tendermint-rpc", "tokio", @@ -3999,7 +4028,7 @@ dependencies = [ "hex", "prost 0.11.9", "ripemd", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", ] @@ -4302,7 +4331,7 @@ dependencies = [ "cfg-if 1.0.0", "ecdsa 0.14.8", "elliptic-curve 0.12.3", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -4315,7 +4344,7 @@ dependencies = [ "ecdsa 0.16.8", "elliptic-curve 0.13.5", "once_cell", - "sha2 0.10.7", + "sha2 0.10.8", "signature 2.1.0", ] @@ -4717,6 +4746,12 @@ name = "molecule2" version = "0.1.0" source = "git+https://github.com/axonweb3/axon-contract?rev=8c2338a#8c2338ad5a3b32f260b5da234536f2681bf7712b" +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + [[package]] name = "multipart" version = "0.18.0" @@ -5246,7 +5281,7 @@ dependencies = [ "digest 0.10.7", "hmac", "password-hash", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -5349,7 +5384,7 @@ checksum = "b42f0394d3123e33353ca5e1e89092e533d2cc490389f2bd6131c43c634ebc5f" dependencies = [ "once_cell", "pest", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -5658,6 +5693,28 @@ dependencies = [ "prost-derive 0.12.1", ] +[[package]] +name = "prost-build" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bdf592881d821b83d471f8af290226c8d51402259e9bb5be7f9f8bdebbb11ac" +dependencies = [ + "bytes", + "heck", + "itertools 0.10.5", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost 0.12.1", + "prost-types 0.12.1", + "regex", + "syn 2.0.31", + "tempfile", + "which", +] + [[package]] name = "prost-derive" version = "0.11.9" @@ -5693,12 +5750,30 @@ dependencies = [ "prost 0.11.9", ] +[[package]] +name = "prost-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e081b29f63d83a4bc75cfc9f3fe424f9156cf92d8a4f0c9407cce9a1b67327cf" +dependencies = [ + "prost 0.12.1", +] + [[package]] name = "protobuf" version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" +[[package]] +name = "protobuf-src" +version = "1.1.0+21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7ac8852baeb3cc6fb83b93646fb93c0ffe5d14bf138c945ceb4b9948ee0e3c1" +dependencies = [ + "autotools", +] + [[package]] name = "pulldown-cmark" version = "0.9.3" @@ -6481,7 +6556,7 @@ dependencies = [ "hmac", "pbkdf2 0.11.0", "salsa20", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -6832,9 +6907,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -7172,7 +7247,7 @@ dependencies = [ "semver", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "url", "zip", @@ -7277,13 +7352,13 @@ dependencies = [ "num-traits", "once_cell", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "ripemd", "serde", "serde_bytes", "serde_json", "serde_repr", - "sha2 0.10.7", + "sha2 0.10.8", "signature 1.6.4", "subtle", "subtle-encoding", @@ -7352,7 +7427,7 @@ dependencies = [ "num-derive", "num-traits", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "serde", "serde_bytes", "subtle-encoding", @@ -7557,7 +7632,7 @@ dependencies = [ "pbkdf2 0.11.0", "rand 0.8.5", "rustc-hash", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "unicode-normalization", "wasm-bindgen", diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index fede34f51..fedb645ba 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -104,7 +104,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 = "bfd8ab46a1f1fc" } +ckb-ics-axon = { git = "https://github.com/synapseweb3/ckb-ics.git", rev = "45cdaa470cb" } cstr_core = "0.2.6" rlp = "0.5.2" diff --git a/crates/relayer/src/chain/axon.rs b/crates/relayer/src/chain/axon.rs index 60b7bd88f..158266412 100644 --- a/crates/relayer/src/chain/axon.rs +++ b/crates/relayer/src/chain/axon.rs @@ -1,15 +1,9 @@ -use std::{ - collections::HashMap, - str::FromStr, - sync::{Arc, RwLock}, - thread, - time::Duration, -}; +use std::{str::FromStr, sync::Arc, thread, time::Duration}; use axon_tools::types::{Block as AxonBlock, Proof as AxonProof, ValidatorExtend}; +use ckb_ics_axon::{axon_client::{commitment_slot, AxonCommitmentProof}, commitment::{connection_path, channel_path}}; use eth2_types::Hash256; use k256::ecdsa::SigningKey; -use rlp::Encodable; use tracing::{debug, warn}; use crate::{ @@ -30,12 +24,10 @@ use crate::{ light_client::{axon::LightClient as AxonLightClient, LightClient}, misbehaviour::MisbehaviourEvidence, }; -use eth_light_client_in_ckb_prover::Receipts; use ethers::{ prelude::*, providers::{Http, Middleware, Provider}, signers::{Signer as _, Wallet}, - utils::rlp, }; use ibc_proto::{ google::protobuf::Any, @@ -93,7 +85,7 @@ use super::{ client::ClientSettings, cosmos::encode::key_pair_to_signer, endpoint::{ChainEndpoint, ChainStatus, HealthCheck}, - handle::{CacheTxHashStatus, Subscription}, + handle::Subscription, requests::{ CrossChainQueryRequest, IncludeProof, QueryChannelClientStateRequest, QueryChannelRequest, QueryChannelsRequest, QueryClientConnectionsRequest, QueryClientEventRequest, @@ -140,13 +132,6 @@ abigen!( ]" ); -#[derive(Default)] -pub struct IBCInfoCache { - conn_tx_hash: HashMap, - chan_tx_hash: HashMap<(ChannelId, PortId), TxHash>, - packet_tx_hash: HashMap<(ChannelId, PortId, u64), TxHash>, -} - pub struct AxonChain { rt: Arc, config: AxonChainConfig, @@ -156,7 +141,6 @@ pub struct AxonChain { client: Provider, keybase: KeyRing, chain_id: u64, - ibc_cache: Arc>, } impl AxonChain { @@ -214,7 +198,6 @@ impl ChainEndpoint for AxonChain { .map_err(|e| Error::other_error(e.to_string()))? .as_u64(); let light_client = AxonLightClient::from_config(&config, rt.clone())?; - let ibc_cache = Arc::new(RwLock::new(IBCInfoCache::default())); // TODO: since Ckb endpoint uses Axon metadata cell as its light client, Axon // endpoint has no need to monitor the update of its metadata @@ -234,7 +217,6 @@ impl ChainEndpoint for AxonChain { chain_id, rpc_client, client, - ibc_cache, }) } @@ -1133,7 +1115,6 @@ impl ChainEndpoint for AxonChain { Ok(vec![]) } - // TODO do we need to implement this? fn build_connection_proofs_and_client_state( &self, message_type: ConnectionMsgType, @@ -1141,20 +1122,13 @@ impl ChainEndpoint for AxonChain { _client_id: &ClientId, height: Height, ) -> Result<(Option, Proofs), Error> { + let path = connection_path(connection_id.as_str()); let state = match message_type { ConnectionMsgType::OpenTry => connection::State::Init, ConnectionMsgType::OpenAck => connection::State::TryOpen, ConnectionMsgType::OpenConfirm => connection::State::Open, }; - let ibc_cache = self.ibc_cache.read().unwrap(); - let tx_hash = ibc_cache - .conn_tx_hash - .get(connection_id) - .ok_or(Error::conn_proof( - connection_id.clone(), - format!("missing connection tx_hash, state {state:?}"), - ))?; - let proofs = self.get_proofs(tx_hash, height).map_err(|e| { + let proofs = self.get_proofs(height, &path).map_err(|e| { Error::conn_proof( connection_id.clone(), format!("{}, state {state:?}", e.detail()), @@ -1169,16 +1143,8 @@ impl ChainEndpoint for AxonChain { channel_id: &ChannelId, height: Height, ) -> Result { - let ibc_cache = self.ibc_cache.read().unwrap(); - let tx_hash = ibc_cache - .chan_tx_hash - .get(&(channel_id.clone(), port_id.clone())) - .ok_or(Error::chan_proof( - port_id.clone(), - channel_id.clone(), - "missing channel tx_hash".to_owned(), - ))?; - let proofs = self.get_proofs(tx_hash, height).map_err(|e| { + let path = channel_path(port_id.as_str(), channel_id.as_str()); + let proofs = self.get_proofs(height, &path).map_err(|e| { Error::chan_proof(port_id.clone(), channel_id.clone(), e.detail().to_string()) })?; Ok(proofs) @@ -1192,19 +1158,12 @@ impl ChainEndpoint for AxonChain { sequence: Sequence, height: Height, ) -> Result { - let ibc_cache = self.ibc_cache.read().unwrap(); - let tx_hash = ibc_cache - .packet_tx_hash - .get(&(channel_id.clone(), port_id.clone(), sequence.into())) - .ok_or(Error::packet_proof( - port_id.clone(), - channel_id.clone(), - sequence.into(), - format!( - "missing packet tx_hash on {packet_type}({channel_id}/{port_id}/{sequence})" - ), - ))?; - let proofs = self.get_proofs(tx_hash, height).map_err(|e| { + let path_fn = match packet_type { + PacketMsgType::Ack => ckb_ics_axon::commitment::packet_acknowledgement_commitment_path, + _ => ckb_ics_axon::commitment::packet_commitment_path, + }; + let path = path_fn(port_id.as_str(), channel_id.as_str(), sequence.into()); + let proofs = self.get_proofs(height, &path).map_err(|e| { Error::chan_proof( port_id.clone(), channel_id.clone(), @@ -1264,123 +1223,88 @@ impl AxonChain { fn init_event_monitor(&mut self) -> Result { crate::time!("axon_init_event_monitor"); // let header_receiver = self.light_client.subscribe(); - let ibc_cache = self.ibc_cache.clone(); - let (mut event_monitor, monitor_tx) = AxonEventMonitor::new( + + // TODO: monitor should start from tip - restore_block_number. Or better + // yet, it should start from where it's shutdown. + let (event_monitor, monitor_tx) = AxonEventMonitor::new( self.config.id.clone(), self.config.websocket_addr.clone(), self.config.contract_address, // header_receiver, self.rt.clone(), - ibc_cache.clone(), ) .map_err(Error::event_monitor)?; - // restore past events to initialize tx_hash caches - let mut ibc_cache = ibc_cache.write().unwrap(); - let latest_block_count = self.config.restore_block_count; - event_monitor - .restore_event_tx_hashes(latest_block_count) - .map_err(Error::event_monitor)? - .into_iter() - .for_each(|v| cache_ics_tx_hash_with_event(&mut ibc_cache, v.event, v.tx_hash)); - thread::spawn(move || event_monitor.run()); Ok(monitor_tx) } - fn get_proofs(&self, tx_hash: &TxHash, height: Height) -> Result { - let receipt = self + fn get_proofs(&self, height: Height, commitment_path: &str) -> Result { + let block_number = height.revision_height(); + let (block, previous_state_root, block_proof, mut validators) = self .rt - .block_on(self.client.get_transaction_receipt(*tx_hash)) - .map_err(|e| Error::rpc_response(e.to_string()))? - .ok_or_else(|| { - Error::other_error(format!( - "can't find transaction receipt with hash {}", - hex::encode(tx_hash) - )) - })?; + .block_on(self.get_proofs_ingredients(block_number.into()))?; - let block_number = receipt.block_number.ok_or_else(|| { - Error::other_error(format!( - "transaction {} is still pending", - hex::encode(tx_hash) - )) - })?; + let debug_content = + generate_debug_content(&block, &previous_state_root, &block_proof, &validators); - let block = self - .rt - .block_on(self.client.get_block(block_number)) - .map_err(|e| Error::rpc_response(e.to_string()))? - .ok_or_else(|| { - Error::other_error(format!("can't find block with number {}", block_number)) + // check the validation of Axon block + axon_tools::verify_proof(block.clone(), previous_state_root, &mut validators, block_proof.clone()) + .map_err(|err| { + std::fs::write( + format!("./debug/axon_block_{block_number}.log"), + debug_content, + ) + .unwrap(); + let err_msg = format!("unverified axon block #{block_number}, err: {:?}", err); + Error::rpc_response(err_msg) })?; - let tx_receipts = block - .transactions - .into_iter() - .map(|tx_hash| { - let receipt = self - .rt - .block_on(self.client.get_transaction_receipt(tx_hash)); - match receipt { - Ok(Some(receipt)) => Ok(receipt), - Ok(None) => Err(Error::other_error(format!( - "can't find transaction receipt with hash {}", - hex::encode(tx_hash) - ))), - Err(e) => Err(Error::rpc_response(e.to_string())), - } - }) - .collect::, _>>()?; - let receipts: Receipts = tx_receipts.into(); - let receipt_proof = receipts.generate_proof(receipt.transaction_index.as_usize()); + let commitment_slot = commitment_slot(commitment_path.as_bytes()); - let (block, state_root, block_proof, mut validators) = self + let mut commitment_proof = self .rt - .block_on(self.get_proofs_ingredients(block_number))?; - - // check the validation of receipts mpt proof - let key = rlp::encode(&receipt.transaction_index.as_u64()); - let result = - axon_tools::verify_trie_proof(block.header.receipts_root, &key, receipt_proof.clone()) - .map_err(|e| Error::rpc_response(format!("unverified receipts mpt: {e:?}")))?; - if result.is_none() { - return Err(Error::rpc_response(format!( - "trie key: {} doesn't exist", - receipt.transaction_index - ))); - } - - let object_proof = - to_ckb_like_object_proof(&receipt, &receipt_proof, &block, &state_root, &block_proof) - .rlp_bytes() - .to_vec(); + .block_on(self.client.get_proof( + self.config.contract_address, + vec![commitment_slot.into()], + Some(block_number.into()), + )) + .unwrap(); + assert!(!commitment_proof.storage_proof.is_empty()); + let commitment_proof = AxonCommitmentProof { + block, + block_proof, + previous_state_root, + account_proof: commitment_proof + .account_proof + .into_iter() + .map(|p| p.0.into()) + .collect(), + storage_proof: commitment_proof + .storage_proof + .remove(0) + .proof + .into_iter() + .map(|p| p.0.into()) + .collect(), + }; + let object_proof = rlp::encode(&commitment_proof) + .freeze() + .to_vec() + .try_into() + .unwrap(); let useless_client_proof = vec![0u8].try_into().unwrap(); let useless_consensus_proof = ConsensusProof::new(vec![0u8].try_into().unwrap(), Height::default()).unwrap(); let proofs = Proofs::new( - object_proof.try_into().unwrap(), + object_proof, Some(useless_client_proof), Some(useless_consensus_proof), None, height, ) .unwrap(); - let debug_content = generate_debug_content(&block, &state_root, &block_proof, &validators); - - // check the validation of Axon block - axon_tools::verify_proof(block, state_root, &mut validators, block_proof).map_err( - |err| { - std::fs::write( - format!("./debug/axon_block_{block_number}.log"), - debug_content, - ) - .unwrap(); - let err_msg = format!("unverified axon block #{block_number}, err: {:?}", err); - Error::rpc_response(err_msg) - }, - )?; Ok(proofs) } @@ -1624,8 +1548,6 @@ impl AxonChain { })?; Height::from_noncosmos_height(block_height.as_u64()) }; - let mut ibc_cache = self.ibc_cache.write().unwrap(); - cache_ics_tx_hash_with_event(&mut ibc_cache, event.clone(), tx_hash); tracing::info!( "{} transaciton {} committed to {}", event.event_type().as_str(), @@ -1639,77 +1561,3 @@ impl AxonChain { }) } } - -fn cache_ics_tx_hash>( - ibc_cache: &mut IBCInfoCache, - cached_status: CacheTxHashStatus, - tx_hash: T, -) { - let hash: [u8; 32] = tx_hash.into(); - match cached_status { - CacheTxHashStatus::Connection(conn_id) => { - ibc_cache.conn_tx_hash.insert(conn_id, hash.into()); - } - CacheTxHashStatus::Channel(chan_id, port_id) => { - ibc_cache - .chan_tx_hash - .insert((chan_id, port_id), hash.into()); - } - CacheTxHashStatus::Packet(chan_id, port_id, sequence) => { - ibc_cache - .packet_tx_hash - .insert((chan_id, port_id, sequence), hash.into()); - } - } -} - -pub(crate) fn cache_ics_tx_hash_with_event>( - ibc_cache: &mut IBCInfoCache, - event: IbcEvent, - tx_hash: T, -) { - let tx_hash_status = match event { - IbcEvent::OpenInitConnection(event) => Some(CacheTxHashStatus::new_with_conn( - event.0.connection_id.unwrap(), - )), - IbcEvent::OpenTryConnection(event) => Some(CacheTxHashStatus::new_with_conn( - event.0.connection_id.unwrap(), - )), - IbcEvent::OpenAckConnection(event) => Some(CacheTxHashStatus::new_with_conn( - event.0.connection_id.unwrap(), - )), - IbcEvent::OpenConfirmConnection(event) => Some(CacheTxHashStatus::new_with_conn( - event.0.connection_id.unwrap(), - )), - IbcEvent::OpenInitChannel(event) => Some(CacheTxHashStatus::new_with_chan( - event.channel_id.unwrap(), - event.port_id, - )), - IbcEvent::OpenTryChannel(event) => Some(CacheTxHashStatus::new_with_chan( - event.channel_id.unwrap(), - event.port_id, - )), - IbcEvent::OpenAckChannel(event) => Some(CacheTxHashStatus::new_with_chan( - event.channel_id.unwrap(), - event.port_id, - )), - IbcEvent::OpenConfirmChannel(event) => Some(CacheTxHashStatus::new_with_chan( - event.channel_id.unwrap(), - event.port_id, - )), - IbcEvent::SendPacket(event) => Some(CacheTxHashStatus::new_with_packet( - event.packet.source_channel, - event.packet.source_port, - event.packet.sequence.into(), - )), - IbcEvent::ReceivePacket(event) => Some(CacheTxHashStatus::new_with_packet( - event.packet.destination_channel, - event.packet.destination_port, - event.packet.sequence.into(), - )), - _ => None, - }; - if let Some(tx_hash_status) = tx_hash_status { - cache_ics_tx_hash(ibc_cache, tx_hash_status, tx_hash); - } -} diff --git a/crates/relayer/src/chain/axon/monitor.rs b/crates/relayer/src/chain/axon/monitor.rs index a983b0c6f..20583e7f9 100644 --- a/crates/relayer/src/chain/axon/monitor.rs +++ b/crates/relayer/src/chain/axon/monitor.rs @@ -1,8 +1,7 @@ -use std::sync::{Arc, RwLock}; +use std::sync::Arc; use std::time::Duration; -use super::{contract::*, IBCInfoCache}; -use crate::chain::axon::cache_ics_tx_hash_with_event; +use super::contract::*; use crate::event::bus::EventBus; use crate::event::IbcEventWithHeight; use crossbeam_channel as channel; @@ -33,8 +32,6 @@ pub struct AxonEventMonitor { start_block_number: u64, rx_cmd: channel::Receiver, event_bus: EventBus>>, - ibc_cache: Arc>, - reprocess_events: Vec<(OwnableIBCHandlerEvents, LogMeta)>, } impl AxonEventMonitor { @@ -50,7 +47,6 @@ impl AxonEventMonitor { websocket_addr: WebSocketClientUrl, contract_address: Address, rt: Arc, - ibc_cache: Arc>, ) -> Result<(Self, TxMonitorCmd)> { let (tx_cmd, rx_cmd) = channel::unbounded(); @@ -73,8 +69,6 @@ impl AxonEventMonitor { start_block_number, rx_cmd, event_bus, - ibc_cache, - reprocess_events: vec![], }; Ok((monitor, TxMonitorCmd::new(tx_cmd))) } @@ -103,14 +97,9 @@ impl AxonEventMonitor { pub fn run(mut self) { if let Next::Continue = self.update_subscribe(false) { info!( - "start Axon event monitor for {}, reprocess {} events", + "start Axon event monitor for {}", self.chain_id, - self.reprocess_events.len() ); - (0..self.reprocess_events.len()).for_each(|_| { - let (event, meta) = self.reprocess_events.remove(0); - self.process_event(event, meta); - }); let mut contract = Contract::new(self.contract_address, Arc::clone(&self.client)); info!( "start to fetch IBC events from block {}", @@ -142,58 +131,6 @@ impl AxonEventMonitor { } } - pub fn restore_event_tx_hashes( - &mut self, - latest_block_count: u64, - ) -> Result> { - let contract = Arc::new(Contract::new( - self.contract_address, - Arc::clone(&self.client), - )); - let restore_block_number = self - .start_block_number - .checked_sub(latest_block_count) - .ok_or(Error::others(format!( - "latest_block_count {latest_block_count} exceeds start_block_number {}", - self.start_block_number - )))?; - let event_filter = |event: &OwnableIBCHandlerEvents| { - matches!( - event, - OwnableIBCHandlerEvents::SendPacketFilter(_) - | OwnableIBCHandlerEvents::WriteAcknowledgementFilter(_) - ) - }; - let events = self - .rt - .block_on( - contract - .events() - .from_block(restore_block_number) - .to_block(self.start_block_number) - .query_with_meta(), - ) - .map_err(|e| Error::others(e.to_string()))? - .into_iter() - .map(|(event, meta)| { - if event_filter(&event) { - self.reprocess_events.push((event.clone(), meta.clone())); - } - IbcEventWithHeight::new_with_tx_hash( - event.into(), - Height::from_noncosmos_height(meta.block_number.as_u64()), - meta.transaction_hash.into(), - ) - }) - .collect::>(); - debug!( - "restored {} events on contract {}", - events.len(), - self.contract_address - ); - Ok(events) - } - fn update_subscribe(&mut self, use_try: bool) -> Next { let cmd = if use_try { match self.rx_cmd.try_recv() { @@ -270,11 +207,6 @@ impl AxonEventMonitor { Height::from_noncosmos_height(meta.block_number.as_u64()), meta.transaction_hash.into(), ); - cache_ics_tx_hash_with_event( - &mut self.ibc_cache.write().unwrap(), - event.event.clone(), - event.tx_hash, - ); let batch = EventBatch { chain_id: self.chain_id.clone(), tracking_id: TrackingId::Static("Axon solidity event streaming"), diff --git a/crates/relayer/src/chain/axon/utils.rs b/crates/relayer/src/chain/axon/utils.rs index d7513be38..5d141404f 100644 --- a/crates/relayer/src/chain/axon/utils.rs +++ b/crates/relayer/src/chain/axon/utils.rs @@ -1,10 +1,6 @@ use std::str::FromStr; use axon_tools::types::{Block as AxonBlock, Proof as AxonProof, ValidatorExtend}; -use ckb_ics_axon::proof::{ - Log as CkbLog, ObjectProof, TransactionReceipt as CkbTransactionReceipt, -}; -use rlp::Encodable; use crate::{ chain::SEC_TO_NANO, @@ -14,7 +10,7 @@ use crate::{ event::IbcEventWithHeight, ibc_contract::OwnableIBCHandlerEvents, }; -use ethers::{types::TransactionReceipt, types::H256, utils::rlp}; +use ethers::types::H256; use ibc_relayer_types::{ clients::{ ics07_axon::{client_state::AxonClientState, consensus_state::AxonConsensusState}, @@ -107,59 +103,6 @@ pub fn to_any_consensus_state( Ok(any_consensus_state) } -// use ObjectProof in Ckb repo to garrantee the correctness of encode/decode of Axon proof -pub fn to_ckb_like_object_proof( - receipt: &TransactionReceipt, - receipt_proof: &[Vec], - block: &AxonBlock, - state_root: &H256, - block_proof: &AxonProof, -) -> ObjectProof { - let logs = receipt - .logs - .iter() - .map(|log| CkbLog { - address: log.address, - topics: log.topics.clone(), - data: log.data.to_vec().into(), - block_hash: log.block_hash, - block_number: log.block_number, - transaction_hash: log.transaction_hash, - transaction_index: log.transaction_index, - log_index: log.log_index, - transaction_log_index: log.transaction_log_index, - log_type: log.log_type.clone(), - removed: log.removed, - }) - .collect(); - let receipt = CkbTransactionReceipt { - transaction_hash: receipt.transaction_hash, - transaction_index: receipt.transaction_index, - block_hash: receipt.block_hash, - block_number: receipt.block_number, - from: receipt.from, - to: receipt.to, - cumulative_gas_used: receipt.cumulative_gas_used, - gas_used: receipt.gas_used, - contract_address: receipt.contract_address, - logs, - status: receipt.status, - root: receipt.root, - logs_bloom: receipt.logs_bloom, - transaction_type: receipt.transaction_type, - effective_gas_price: receipt.effective_gas_price, - }; - let block = block.rlp_bytes().to_vec(); - let axon_proof = block_proof.rlp_bytes().to_vec(); - ObjectProof { - receipt, - receipt_proof: receipt_proof.to_owned(), - block, - state_root: *state_root, - axon_proof, - } -} - pub fn ibc_event_from_ibc_handler_event( height: Height, tx_hash: [u8; 32], diff --git a/crates/relayer/src/chain/ckb4ibc.rs b/crates/relayer/src/chain/ckb4ibc.rs index 93f3375a8..ee414cf07 100644 --- a/crates/relayer/src/chain/ckb4ibc.rs +++ b/crates/relayer/src/chain/ckb4ibc.rs @@ -24,7 +24,7 @@ use crate::misbehaviour::MisbehaviourEvidence; use ckb_ics_axon::handler::{IbcChannel, IbcConnections, IbcPacket, PacketStatus}; use ckb_ics_axon::message::{Envelope, MsgType}; use ckb_ics_axon::object::Ordering; -use ckb_ics_axon::{ChannelArgs, PacketArgs}; +use ckb_ics_axon::{ChannelArgs, PacketArgs, ConnectionArgs}; use ckb_jsonrpc_types::{Status, TransactionView}; use ckb_sdk::constants::TYPE_ID_CODE_HASH; use ckb_sdk::traits::SecpCkbRawKeySigner; @@ -274,11 +274,12 @@ impl Ckb4IbcChain { is_open: bool, ) -> Result<(ChannelEnd, IbcChannel), Error> { let channel_code_hash = self.get_converter()?.get_channel_code_hash(); - let client_id = self + let args = self .config - .lc_client_type_hash(self.counterparty_client_type())?; + .lc_connection_args(self.counterparty_client_type())?; let channel_args = ChannelArgs { - client_id: client_id.into(), + metadata_type_id: args.metadata_type_id, + ibc_handler_address: args.ibc_handler_address, open: is_open, channel_id: get_channel_number(channel_id)?, port_id: convert_port_id_to_array(port_id)?, @@ -355,8 +356,11 @@ impl Ckb4IbcChain { .previous_output(cell.out_point.into()) .build(); let capacity: u64 = cell.output.capacity.into(); - let client_id = hex::encode(cell.output.lock.args.into_bytes()); - if let Ok(client_type) = self.config.lc_client_type(&client_id) { + let args = match ConnectionArgs::from_slice(cell.output.lock.args.as_bytes()) { + Ok(a) => a, + Err(_) => continue, + }; + if let Ok(client_type) = self.config.lc_client_type(&args.client_id()) { resps.push((tx, cell_input, capacity, client_type)); } } @@ -552,6 +556,7 @@ impl ChainEndpoint for Ckb4IbcChain { LightClientItem { chain_id, client_cell_type_args, + .. }, ) in &config.onchain_light_clients { @@ -881,7 +886,7 @@ impl ChainEndpoint for Ckb4IbcChain { .map(|client_type| { // TODO query latest_height from light client cell (for example Axon metadata cell) let client_id = self.config.lc_client_id(*client_type).unwrap(); - let chain_id = self.config.lc_chain_id(&client_id.to_string()).unwrap(); + let chain_id = self.config.lc_chain_id_by_client_id(&client_id.to_string()).unwrap(); IdentifiedAnyClientState { client_id, client_state: CkbClientState { @@ -899,7 +904,7 @@ impl ChainEndpoint for Ckb4IbcChain { request: QueryClientStateRequest, _include_proof: IncludeProof, ) -> Result<(AnyClientState, Option), Error> { - let chain_id = self.config.lc_chain_id(&request.client_id.to_string())?; + let chain_id = self.config.lc_chain_id_by_client_id(&request.client_id.to_string())?; // TODO query latest_height let client_state = CkbClientState { chain_id, diff --git a/crates/relayer/src/chain/ckb4ibc/extractor.rs b/crates/relayer/src/chain/ckb4ibc/extractor.rs index 7faed315c..d35d9e16c 100644 --- a/crates/relayer/src/chain/ckb4ibc/extractor.rs +++ b/crates/relayer/src/chain/ckb4ibc/extractor.rs @@ -8,6 +8,7 @@ use ckb_ics_axon::message::{Envelope, MsgType}; use ckb_ics_axon::object::{ ConnectionEnd as CkbConnectionEnd, Ordering as CkbOrdering, State as CkbState, }; +use ckb_ics_axon::{ConnectionArgs, connection_id, get_channel_id_str}; use ckb_jsonrpc_types::TransactionView; use ckb_types::packed::WitnessArgs; use ckb_types::prelude::Entity; @@ -24,9 +25,7 @@ use ibc_relayer_types::core::ics04_channel::channel::{ }; use ibc_relayer_types::core::ics04_channel::version::Version as ChanVersion; use ibc_relayer_types::core::ics23_commitment::commitment::CommitmentPrefix; -use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId}; - -use super::utils::{generate_channel_id, generate_connection_id}; +use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, ClientId, PortId}; pub fn extract_channel_end_from_tx( tx: TransactionView, @@ -43,29 +42,34 @@ pub fn extract_channel_end_from_tx( Ok((channel_end, ckb_channel_end)) } -pub fn extract_ibc_connections_from_tx(tx: TransactionView) -> Result { +pub fn extract_ibc_connections_from_tx( + tx: TransactionView, +) -> Result<(ConnectionArgs, IbcConnections), Error> { let idx = get_object_index(&tx, ObjectType::IbcConnections)?; let witness = tx.inner.witnesses.get(idx).unwrap(); let witness_args = WitnessArgs::from_slice(witness.as_bytes()).unwrap(); + let connection_args = + ConnectionArgs::from_slice(tx.inner.outputs[idx].lock.args.as_bytes()).unwrap(); let ibc_connection_cells = rlp::decode::(&witness_args.output_type().to_opt().unwrap().raw_data()) .map_err(|_| Error::extract_conn_tx_error(tx.hash.to_string()))?; - Ok(ibc_connection_cells) + Ok((connection_args, ibc_connection_cells)) } pub fn extract_connections_from_tx( tx: TransactionView, prefix: &CommitmentPrefix, ) -> Result<(Vec, IbcConnections), Error> { - let ibc_connection_cell = extract_ibc_connections_from_tx(tx)?; - let result = ibc_connection_cell + let (args, connections) = extract_ibc_connections_from_tx(tx)?; + let client_id = args.client_id(); + let result = connections .connections .iter() .enumerate() - .flat_map(|(idx, connection)| convert_connection_end(connection.clone(), idx, prefix)) + .flat_map(|(idx, connection)| convert_connection_end(&client_id, connection.clone(), idx, prefix)) .collect(); - Ok((result, ibc_connection_cell)) + Ok((result, connections)) } pub fn extract_ibc_packet_from_tx(tx: TransactionView) -> Result<(IbcPacket, Vec), Error> { @@ -110,11 +114,12 @@ fn navigate(t: &MsgType, object_type: &ObjectType) -> usize { } fn convert_connection_end( + client_id: &str, connection: CkbConnectionEnd, idx: usize, prefix: &CommitmentPrefix, ) -> Result { - let connection_id = generate_connection_id(idx as u16, &connection.client_id); + let connection_id = connection_id(client_id, idx).parse().unwrap(); let state = match connection.state { CkbState::Unknown => ConnectionState::Uninitialized, CkbState::Init => ConnectionState::Init, @@ -122,18 +127,17 @@ fn convert_connection_end( CkbState::Open => ConnectionState::Open, _ => ConnectionState::Uninitialized, }; - let client_id = { - let s = connection.client_id; - ClientId::from_str(&s).map_err(|_| Error::ckb_client_id_invalid(s)) - }?; + let client_id = + ClientId::from_str(client_id).map_err(|_| Error::ckb_client_id_invalid(client_id.to_string()))?; let remote_client_id = { let id = connection.counterparty.client_id; ClientId::from_str(&id).map_err(|_| Error::ckb_client_id_invalid(id)) }?; - let remote_connection_id = connection - .counterparty - .connection_id - .map(|c| ConnectionId::from_str(&c).unwrap()); + let remote_connection_id = if connection.counterparty.connection_id.is_empty() { + None + } else { + Some(connection.counterparty.connection_id.parse().unwrap()) + }; let delay_period = connection.delay_period; let result = IdentifiedConnectionEnd { connection_id, @@ -194,7 +198,7 @@ fn convert_channel_end(ckb_channel_end: CkbIbcChannel) -> Result Result; - - fn get_ibc_connections_by_port_id( - &self, - channel_id: &ChannelId, - ) -> Result; + ) -> Result<(ConnectionArgs, IbcConnections), Error>; fn get_ibc_connections_input(&self, client_id: &str) -> Result<(CellInput, u64), Error>; @@ -167,34 +160,23 @@ impl<'a> MsgToTxConverter for Converter<'a> { fn get_ibc_connections_by_connection_id( &self, connection_id: &ConnectionId, - ) -> Result { + ) -> Result<(ConnectionArgs, IbcConnections), Error> { let conneciton_cache = self.ckb_instance.connection_cache.borrow(); - let ibc_connections = conneciton_cache.iter().find(|(_, (v, _, _, _))| { - v.connections - .iter() - .enumerate() - .any(|(idx, c)| connection_id == &generate_connection_id(idx as u16, &c.client_id)) - }); - if let Some((_, (value, _, _, _))) = ibc_connections { - Ok(value.clone()) - } else { - Err(Error::query(format!( - "connection {connection_id} not found in cache" - ))) - } - } - - fn get_ibc_connections_by_port_id( - &self, - channel_id: &ChannelId, - ) -> Result { - let channel_cache = self.ckb_instance.channel_cache.borrow(); - let channel = channel_cache - .get(channel_id) - .ok_or_else(|| Error::query(format!("channel {channel_id} not found in cache")))?; - // FIXME: should modify ibc contract - let connection_id = channel.connection_hops[0].parse().unwrap(); - self.get_ibc_connections_by_connection_id(&connection_id) + conneciton_cache + .iter() + .find_map(|(k, (v, _, _, _))| { + let args = self.ckb_instance.config.lc_connection_args(*k).unwrap(); + let client_id = args.client_id(); + let found = v.connections.iter().enumerate().any(|(idx, _)| { + connection_id.as_str() == ckb_ics_axon::connection_id(client_id.as_str(), idx) + }); + if found { + Some((args, v.clone())) + } else { + None + } + }) + .ok_or_else(|| Error::query(format!("connection {connection_id} not found in cache"))) } fn get_ibc_connections_input(&self, client_id: &str) -> Result<(CellInput, u64), Error> { @@ -524,3 +506,10 @@ impl TxBuilder { self.builder.build() } } + +fn convert_proof_height(height: Height) -> ckb_ics_axon::proto::client::Height { + ckb_ics_axon::proto::client::Height { + revision_number: height.revision_number(), + revision_height: height.revision_height(), + } +} diff --git a/crates/relayer/src/chain/ckb4ibc/message/channel.rs b/crates/relayer/src/chain/ckb4ibc/message/channel.rs index b4ffa28d5..6c51adb46 100644 --- a/crates/relayer/src/chain/ckb4ibc/message/channel.rs +++ b/crates/relayer/src/chain/ckb4ibc/message/channel.rs @@ -6,7 +6,7 @@ use ckb_ics_axon::message::MsgChannelOpenInit as CkbMsgChannelOpenInit; use ckb_ics_axon::message::MsgChannelOpenTry as CkbMsgChannelOpenTry; use ckb_ics_axon::message::MsgType; use ckb_ics_axon::object::{ChannelCounterparty, Ordering as CkbOrdering, State as CkbState}; -use ckb_ics_axon::ChannelArgs; +use ckb_ics_axon::{get_channel_id_str, ChannelArgs}; use ckb_types::packed::BytesOpt; use ibc_relayer_types::core::ics04_channel::channel::{ChannelEnd, Order, State}; use ibc_relayer_types::core::ics04_channel::events::{OpenAck, OpenConfirm, OpenInit, OpenTry}; @@ -19,17 +19,17 @@ use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, PortId}; use ibc_relayer_types::events::IbcEvent; use std::str::FromStr; -use super::{CkbTxInfo, MsgToTxConverter, TxBuilder}; +use super::{CkbTxInfo, MsgToTxConverter, TxBuilder, convert_proof_height}; use crate::chain::ckb4ibc::utils::{ - convert_port_id_to_array, convert_proof, extract_client_id_by_connection_id, - generate_channel_id, get_channel_lock_script, get_channel_number, get_client_id_from_channel, - get_client_outpoint, get_connection_lock_script, get_encoded_object, + convert_port_id_to_array, get_channel_lock_script, get_channel_number, get_client_outpoint, + get_connection_lock_script, get_encoded_object, }; use crate::error::Error; fn convert_channel_end( channel_end: ChannelEnd, port_id: PortId, + remote_connection_id: String, channel_number: u16, ) -> Result { let state = match channel_end.state { @@ -67,6 +67,7 @@ fn convert_channel_end( let counterparty = ChannelCounterparty { port_id: remote_port_id, channel_id: remote_channel_id, + connection_id: remote_connection_id, }; let sequence = Sequence { @@ -84,6 +85,7 @@ fn convert_channel_end( sequence, counterparty, connection_hops, + version: channel_end.version.to_string(), }; Ok(result) } @@ -92,14 +94,28 @@ pub fn convert_chan_open_init_to_tx( msg: MsgChannelOpenInit, converter: &C, ) -> Result { - let old_connection_cell = - converter.get_ibc_connections_by_connection_id(&msg.channel.connection_hops[0])?; + let connection_id = &msg.channel.connection_hops[0]; + + let (connection_args, old_connection_cell) = + converter.get_ibc_connections_by_connection_id(connection_id)?; + let client_id = connection_args.client_id(); let next_channel_num = old_connection_cell.next_channel_number; let mut new_connection_cell = old_connection_cell.clone(); new_connection_cell.next_channel_number += 1; - let ibc_channel_end = - convert_channel_end(msg.channel.clone(), msg.port_id.clone(), next_channel_num)?; + let remote_connection_id = old_connection_cell + .get_by_id(&connection_args.client_id(), connection_id.as_str()) + .ok_or_else(|| Error::connection_not_found(connection_id.clone()))? + .counterparty + .connection_id + .clone(); + + let ibc_channel_end = convert_channel_end( + msg.channel.clone(), + msg.port_id.clone(), + remote_connection_id, + next_channel_num, + )?; let ibc_channel = get_encoded_object(&ibc_channel_end); let envelope = Envelope { @@ -107,9 +123,9 @@ pub fn convert_chan_open_init_to_tx( content: rlp::encode(&CkbMsgChannelOpenInit {}).to_vec(), }; - let (client_cell_type_args, client_id) = get_client_id_from_channel(&msg.channel, converter)?; let channel_args = ChannelArgs { - client_id: client_cell_type_args, + metadata_type_id: connection_args.metadata_type_id, + ibc_handler_address: connection_args.ibc_handler_address, open: false, channel_id: next_channel_num, port_id: convert_port_id_to_array(&msg.port_id)?, @@ -135,7 +151,7 @@ pub fn convert_chan_open_init_to_tx( let event = IbcEvent::OpenInitChannel(OpenInit { port_id: msg.port_id, - channel_id: Some(generate_channel_id(next_channel_num)), + channel_id: Some(get_channel_id_str(next_channel_num).parse().unwrap()), connection_id: msg.channel.connection_hops[0].clone(), counterparty_port_id: msg.channel.remote.port_id, counterparty_channel_id: msg.channel.remote.channel_id, @@ -153,30 +169,45 @@ pub fn convert_chan_open_try_to_tx( msg: MsgChannelOpenTry, converter: &C, ) -> Result { - let old_connection_cell = + let connection_id = &msg.channel.connection_hops[0]; + + let (connection_args, old_connection_cell) = converter.get_ibc_connections_by_connection_id(&msg.channel.connection_hops[0])?; + let client_id = connection_args.client_id(); let next_channel_num = old_connection_cell.next_channel_number; let mut new_connection_cell = old_connection_cell.clone(); new_connection_cell.next_channel_number += 1; - let ibc_channel_end = - convert_channel_end(msg.channel.clone(), msg.port_id.clone(), next_channel_num)?; + let remote_connection_id = old_connection_cell + .get_by_id(&connection_args.client_id(), connection_id.as_str()) + .ok_or_else(|| Error::connection_not_found(connection_id.clone()))? + .counterparty + .connection_id + .clone(); + + let ibc_channel_end = convert_channel_end( + msg.channel.clone(), + msg.port_id.clone(), + remote_connection_id, + next_channel_num, + )?; let ibc_channel = get_encoded_object(&ibc_channel_end); - let (client_cell_type_args, client_id) = get_client_id_from_channel(&msg.channel, converter)?; let old_connection = get_encoded_object(&old_connection_cell); let new_connection = get_encoded_object(&new_connection_cell); let envelope = Envelope { msg_type: MsgType::MsgChannelOpenTry, content: rlp::encode(&CkbMsgChannelOpenTry { - proof_chan_end_on_a: convert_proof(msg.proofs)?, + proof_height: convert_proof_height(msg.proofs.height()), + proof_init: msg.proofs.object_proof().clone().into(), }) .to_vec(), }; let channel_args = ChannelArgs { - client_id: client_cell_type_args, + metadata_type_id: connection_args.metadata_type_id, + ibc_handler_address: connection_args.ibc_handler_address, open: false, channel_id: next_channel_num, port_id: convert_port_id_to_array(&msg.port_id)?, @@ -198,7 +229,7 @@ pub fn convert_chan_open_try_to_tx( let event = IbcEvent::OpenTryChannel(OpenTry { port_id: msg.port_id, - channel_id: Some(generate_channel_id(next_channel_num)), + channel_id: Some(get_channel_id_str(next_channel_num).parse().unwrap()), connection_id: msg.channel.connection_hops[0].clone(), counterparty_port_id: msg.channel.remote.port_id, counterparty_channel_id: msg.channel.remote.channel_id, @@ -226,16 +257,18 @@ pub fn convert_chan_open_ack_to_tx( let envelope = Envelope { msg_type: MsgType::MsgChannelOpenAck, content: rlp::encode(&CkbMsgChannelOpenAck { - proofs: convert_proof(msg.proofs)?, + proof_height: convert_proof_height(msg.proofs.height()), + proof_try: msg.proofs.object_proof().clone().into(), }) .to_vec(), }; - let connection_id = old_channel.connection_hops[0].clone(); - let (client_cell_type_args, client_id) = - extract_client_id_by_connection_id(&connection_id, converter)?; + let connection_id = old_channel.connection_hops[0].parse().unwrap(); + let (connection_args, _) = converter.get_ibc_connections_by_connection_id(&connection_id)?; + let client_id = connection_args.client_id(); let channel_args = ChannelArgs { - client_id: client_cell_type_args, + metadata_type_id: connection_args.metadata_type_id, + ibc_handler_address: connection_args.ibc_handler_address, open: true, channel_id: channel_idx, port_id: convert_port_id_to_array(&msg.port_id)?, @@ -259,7 +292,7 @@ pub fn convert_chan_open_ack_to_tx( let event = IbcEvent::OpenAckChannel(OpenAck { port_id: msg.port_id, channel_id: Some(msg.channel_id), - connection_id: connection_id.parse().unwrap(), + connection_id, counterparty_port_id, counterparty_channel_id: Some(msg.counterparty_channel_id), }); @@ -288,16 +321,18 @@ pub fn convert_chan_open_confirm_to_tx( let envelope = Envelope { msg_type: MsgType::MsgChannelOpenConfirm, content: rlp::encode(&CkbMsgChannelOpenConfirm { - proofs: convert_proof(msg.proofs)?, + proof_height: convert_proof_height(msg.proofs.height()), + proof_ack: msg.proofs.object_proof().clone().into(), }) .to_vec(), }; - let connection_id = old_channel.connection_hops[0].clone(); - let (client_cell_type_args, client_id) = - extract_client_id_by_connection_id(&connection_id, converter)?; + let connection_id = old_channel.connection_hops[0].parse().unwrap(); + let (connection_args, _) = converter.get_ibc_connections_by_connection_id(&connection_id)?; + let client_id = connection_args.client_id(); let channel_args = ChannelArgs { - client_id: client_cell_type_args, + metadata_type_id: connection_args.metadata_type_id, + ibc_handler_address: connection_args.ibc_handler_address, open: true, channel_id: get_channel_number(&msg.channel_id)?, port_id: convert_port_id_to_array(&msg.port_id)?, @@ -320,7 +355,7 @@ pub fn convert_chan_open_confirm_to_tx( let event = IbcEvent::OpenConfirmChannel(OpenConfirm { port_id: msg.port_id, channel_id: Some(msg.channel_id), - connection_id: connection_id.parse().unwrap(), + connection_id, counterparty_port_id, counterparty_channel_id: Some(counterparty_channel_id), }); diff --git a/crates/relayer/src/chain/ckb4ibc/message/connection.rs b/crates/relayer/src/chain/ckb4ibc/message/connection.rs index dda743959..d4d52b2f4 100644 --- a/crates/relayer/src/chain/ckb4ibc/message/connection.rs +++ b/crates/relayer/src/chain/ckb4ibc/message/connection.rs @@ -1,11 +1,5 @@ -use crate::{ - chain::ckb4ibc::utils::{ - convert_proof, generate_connection_id, get_client_outpoint, get_connection_index_by_id, - get_connection_lock_script, get_encoded_object, - }, - error::Error, -}; use ckb_ics_axon::{ + connection_id, message::{ Envelope, MsgConnectionOpenAck as CkbMsgConnectionOpenAck, MsgConnectionOpenConfirm as CkbMsgConnectionOpenConfirm, @@ -25,7 +19,14 @@ use ibc_relayer_types::{ events::IbcEvent, }; -use super::{CkbTxInfo, MsgToTxConverter, TxBuilder}; +use super::{convert_proof_height, CkbTxInfo, MsgToTxConverter, TxBuilder}; +use crate::{ + chain::ckb4ibc::utils::{ + get_client_outpoint, get_connection_index_by_id, get_connection_lock_script, + get_encoded_object, + }, + error::Error, +}; pub fn convert_conn_open_init_to_tx( msg: MsgConnectionOpenInit, @@ -36,22 +37,20 @@ pub fn convert_conn_open_init_to_tx( let remote_client_id = msg.counterparty.client_id().to_string(); let counterparty = ConnectionCounterparty { client_id: remote_client_id, - connection_id: None, + connection_id: "".into(), commitment_prefix: converter.get_commitment_prefix(), }; let connection_end = CkbConnectionEnd { state: State::Init, - client_id: client_id.clone(), counterparty, delay_period: msg.delay_period.as_secs(), - versions: vec![Default::default()], + ..Default::default() }; let old_ibc_connection_cell = converter.get_ibc_connections(&client_id)?; - let this_conn_idx = old_ibc_connection_cell.next_connection_number; + let this_conn_idx = old_ibc_connection_cell.connections.len(); let mut new_ibc_connection_cell = old_ibc_connection_cell.clone(); new_ibc_connection_cell.connections.push(connection_end); - new_ibc_connection_cell.next_connection_number += 1; let envelope = Envelope { msg_type: MsgType::MsgConnectionOpenInit, @@ -73,7 +72,7 @@ pub fn convert_conn_open_init_to_tx( .build(); let event = IbcEvent::OpenInitConnection(OpenInit(Attributes { - connection_id: Some(generate_connection_id(this_conn_idx, &client_id)), + connection_id: Some(connection_id(&client_id, this_conn_idx).parse().unwrap()), client_id: msg.client_id, counterparty_connection_id: None, counterparty_client_id: msg.counterparty.client_id().clone(), @@ -98,27 +97,26 @@ pub fn convert_conn_open_try_to_tx( let counterparty = ConnectionCounterparty { client_id: remote_client_id, - connection_id: Some(remote_conn_id), + connection_id: remote_conn_id, commitment_prefix: converter.get_commitment_prefix(), }; let connection_end = CkbConnectionEnd { state: State::OpenTry, - client_id: client_id.clone(), counterparty, delay_period: msg.delay_period.as_secs(), - versions: vec![Default::default()], + ..Default::default() }; let old_ibc_connection_cell = converter.get_ibc_connections(&client_id)?; - let this_conn_idx = old_ibc_connection_cell.next_connection_number; + let this_conn_idx = old_ibc_connection_cell.connections.len(); let mut new_ibc_connection_cell = old_ibc_connection_cell.clone(); new_ibc_connection_cell.connections.push(connection_end); - new_ibc_connection_cell.next_connection_number += 1; let envelope = Envelope { msg_type: MsgType::MsgConnectionOpenTry, content: rlp::encode(&CkbMsgConnectionOpenTry { - proof: convert_proof(msg.proofs)?, + proof_height: convert_proof_height(msg.proofs.height()), + proof_init: msg.proofs.object_proof().clone().into(), }) .to_vec(), }; @@ -138,7 +136,7 @@ pub fn convert_conn_open_try_to_tx( .build(); let event = IbcEvent::OpenTryConnection(OpenTry(Attributes { - connection_id: Some(generate_connection_id(this_conn_idx, &client_id)), + connection_id: Some(connection_id(&client_id, this_conn_idx).parse().unwrap()), client_id: msg.client_id, counterparty_connection_id: msg.counterparty.connection_id.clone(), counterparty_client_id: msg.counterparty.client_id().clone(), @@ -156,26 +154,27 @@ pub fn convert_conn_open_ack_to_tx( msg: MsgConnectionOpenAck, converter: &C, ) -> Result { - let old_ibc_connection_cell = + let (connection_args, old_ibc_connection_cell) = converter.get_ibc_connections_by_connection_id(&msg.connection_id)?; let mut new_ibc_connection_cell = old_ibc_connection_cell.clone(); let idx = get_connection_index_by_id(&msg.connection_id)? as usize; let connection_end = new_ibc_connection_cell.connections.get_mut(idx).unwrap(); connection_end.state = State::Open; - connection_end.counterparty.connection_id = Some(msg.counterparty_connection_id.to_string()); + connection_end.counterparty.connection_id = msg.counterparty_connection_id.to_string(); let envelope = Envelope { msg_type: MsgType::MsgConnectionOpenAck, content: rlp::encode(&CkbMsgConnectionOpenAck { conn_id_on_a: idx, - proof_conn_end_on_b: convert_proof(msg.proofs)?, + proof_height: convert_proof_height(msg.proofs.height()), + proof_try: msg.proofs.object_proof().clone().into(), }) .to_vec(), }; let counterparty_client_id = connection_end.counterparty.client_id.clone(); - let client_id = connection_end.client_id.clone(); + let client_id = connection_args.client_id(); let old_connection = get_encoded_object(&old_ibc_connection_cell); let new_connection = get_encoded_object(&new_ibc_connection_cell); @@ -210,7 +209,7 @@ pub fn convert_conn_open_confirm_to_tx( msg: MsgConnectionOpenConfirm, converter: &C, ) -> Result { - let old_ibc_connection_cell = + let (connection_args, old_ibc_connection_cell) = converter.get_ibc_connections_by_connection_id(&msg.connection_id)?; let mut new_ibc_connection_cell = old_ibc_connection_cell.clone(); @@ -222,18 +221,15 @@ pub fn convert_conn_open_confirm_to_tx( msg_type: MsgType::MsgConnectionOpenConfirm, content: rlp::encode(&CkbMsgConnectionOpenConfirm { conn_id_on_b: idx, - proofs: convert_proof(msg.proofs)?, + proof_height: convert_proof_height(msg.proofs.height()), + proof_ack: msg.proofs.object_proof().clone().into(), }) .to_vec(), }; let counterparty_client_id = connection_end.counterparty.client_id.clone(); - let counterparty_connection_id = connection_end - .counterparty - .connection_id - .clone() - .map(|v| v.parse().unwrap()); - let client_id = connection_end.client_id.clone(); + let counterparty_connection_id = Some(connection_end.counterparty.connection_id.parse().unwrap()); + let client_id = connection_args.client_id(); let old_connection = get_encoded_object(&old_ibc_connection_cell); let new_connection = get_encoded_object(&new_ibc_connection_cell); diff --git a/crates/relayer/src/chain/ckb4ibc/message/packet.rs b/crates/relayer/src/chain/ckb4ibc/message/packet.rs index f51c84150..6f600cc60 100644 --- a/crates/relayer/src/chain/ckb4ibc/message/packet.rs +++ b/crates/relayer/src/chain/ckb4ibc/message/packet.rs @@ -14,11 +14,11 @@ use ibc_relayer_types::core::ics04_channel::msgs::recv_packet::MsgRecvPacket; use ibc_relayer_types::core::ics04_channel::packet::Packet; use ibc_relayer_types::events::IbcEvent; +use super::convert_proof_height; use super::{CkbTxInfo, MsgToTxConverter, TxBuilder}; use crate::chain::ckb4ibc::utils::{ - convert_port_id_to_array, convert_proof, extract_client_id_by_connection_id, - get_channel_lock_script, get_channel_number, get_client_outpoint, get_encoded_object, - get_packet_lock_script, + convert_port_id_to_array, get_channel_lock_script, get_channel_number, get_client_outpoint, + get_encoded_object, get_packet_lock_script, }; use crate::chain::SEC_TO_NANO; use crate::error::Error; @@ -73,7 +73,8 @@ pub fn convert_recv_packet_to_tx( } let recv_packet = CkbMsgRecvPacket { - proofs: convert_proof(msg.proofs)?, + proof_height: convert_proof_height(msg.proofs.height()), + proof_commitment: msg.proofs.object_proof().clone().into(), }; let envelope = Envelope { msg_type: MsgType::MsgRecvPacket, @@ -88,10 +89,13 @@ pub fn convert_recv_packet_to_tx( sequence: packet.sequence, }; - let (client_cell_type_args, client_id) = - extract_client_id_by_connection_id(&new_channel_end.connection_hops[0], converter)?; + let connection_id = new_channel_end.connection_hops[0].parse().unwrap(); + let connection_args = + converter.get_ibc_connections_by_connection_id(&connection_id)?.0; + let client_id = connection_args.client_id(); let channel_args = ChannelArgs { - client_id: client_cell_type_args, + metadata_type_id: connection_args.metadata_type_id, + ibc_handler_address: connection_args.ibc_handler_address, open: true, channel_id: channel_number, port_id, @@ -167,7 +171,8 @@ pub fn convert_ack_packet_to_tx( let new_channel = get_encoded_object(&new_channel_end); let ack_packet = CkbMsgAckPacket { - proofs: convert_proof(msg.proofs)?, + proof_height: convert_proof_height(msg.proofs.height()), + proof_acked: msg.proofs.object_proof().clone().into(), }; let envelope = Envelope { msg_type: MsgType::MsgAckPacket, @@ -200,10 +205,13 @@ pub fn convert_ack_packet_to_tx( converter.get_ibc_packet(&channel_id, &msg.packet.source_port, msg.packet.sequence)?; let old_packet = get_encoded_object(&old_ibc_packet); - let (client_cell_type_args, client_id) = - extract_client_id_by_connection_id(&new_channel_end.connection_hops[0], converter)?; + let connection_id = new_channel_end.connection_hops[0].parse().unwrap(); + let connection_args = + converter.get_ibc_connections_by_connection_id(&connection_id)?.0; + let client_id = connection_args.client_id(); let channel_args = ChannelArgs { - client_id: client_cell_type_args, + metadata_type_id: connection_args.metadata_type_id, + ibc_handler_address: connection_args.ibc_handler_address, open: true, channel_id: channel_number, port_id, diff --git a/crates/relayer/src/chain/ckb4ibc/monitor.rs b/crates/relayer/src/chain/ckb4ibc/monitor.rs index d9f21c19b..1b415bd7b 100644 --- a/crates/relayer/src/chain/ckb4ibc/monitor.rs +++ b/crates/relayer/src/chain/ckb4ibc/monitor.rs @@ -5,7 +5,7 @@ use std::time::Duration; use ckb_ics_axon::handler::{IbcPacket, PacketStatus}; use ckb_ics_axon::object::State as CkbState; -use ckb_ics_axon::ChannelArgs; +use ckb_ics_axon::{connection_id, ChannelArgs}; use ckb_jsonrpc_types::{JsonBytes, Status, TransactionView}; use ckb_sdk::rpc::ckb_indexer::SearchKey; use ckb_types::core::ScriptHashType; @@ -44,9 +44,7 @@ use crate::event::monitor::{Error, EventBatch, MonitorCmd, Next, Result, TxMonit use crate::event::IbcEventWithHeight; use super::cache_set::CacheSet; -use super::utils::{ - generate_connection_id, get_prefix_search_key, get_script_hash, tip_block_number, -}; +use super::utils::{get_prefix_search_key, get_script_hash, tip_block_number}; #[derive(Eq, PartialOrd, Ord, PartialEq, Hash, Clone, Copy)] pub enum IbcProtocolType { @@ -172,15 +170,15 @@ impl Ckb4IbcEventMonitor { async fn fetch_connection_events(&mut self) -> Result { let connection_code_hash = get_script_hash(&self.config.connection_type_args); - let client_type_hash = self + let connection_args = self .config - .lc_client_type_hash(self.counterparty_client_type) + .lc_connection_args(self.counterparty_client_type) .map_err(|e| Error::collect_events_failed(e.to_string()))?; - let client_id: ClientId = hex::encode(client_type_hash.0).parse().unwrap(); + let client_id = connection_args.client_id(); let script = Script::new_builder() .code_hash(connection_code_hash) .hash_type(ScriptHashType::Type.into()) - .args(client_type_hash.as_bytes().pack()) + .args(connection_args.encode().pack()) .build(); let key = get_prefix_search_key(script); let connections = self @@ -204,7 +202,7 @@ impl Ckb4IbcEventMonitor { events: vec![], }); } - let ((ibc_connection_cell, tx_hash), (block_number, _, _)) = + let (((_, connections), tx_hash), (block_number, _, _)) = connections.into_iter().next().unwrap(); if self.cache_set.read().unwrap().has(&tx_hash) { return Ok(EventBatch { @@ -215,21 +213,23 @@ impl Ckb4IbcEventMonitor { }); } self.cache_set.write().unwrap().insert(tx_hash.clone()); - let events = ibc_connection_cell + let events = connections .connections .into_iter() .enumerate() .flat_map(|(idx, connection_end)| match connection_end.state { CkbState::Init => { - let connection_id = generate_connection_id(idx as u16, client_id.as_str()); + let connection_id = connection_id(client_id.as_str(), idx).parse().unwrap(); info!( "🫡 {} received ConnectionOpenInit event, connection_id = {connection_id}", self.config.id ); let attrs = Attributes { connection_id: Some(connection_id), - client_id: client_id.clone(), - counterparty_connection_id: None, + client_id: client_id.parse().unwrap(), + counterparty_connection_id: Some( + connection_end.counterparty.connection_id.parse().unwrap(), + ), counterparty_client_id: ClientId::from_str( &connection_end.counterparty.client_id, ) @@ -243,14 +243,14 @@ impl Ckb4IbcEventMonitor { }) } CkbState::OpenTry => { - let connection_id = generate_connection_id(idx as u16, client_id.as_str()); + let connection_id = connection_id(client_id.as_str(), idx).parse().unwrap(); info!( "🫡 {} received ConnectionOpenTry event, connection_id = {connection_id}", self.config.id ); let attrs = Attributes { connection_id: Some(connection_id), - client_id: client_id.clone(), + client_id: client_id.parse().unwrap(), counterparty_connection_id: None, counterparty_client_id: ClientId::from_str( &connection_end.counterparty.client_id, @@ -280,12 +280,13 @@ impl Ckb4IbcEventMonitor { } async fn fetch_channel_events(&mut self) -> Result { - let client_id = self + let args = self .config - .lc_client_type_hash(self.counterparty_client_type) + .lc_connection_args(self.counterparty_client_type) .map_err(|e| Error::collect_events_failed(e.to_string()))?; let channel_args = ChannelArgs { - client_id: client_id.into(), + metadata_type_id: args.metadata_type_id, + ibc_handler_address: args.ibc_handler_address, open: false, ..Default::default() }; diff --git a/crates/relayer/src/chain/ckb4ibc/utils.rs b/crates/relayer/src/chain/ckb4ibc/utils.rs index 873c6c764..c1d229562 100644 --- a/crates/relayer/src/chain/ckb4ibc/utils.rs +++ b/crates/relayer/src/chain/ckb4ibc/utils.rs @@ -6,10 +6,8 @@ use crate::chain::SEC_TO_NANO; use crate::config::ckb4ibc::ChainConfig; use crate::error::Error; use crate::event::IbcEventWithHeight; -use ckb_ics_axon::consts::{CHANNEL_ID_PREFIX, CONNECTION_ID_PREFIX}; +use ckb_ics_axon::consts::CHANNEL_ID_PREFIX; use ckb_ics_axon::handler::IbcPacket; -use ckb_ics_axon::object::Proofs as CkbProofs; -use ckb_ics_axon::proof::ObjectProof; use ckb_jsonrpc_types::TransactionView; use ckb_sdk::constants::TYPE_ID_CODE_HASH; use ckb_sdk::rpc::ckb_indexer::ScriptSearchMode; @@ -21,7 +19,6 @@ use ckb_types::packed::{Byte32, Bytes, BytesOpt, OutPoint, Script}; use ckb_types::prelude::{Builder, Entity, Pack}; use ckb_types::{h256, H256}; use ibc_relayer_types::core::ics02_client::client_type::ClientType; -use ibc_relayer_types::core::ics04_channel::channel::ChannelEnd; use ibc_relayer_types::core::ics04_channel::events::{SendPacket, WriteAcknowledgement}; use ibc_relayer_types::core::ics04_channel::packet::{Packet, Sequence}; use ibc_relayer_types::core::ics04_channel::timeout::TimeoutHeight; @@ -62,17 +59,6 @@ pub fn get_encoded_object(obj: &T) -> EncodedObject { } } -pub fn convert_proof(ckb_proofs: Proofs) -> Result { - let object_proof_data: Vec = ckb_proofs.object_proof().clone().into(); - let object_proof = rlp::decode::(&object_proof_data) - .map_err(|_| Error::other_error(String::from("convert object proof error")))?; - Ok(CkbProofs { - height: ckb_proofs.height().revision_number().to_le_bytes().to_vec(), - object_proof, - client_proof: vec![], - }) -} - pub fn convert_port_id_to_array(port_id: &PortId) -> Result<[u8; 32], Error> { let port_id = H256::from_str(port_id.as_str()) .map_err(|_| Error::ckb_port_id_invalid(port_id.as_str().to_string()))?; @@ -98,19 +84,6 @@ pub fn get_channel_number(id: &ChannelId) -> Result { .map_err(|_| Error::ckb_chan_id_invalid(s.to_string())) } -pub fn get_connection_id_prefix(client_id: &str) -> String { - // to keep connection_id unique in global - format!("{}-{CONNECTION_ID_PREFIX}", &client_id[..6]) -} - -pub fn generate_connection_id(idx: u16, client_id: &str) -> ConnectionId { - ConnectionId::from_str(&format!("{}{idx}", get_connection_id_prefix(client_id))).unwrap() -} - -pub fn generate_channel_id(idx: u16) -> ChannelId { - ChannelId::from_str(&format!("{CHANNEL_ID_PREFIX}{idx}")).unwrap() -} - pub fn get_connection_index_by_id(id: &ConnectionId) -> Result { let s = id.as_str(); let result = s @@ -151,15 +124,14 @@ pub fn get_connection_lock_script( client_id: Option, ) -> Result { // fetch specific (concrete client cell) or all (prefix search) - let mut client_cell_type_args = vec![]; + let mut connection_lock_args = vec![]; if let Some(client_id) = client_id { - let client_type = config.lc_client_type(&client_id)?; - client_cell_type_args - .append(&mut config.lc_client_type_hash(client_type)?.as_bytes().to_vec()); + let args = config.lc_connection_args_by_id(&client_id)?; + connection_lock_args = args.encode(); } let script = Script::new_builder() .code_hash(get_script_hash(&config.connection_type_args)) - .args(client_cell_type_args.pack()) + .args(connection_lock_args.pack()) .hash_type(ScriptHashType::Type.into()) .build(); Ok(script) @@ -222,7 +194,7 @@ pub fn get_search_key_with_sudt( } pub fn get_dummy_merkle_proof(height: Height) -> Proofs { - let encoded = rlp::encode(&ObjectProof::default()).to_vec(); + let encoded = vec![0]; let useless_client_proof = vec![0u8].try_into().unwrap(); let useless_consensus_proof = ConsensusProof::new(vec![0u8].try_into().unwrap(), Height::default()).unwrap(); @@ -245,36 +217,6 @@ pub fn get_client_outpoint( .ok_or(Error::other_error(format!("not found {client_id}"))) } -pub fn get_client_id_from_channel( - channel: &ChannelEnd, - converter: &impl MsgToTxConverter, -) -> Result<([u8; 32], String), Error> { - let connection_id = channel.connection_hops[0].clone(); - extract_client_id_by_connection_id(&connection_id.to_string(), converter) -} - -pub fn extract_client_id_by_connection_id( - connection_id: &String, - converter: &impl MsgToTxConverter, -) -> Result<([u8; 32], String), Error> { - let connection_id = connection_id - .parse() - .map_err(|_| Error::other_error(format!("bad connection_id {connection_id}")))?; - let idx = get_connection_index_by_id(&connection_id) - .map_err(|_| Error::other_error(format!("bad connection_id {connection_id}")))?; - let ibc_conn = converter.get_ibc_connections_by_connection_id(&connection_id)?; - let connection_end = ibc_conn - .connections - .get(idx as usize) - .ok_or(Error::other_error(format!("exceed connection index {idx}")))?; - let client_id = connection_end.client_id.clone(); - let client_cell_type_args = hex::decode(&client_id) - .map_err(|_| Error::other_error(format!("client_id {client_id} hex decodeable")))? - .try_into() - .map_err(|_| Error::other_error(format!("client_id {client_id} size = 32")))?; - Ok((client_cell_type_args, client_id)) -} - pub fn generate_ibc_packet_event( packet: IbcPacket, height: u64, diff --git a/crates/relayer/src/chain/handle.rs b/crates/relayer/src/chain/handle.rs index b29b877aa..0f2179508 100644 --- a/crates/relayer/src/chain/handle.rs +++ b/crates/relayer/src/chain/handle.rs @@ -97,27 +97,6 @@ pub fn reply_channel() -> (ReplyTo, Reply) { crossbeam_channel::bounded(1) } -#[derive(Debug, Clone)] -pub enum CacheTxHashStatus { - Connection(ConnectionId), - Channel(ChannelId, PortId), - Packet(ChannelId, PortId, u64), -} - -impl CacheTxHashStatus { - pub fn new_with_conn(conn_id: ConnectionId) -> Self { - Self::Connection(conn_id) - } - - pub fn new_with_chan(chan_id: ChannelId, port_id: PortId) -> Self { - Self::Channel(chan_id, port_id) - } - - pub fn new_with_packet(chan_id: ChannelId, port_id: PortId, sequence: u64) -> Self { - Self::Packet(chan_id, port_id, sequence) - } -} - /// Requests that a `ChainHandle` may send to a `ChainRuntime`. #[derive(Clone, Debug)] #[allow(clippy::large_enum_variant)] diff --git a/crates/relayer/src/config/ckb4ibc.rs b/crates/relayer/src/config/ckb4ibc.rs index 45850751a..fd53cf41c 100644 --- a/crates/relayer/src/config/ckb4ibc.rs +++ b/crates/relayer/src/config/ckb4ibc.rs @@ -1,8 +1,9 @@ +use ckb_ics_axon::ConnectionArgs; use ckb_types::{ core::ScriptHashType, packed::Script, prelude::{Builder, Entity, Pack, Unpack}, - H256, + H160, H256, }; use ibc_relayer_types::core::{ ics02_client::client_type::ClientType, @@ -21,6 +22,7 @@ use super::filter::PacketFilter; pub struct LightClientItem { pub chain_id: ChainId, pub client_cell_type_args: H256, + pub ibc_handler_address: H160, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -44,14 +46,19 @@ pub struct ChainConfig { } impl ChainConfig { - pub fn lc_chain_id(&self, client_id: &String) -> Result { + pub fn lc_chain_id_by_client_id(&self, client_id: &str) -> Result { let chain_id = self .onchain_light_clients .iter() .find_map(|(_, v)| { - let client_type_hash = + let metadata_type_hash = calc_type_hash(&self.client_code_hash, &v.client_cell_type_args); - if hex::encode(client_type_hash) == client_id.as_str() { + let v_client_id = ConnectionArgs { + metadata_type_id: metadata_type_hash.0, + ibc_handler_address: v.ibc_handler_address.0, + } + .client_id(); + if client_id == v_client_id { Some(v.chain_id.clone()) } else { None @@ -68,9 +75,14 @@ impl ChainConfig { .onchain_light_clients .iter() .find_map(|(k, v)| { - let client_type_hash = + let metadata_type_hash = calc_type_hash(&self.client_code_hash, &v.client_cell_type_args); - if hex::encode(client_type_hash) == client_id { + let v_client_id = ConnectionArgs { + metadata_type_id: metadata_type_hash.0, + ibc_handler_address: v.ibc_handler_address.0, + } + .client_id(); + if client_id == v_client_id { Some(*k) } else { None @@ -82,28 +94,62 @@ impl ChainConfig { Ok(client_type) } - pub fn lc_client_id(&self, client_type: ClientType) -> Result { - let client_type_args = self.lc_client_type_args(client_type)?; - let client_type_hash = calc_type_hash(&self.client_code_hash, &client_type_args); - let client_id = hex::encode(client_type_hash).parse().unwrap(); - Ok(client_id) - } - - pub fn lc_client_type_args(&self, client_type: ClientType) -> Result { - let (_, item) = self + pub fn lc_connection_args_by_id(&self, client_id: &str) -> Result { + Ok(self .onchain_light_clients .iter() - .find(|(v, _)| **v == client_type) + .find_map(|(_, v)| { + let metadata_type_hash = + calc_type_hash(&self.client_code_hash, &v.client_cell_type_args); + let args = ConnectionArgs { + metadata_type_id: metadata_type_hash.0, + ibc_handler_address: v.ibc_handler_address.0, + }; + if client_id == args.client_id() { + Some(args) + } else { + None + } + }) .ok_or(Error::other_error(format!( - "config.toml missing client_type {client_type}" - )))?; - Ok(item.client_cell_type_args.clone()) + "config.toml missing client_id {client_id}" + )))?) } - pub fn lc_client_type_hash(&self, client_type: ClientType) -> Result { - let client_type_args = self.lc_client_type_args(client_type)?; - let client_type_hash = calc_type_hash(&self.client_code_hash, &client_type_args); - Ok(client_type_hash) + pub fn lc_client_id(&self, client_type: ClientType) -> Result { + let lc_item = self + .onchain_light_clients + .get(&client_type) + .ok_or_else(|| { + Error::other_error(format!("config.toml missing client_type {client_type}")) + })?; + let args = ConnectionArgs { + metadata_type_id: calc_type_hash( + &self.client_code_hash, + &lc_item.client_cell_type_args, + ) + .0, + ibc_handler_address: lc_item.ibc_handler_address.0, + }; + Ok(args.client_id().parse().unwrap()) + } + + pub fn lc_connection_args(&self, client_type: ClientType) -> Result { + let lc_item = self + .onchain_light_clients + .get(&client_type) + .ok_or_else(|| { + Error::other_error(format!("config.toml missing client_type {client_type}")) + })?; + let args = ConnectionArgs { + metadata_type_id: calc_type_hash( + &self.client_code_hash, + &lc_item.client_cell_type_args, + ) + .0, + ibc_handler_address: lc_item.ibc_handler_address.0, + }; + Ok(args) } } diff --git a/tools/ibc-test/Cargo.toml b/tools/ibc-test/Cargo.toml index 92cccb2b5..aa5d2280a 100644 --- a/tools/ibc-test/Cargo.toml +++ b/tools/ibc-test/Cargo.toml @@ -28,7 +28,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 = "bfd8ab46a1f1fc" } +ckb-ics-axon = { git = "https://github.com/synapseweb3/ckb-ics.git", rev = "45cdaa470cb" } rlp = "0.5.2" secp256k1 = "0.24" ckb-hash = "0.106"