Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add channel close feature #382

Merged
merged 9 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/relayer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,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 = "0299a91" }
cstr_core = "0.2.6"
rlp = "0.5.2"

Expand Down
93 changes: 74 additions & 19 deletions crates/relayer/src/chain/ckb4ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ use ibc_relayer_types::Height;
use rlp::Encodable;
use semver::Version;
use std::sync::RwLock;
use tendermint::Hash as TxHash;
use tendermint_rpc::endpoint::broadcast::tx_sync::Response;
use tokio::runtime::Runtime;
use tokio::sync::watch::Sender as WatchSender;
Expand All @@ -77,7 +78,7 @@ use self::monitor::{Ckb4IbcEventMonitor, WriteAckMonitorCmd};
use self::utils::{
convert_port_id_to_array, fetch_transaction_by_hash, generate_ibc_packet_event,
get_channel_number, get_dummy_merkle_proof, get_encoded_object, get_prefix_search_key,
get_search_key_with_sudt,
get_search_key_with_sudt, transaction_to_event,
};

use super::ckb::rpc_client::RpcClient;
Expand All @@ -88,15 +89,15 @@ use super::endpoint::{ChainStatus, HealthCheck};
use super::handle::Subscription;
use super::requests::{
CrossChainQueryRequest, IncludeProof, QueryChannelClientStateRequest, QueryChannelRequest,
QueryChannelsRequest, QueryClientConnectionsRequest, QueryClientStateRequest,
QueryClientStatesRequest, QueryConnectionChannelsRequest, QueryConnectionRequest,
QueryConnectionsRequest, QueryConsensusStateHeightsRequest, QueryConsensusStateRequest,
QueryHeight, QueryHostConsensusStateRequest, QueryNextSequenceReceiveRequest,
QueryPacketAcknowledgementRequest, QueryPacketAcknowledgementsRequest,
QueryPacketCommitmentRequest, QueryPacketCommitmentsRequest, QueryPacketEventDataRequest,
QueryPacketReceiptRequest, QueryTxRequest, QueryUnreceivedAcksRequest,
QueryUnreceivedPacketsRequest, QueryUpgradedClientStateRequest,
QueryUpgradedConsensusStateRequest,
QueryChannelsRequest, QueryClientConnectionsRequest, QueryClientEventRequest,
QueryClientStateRequest, QueryClientStatesRequest, QueryConnectionChannelsRequest,
QueryConnectionRequest, QueryConnectionsRequest, QueryConsensusStateHeightsRequest,
QueryConsensusStateRequest, QueryHeight, QueryHostConsensusStateRequest,
QueryNextSequenceReceiveRequest, QueryPacketAcknowledgementRequest,
QueryPacketAcknowledgementsRequest, QueryPacketCommitmentRequest,
QueryPacketCommitmentsRequest, QueryPacketEventDataRequest, QueryPacketReceiptRequest,
QueryTxHash, QueryTxRequest, QueryUnreceivedAcksRequest, QueryUnreceivedPacketsRequest,
QueryUpgradedClientStateRequest, QueryUpgradedConsensusStateRequest,
};
use super::tracking::TrackedMsgs;
use tokio::runtime::Runtime as TokioRuntime;
Expand Down Expand Up @@ -234,7 +235,7 @@ impl Ckb4IbcChain {
let tx = self
.rt
.block_on(fetch_transaction_by_hash(self.rpc_client.as_ref(), tx_hash))?;
let (packet, _) = extract_ibc_packet_from_tx(tx)?;
let (packet, _) = extract_ibc_packet_from_tx(&tx)?;
let cell_input = CellInput::new_builder()
.previous_output(cell.out_point.into())
.build();
Expand Down Expand Up @@ -312,7 +313,7 @@ impl Ckb4IbcChain {
serde_json::from_slice(json_bytes.as_bytes()).unwrap()
}
};
let channel_end = extract_channel_end_from_tx(tx)?;
let channel_end = extract_channel_end_from_tx(&tx)?;
let input = CellInput::new_builder()
.previous_output(cell.out_point.clone().into())
.build();
Expand Down Expand Up @@ -375,7 +376,7 @@ impl Ckb4IbcChain {
serde_json::from_slice::<TransactionView>(bytes.as_bytes()).unwrap()
}
};
let (connections, ibc_connection) = extract_connections_from_tx(tx, &prefix)?;
let (connections, ibc_connection) = extract_connections_from_tx(&tx, &prefix)?;
cache.insert(
client_type,
(ibc_connection, cell_input, capacity, connections),
Expand Down Expand Up @@ -848,9 +849,10 @@ impl ChainEndpoint for Ckb4IbcChain {
Ok(vec![ckb_balance])
}

// TODO Need to align with CKB ibc contract
// TODO: Ckb4Ibc's denom is hash of `sudt_type_script`, we cannot recover it to type_script,
// so it's hard to watch denom trace
fn query_denom_trace(&self, _hash: String) -> Result<DenomTrace, Error> {
warn!("axon query_denom_trace() cannot implement");
warn!("ckb4ibc query_denom_trace() cannot implement");
Ok(DenomTrace {
path: "".to_owned(),
base_denom: "".to_owned(),
Expand Down Expand Up @@ -1046,7 +1048,7 @@ impl ChainEndpoint for Ckb4IbcChain {
serde_json::from_slice::<TransactionView>(bytes.as_bytes()).unwrap()
}
};
extract_channel_end_from_tx(tx)
extract_channel_end_from_tx(&tx)
})
.map(|(channel, _)| channel)
.collect();
Expand Down Expand Up @@ -1273,9 +1275,62 @@ impl ChainEndpoint for Ckb4IbcChain {
Ok((sequence, None))
}

fn query_txs(&self, _request: QueryTxRequest) -> Result<Vec<IbcEventWithHeight>, Error> {
warn!("ckb4ibc query_txs() not support");
Ok(vec![])
fn query_txs(&self, request: QueryTxRequest) -> Result<Vec<IbcEventWithHeight>, Error> {
let prefix = self.query_commitment_prefix()?;
let events = match request {
QueryTxRequest::Client(QueryClientEventRequest {
query_height: _,
event_id: _,
client_id: _,
consensus_height,
}) => {
let block = self.rt.block_on(
self.rpc_client
.get_block_by_number(consensus_height.revision_height().into()),
)?;
let block_number: u64 = block.header.inner.number.into();
block
.transactions
.into_iter()
.flat_map(|tx| -> Result<_, Error> {
let event = transaction_to_event(&tx, &prefix)?;
ashuralyk marked this conversation as resolved.
Show resolved Hide resolved
Ok(IbcEventWithHeight {
event,
height: Height::from_noncosmos_height(block_number),
tx_hash: tx.hash.into(),
})
})
.collect::<Vec<_>>()
}
QueryTxRequest::Transaction(QueryTxHash(TxHash::Sha256(hash))) => {
let tx = self
.rt
.block_on(self.rpc_client.get_transaction(&hash.into()))?
.expect("query_txs");
let Some(block_hash) = tx.tx_status.block_hash else {
return Ok(vec![]);
};
let block = self.rt.block_on(self.rpc_client.get_block(&block_hash))?;
let block_number: u64 = block.header.inner.number.into();
let Some(tx) = tx.transaction else {
return Ok(vec![]);
};
let tx = match tx.inner {
ckb_jsonrpc_types::Either::Left(tx) => tx,
ckb_jsonrpc_types::Either::Right(json_bytes) => {
serde_json::from_slice(json_bytes.as_bytes()).unwrap()
}
};
let event = transaction_to_event(&tx, &prefix)?;
vec![IbcEventWithHeight {
event,
height: Height::from_noncosmos_height(block_number),
tx_hash: tx.hash.into(),
}]
}
_ => vec![],
};
Ok(events)
}

fn query_packet_events(
Expand Down
51 changes: 42 additions & 9 deletions crates/relayer/src/chain/ckb4ibc/extractor.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
use std::str::FromStr;
use std::time::Duration;

use crate::chain::SEC_TO_NANO;
use crate::error::Error;

use ckb_ics_axon::handler::{IbcChannel as CkbIbcChannel, IbcConnections, IbcPacket};
use ckb_ics_axon::message::{Envelope, MsgType};
use ckb_ics_axon::object::{
ConnectionEnd as CkbConnectionEnd, Ordering as CkbOrdering, State as CkbState,
ConnectionEnd as CkbConnectionEnd, Ordering as CkbOrdering, Packet as CkbPacket,
State as CkbState,
};
use ckb_jsonrpc_types::TransactionView;
use ckb_types::packed::WitnessArgs;
use ckb_types::prelude::Entity;
use ibc_relayer_types::core::ics02_client::height::Height;
use ibc_relayer_types::core::ics03_connection::connection::{
ConnectionEnd, IdentifiedConnectionEnd,
};
Expand All @@ -22,16 +25,19 @@ use ibc_relayer_types::core::ics04_channel::channel::{
ChannelEnd, Counterparty as ChannelCounterparty, IdentifiedChannelEnd, Order,
State as ChannelState,
};
use ibc_relayer_types::core::ics04_channel::packet::Packet;
use ibc_relayer_types::core::ics04_channel::timeout::TimeoutHeight;
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 ibc_relayer_types::timestamp::Timestamp;

use super::utils::{generate_channel_id, generate_connection_id};

pub fn extract_channel_end_from_tx(
tx: TransactionView,
tx: &TransactionView,
) -> Result<(IdentifiedChannelEnd, CkbIbcChannel), Error> {
let idx = get_object_index(&tx, ObjectType::ChannelEnd)?;
let idx = get_object_index(tx, ObjectType::ChannelEnd)?;
let witness = tx.inner.witnesses.get(idx).unwrap();
let witness_args = WitnessArgs::from_slice(witness.as_bytes())
.map_err(|_| Error::ckb_decode_witness_args())?;
Expand All @@ -43,8 +49,8 @@ pub fn extract_channel_end_from_tx(
Ok((channel_end, ckb_channel_end))
}

pub fn extract_ibc_connections_from_tx(tx: TransactionView) -> Result<IbcConnections, Error> {
let idx = get_object_index(&tx, ObjectType::IbcConnections)?;
pub fn extract_ibc_connections_from_tx(tx: &TransactionView) -> Result<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 ibc_connection_cells =
Expand All @@ -55,7 +61,7 @@ pub fn extract_ibc_connections_from_tx(tx: TransactionView) -> Result<IbcConnect
}

pub fn extract_connections_from_tx(
tx: TransactionView,
tx: &TransactionView,
prefix: &CommitmentPrefix,
) -> Result<(Vec<IdentifiedConnectionEnd>, IbcConnections), Error> {
let ibc_connection_cell = extract_ibc_connections_from_tx(tx)?;
Expand All @@ -68,8 +74,8 @@ pub fn extract_connections_from_tx(
Ok((result, ibc_connection_cell))
}

pub fn extract_ibc_packet_from_tx(tx: TransactionView) -> Result<(IbcPacket, Vec<u8>), Error> {
let envelope = get_envelope(&tx)?;
pub fn extract_ibc_packet_from_tx(tx: &TransactionView) -> Result<(IbcPacket, Vec<u8>), Error> {
let envelope = get_envelope(tx)?;
let idx = navigate(&envelope.msg_type, &ObjectType::IbcPacket);
let witness = tx.inner.witnesses.get(idx).unwrap();
let witness_args = WitnessArgs::from_slice(witness.as_bytes())
Expand All @@ -80,6 +86,11 @@ pub fn extract_ibc_packet_from_tx(tx: TransactionView) -> Result<(IbcPacket, Vec
Ok((ibc_packet, envelope.content))
}

pub fn extract_packet_from_tx(tx: &TransactionView) -> Result<(Packet, Option<Vec<u8>>), Error> {
let (packet, _) = extract_ibc_packet_from_tx(tx)?;
Ok((convert_packet(packet.packet)?, packet.ack))
}

fn navigate(t: &MsgType, object_type: &ObjectType) -> usize {
match (t, object_type) {
(MsgType::MsgClientCreate, ObjectType::IbcConnections) => 0,
Expand Down Expand Up @@ -204,6 +215,28 @@ fn convert_channel_end(ckb_channel_end: CkbIbcChannel) -> Result<IdentifiedChann
Ok(result)
}

fn convert_packet(packet: CkbPacket) -> Result<Packet, Error> {
fn other_error<E: ToString>(error: E) -> Error {
Error::other_error(error.to_string())
}
Ok(Packet {
sequence: (packet.sequence as u64).try_into().map_err(other_error)?,
source_port: PortId::from_str(&packet.source_port_id).map_err(other_error)?,
source_channel: ChannelId::from_str(&packet.source_channel_id).map_err(other_error)?,
destination_port: PortId::from_str(&packet.destination_port_id).map_err(other_error)?,
destination_channel: ChannelId::from_str(&packet.destination_channel_id)
.map_err(other_error)?,
timeout_height: if packet.timeout_height == 0 {
TimeoutHeight::Never
} else {
TimeoutHeight::At(Height::from_noncosmos_height(packet.timeout_height))
},
timeout_timestamp: Timestamp::from_nanoseconds(packet.timeout_timestamp * SEC_TO_NANO)
.map_err(other_error)?,
data: packet.data,
})
}

#[derive(Debug, Clone, Copy)]
enum ObjectType {
ChannelEnd,
Expand All @@ -216,7 +249,7 @@ fn get_object_index(tx: &TransactionView, object_type: ObjectType) -> Result<usi
Ok(navigate(&envelope.msg_type, &object_type))
}

fn get_envelope(tx: &TransactionView) -> Result<Envelope, Error> {
pub fn get_envelope(tx: &TransactionView) -> Result<Envelope, Error> {
let msg = tx.inner.witnesses.last().ok_or(Error::ckb_none_witness())?;

let bytes = msg.as_bytes();
Expand Down
Loading
Loading