Skip to content

Commit

Permalink
feat: fix a capacity bug and complete packet test
Browse files Browse the repository at this point in the history
  • Loading branch information
liyukun committed Aug 29, 2023
1 parent 94a8cc5 commit c005570
Show file tree
Hide file tree
Showing 20 changed files with 178 additions and 176 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

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

76 changes: 49 additions & 27 deletions crates/relayer/src/chain/ckb4ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,14 @@ pub struct Ckb4IbcChain {
counterparty_client_type: WatchSender<Option<ClientType>>,

client_outpoints: RefCell<HashMap<ClientType, OutPoint>>,
channel_input_data: RefCell<HashMap<(ChannelId, PortId), CellInput>>,
channel_input_data: RefCell<HashMap<(ChannelId, PortId), (CellInput, u64)>>,
channel_cache: RefCell<HashMap<ChannelId, IbcChannel>>,
#[allow(clippy::type_complexity)]
connection_cache:
RefCell<HashMap<ClientType, (IbcConnections, CellInput, Vec<IdentifiedConnectionEnd>)>>,
packet_input_data: RefCell<HashMap<(ChannelId, PortId, Sequence), CellInput>>,
connection_cache: RefCell<
HashMap<ClientType, (IbcConnections, CellInput, u64, Vec<IdentifiedConnectionEnd>)>,
>,
#[allow(clippy::type_complexity)]
packet_input_data: RefCell<HashMap<(ChannelId, PortId, Sequence), (CellInput, u64)>>,
packet_cache: RefCell<HashMap<(ChannelId, PortId, Sequence), IbcPacket>>,
}

Expand Down Expand Up @@ -250,7 +252,8 @@ impl Ckb4IbcChain {
let cell_input = CellInput::new_builder()
.previous_output(cell.out_point.into())
.build();
packets.push((ibc_packet, cell_input));
let capacity: u64 = cell.output.capacity.into();
packets.push((ibc_packet, cell_input, capacity));
}
Ok(packets)
});
Expand All @@ -259,14 +262,14 @@ impl Ckb4IbcChain {
.rt
.block_on(packets)?
.into_iter()
.map(|(packet, cell_input)| {
.map(|(packet, cell_input, capacity)| {
let channel_id: ChannelId = packet.packet.source_channel_id.parse().unwrap();
let port_id: PortId = packet.packet.source_port_id.parse().unwrap();
let sequence: Sequence = (packet.packet.sequence as u64).try_into().unwrap();

self.packet_input_data.borrow_mut().insert(
(channel_id.clone(), port_id.clone(), sequence),
cell_input.clone(),
(cell_input.clone(), capacity),
);
self.packet_cache
.borrow_mut()
Expand Down Expand Up @@ -326,28 +329,24 @@ impl Ckb4IbcChain {
let input = CellInput::new_builder()
.previous_output(cell.out_point.clone().into())
.build();
Ok((channel_end, input))
let capacity: u64 = cell.output.capacity.into();
Ok((channel_end, input, capacity))
});

let ((channel, ibc_channel_end), cell_input) = self.rt.block_on(channel_future)?;
let ((channel, ibc_channel_end), cell_input, capacity) =
self.rt.block_on(channel_future)?;

self.channel_input_data
.borrow_mut()
.insert((channel.channel_id.clone(), channel.port_id), cell_input);
self.channel_input_data.borrow_mut().insert(
(channel.channel_id.clone(), channel.port_id),
(cell_input, capacity),
);
self.channel_cache
.borrow_mut()
.insert(channel.channel_id, ibc_channel_end.clone());

Ok((channel.channel_end, ibc_channel_end))
}

fn clear_cache(&mut self) {
self.channel_input_data.get_mut().clear();
self.channel_cache.get_mut().clear();
self.packet_input_data.get_mut().clear();
self.connection_cache.get_mut().clear();
}

fn query_connection_and_cache(&self) -> Result<(), Error> {
let search_key = get_connection_search_key(&self.config, None)?;
let future = self
Expand All @@ -365,14 +364,15 @@ impl Ckb4IbcChain {
let cell_input = CellInput::new_builder()
.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());
resps.push((tx, cell_input, client_id));
resps.push((tx, cell_input, capacity, client_id));
}
Ok(resps)
});
let mut cache = self.connection_cache.borrow_mut();
let prefix = self.query_commitment_prefix()?;
for (transaction, cell_input, client_id) in self.rt.block_on(future)? {
for (transaction, cell_input, capacity, client_id) in self.rt.block_on(future)? {
let tx = transaction
.expect("empty transaction response")
.transaction
Expand All @@ -385,11 +385,21 @@ impl Ckb4IbcChain {
};
let (connections, ibc_connection) = extract_connections_from_tx(tx, &prefix)?;
let client_type = self.config.lc_client_type(&client_id)?;
cache.insert(client_type, (ibc_connection, cell_input, connections));
cache.insert(
client_type,
(ibc_connection, cell_input, capacity, connections),
);
}
Ok(())
}

fn clear_cache(&mut self) {
self.channel_input_data.get_mut().clear();
self.channel_cache.get_mut().clear();
self.packet_input_data.get_mut().clear();
self.connection_cache.get_mut().clear();
}

pub fn complete_tx_with_secp256k1_change_and_envelope(
&self,
tx: CoreTransactionView,
Expand All @@ -404,19 +414,31 @@ impl Ckb4IbcChain {
input_capacity,
fee_rate,
);
let (result, _) = self.rt.block_on(tx)?;
let (tx, extra_inputs) = self.rt.block_on(tx)?;

let total_inputs_capacity = extra_inputs
.into_iter()
.map(|v| Unpack::<u64>::unpack(&v.capacity()))
.sum::<u64>()
+ input_capacity;
let total_outputs_capacity = tx.outputs_capacity().unwrap().as_u64();
assert!(
total_inputs_capacity > total_outputs_capacity,
"capacity overflow: {total_inputs_capacity} > {total_outputs_capacity}"
);

let witness = WitnessArgs::new_builder()
.output_type(get_encoded_object(&envelope).witness)
.build()
.as_bytes()
.pack();
let result = result
let tx = tx
.as_advanced_builder()
// placeholder for the secp256k1 script, it will be used in the signing step
.witness(WitnessArgs::new_builder().build().as_bytes().pack())
.witness(witness)
.build();
Ok(result)
Ok(tx)
}

fn counterparty_client_type(&self) -> ClientType {
Expand Down Expand Up @@ -893,7 +915,7 @@ impl ChainEndpoint for Ckb4IbcChain {
.connection_cache
.borrow()
.iter()
.flat_map(|(_, (_, _, connection))| connection.clone())
.flat_map(|(_, (_, _, _, connection))| connection.clone())
.collect();
Ok(connections)
}
Expand All @@ -904,7 +926,7 @@ impl ChainEndpoint for Ckb4IbcChain {
) -> Result<Vec<ConnectionId>, Error> {
self.query_connection_and_cache()?;
let client_type = self.config.lc_client_type(&request.client_id.to_string())?;
if let Some((_, _, connection)) = self.connection_cache.borrow().get(&client_type) {
if let Some((_, _, _, connection)) = self.connection_cache.borrow().get(&client_type) {
self.sync_counterparty_client_type(client_type);
let connection_ids = connection.iter().map(|v| v.connection_id.clone()).collect();
Ok(connection_ids)
Expand Down
41 changes: 23 additions & 18 deletions crates/relayer/src/chain/ckb4ibc/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,15 @@ pub trait MsgToTxConverter {
channel_id: &ChannelId,
) -> Result<&IbcConnections, Error>;

fn get_ibc_connections_input(&self, client_id: &str) -> Result<&CellInput, Error>;
fn get_ibc_connections_input(&self, client_id: &str) -> Result<(&CellInput, u64), Error>;

fn get_ibc_channel(&self, id: &ChannelId) -> Result<&IbcChannel, Error>;

fn get_ibc_channel_input(
&self,
channel_id: &ChannelId,
port_id: &PortId,
) -> Result<&CellInput, Error>;
) -> Result<(&CellInput, u64), Error>;

fn get_client_outpoint(&self, client_id: &str) -> Option<&OutPoint>;

Expand All @@ -117,7 +117,7 @@ pub trait MsgToTxConverter {
chan: &ChannelId,
port: &PortId,
seq: &Sequence,
) -> Result<&CellInput, Error>;
) -> Result<(&CellInput, u64), Error>;

fn get_ibc_packet(
&self,
Expand All @@ -132,12 +132,15 @@ pub trait MsgToTxConverter {
}

pub struct Converter<'a> {
pub channel_input_data: Ref<'a, HashMap<(ChannelId, PortId), CellInput>>,
pub channel_input_data: Ref<'a, HashMap<(ChannelId, PortId), (CellInput, u64)>>,
pub channel_cache: Ref<'a, HashMap<ChannelId, IbcChannel>>,
#[allow(clippy::type_complexity)]
pub connection_cache:
Ref<'a, HashMap<ClientType, (IbcConnections, CellInput, Vec<IdentifiedConnectionEnd>)>>,
pub packet_input_data: Ref<'a, HashMap<(ChannelId, PortId, Sequence), CellInput>>,
pub connection_cache: Ref<
'a,
HashMap<ClientType, (IbcConnections, CellInput, u64, Vec<IdentifiedConnectionEnd>)>,
>,
#[allow(clippy::type_complexity)]
pub packet_input_data: Ref<'a, HashMap<(ChannelId, PortId, Sequence), (CellInput, u64)>>,
pub packet_cache: Ref<'a, HashMap<(ChannelId, PortId, Sequence), IbcPacket>>,
pub config: &'a ChainConfig,
pub client_outpoints: Ref<'a, HashMap<ClientType, OutPoint>>,
Expand All @@ -154,7 +157,7 @@ impl<'a> MsgToTxConverter for Converter<'a> {

fn get_ibc_connections(&self, client_id: &str) -> Result<&IbcConnections, Error> {
let client_type = self.config.lc_client_type(client_id)?;
if let Some((connection, _, _)) = self.connection_cache.get(&client_type) {
if let Some((connection, _, _, _)) = self.connection_cache.get(&client_type) {
Ok(connection)
} else {
Err(Error::query(format!(
Expand All @@ -167,13 +170,13 @@ impl<'a> MsgToTxConverter for Converter<'a> {
&self,
connection_id: &ConnectionId,
) -> Result<&IbcConnections, Error> {
let ibc_connections = self.connection_cache.iter().find(|(_, (v, _, _))| {
let ibc_connections = self.connection_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 {
if let Some((_, (value, _, _, _))) = ibc_connections {
Ok(value)
} else {
Err(Error::query(format!(
Expand All @@ -195,10 +198,10 @@ impl<'a> MsgToTxConverter for Converter<'a> {
self.get_ibc_connections_by_connection_id(&connection_id)
}

fn get_ibc_connections_input(&self, client_id: &str) -> Result<&CellInput, Error> {
fn get_ibc_connections_input(&self, client_id: &str) -> Result<(&CellInput, u64), Error> {
let client_type = self.config.lc_client_type(client_id)?;
if let Some((_, cell_input, _)) = self.connection_cache.get(&client_type) {
Ok(cell_input)
if let Some((_, cell_input, capacity, _)) = self.connection_cache.get(&client_type) {
Ok((cell_input, *capacity))
} else {
Err(Error::query(format!(
"client_type {client_type} isn't in cache"
Expand All @@ -216,9 +219,10 @@ impl<'a> MsgToTxConverter for Converter<'a> {
&self,
channel_id: &ChannelId,
port_id: &PortId,
) -> Result<&CellInput, Error> {
) -> Result<(&CellInput, u64), Error> {
self.channel_input_data
.get(&(channel_id.clone(), port_id.clone()))
.map(|(input, capacity)| (input, *capacity))
.ok_or(Error::query(format!("no channel({channel_id}/{port_id})")))
}

Expand Down Expand Up @@ -258,9 +262,10 @@ impl<'a> MsgToTxConverter for Converter<'a> {
channel_id: &ChannelId,
port_id: &PortId,
sequence: &Sequence,
) -> Result<&CellInput, Error> {
) -> Result<(&CellInput, u64), Error> {
self.packet_input_data
.get(&(channel_id.clone(), port_id.clone(), *sequence))
.map(|(input, capacity)| (input, *capacity))
.ok_or(Error::query(format!(
"no packet({channel_id}/{port_id}/{sequence})"
)))
Expand Down Expand Up @@ -410,13 +415,13 @@ impl TxBuilder {
self.builder.input(input).into()
}

pub fn output(self, lock: Script, capacity: Capacity, data: PackedBytes) -> Self {
pub fn output(self, lock: Script, data: PackedBytes) -> Self {
self.builder
.output(
CellOutput::new_builder()
.lock(lock)
.capacity(capacity.pack())
.build(),
.build_exact_capacity(Capacity::bytes(data.len()).unwrap())
.expect("transaction output capacity"),
)
.output_data(data)
.into()
Expand Down
Loading

0 comments on commit c005570

Please sign in to comment.