From 963bf1a4ca5538fe9207018bca730fb4a0bf25f6 Mon Sep 17 00:00:00 2001 From: Yin Guanhao Date: Mon, 27 Nov 2023 15:39:46 +0800 Subject: [PATCH] feat!: write commitment --- .github/workflows/rust.yml | 2 + axon/src/handler/mod.rs | 341 +++++++++++------- axon/src/handler/objects.rs | 36 +- axon/src/handler/test.rs | 682 ++++++++++++++++++++++++++++-------- axon/src/lib.rs | 76 ++-- axon/src/message.rs | 63 +++- axon/src/object.rs | 53 ++- 7 files changed, 953 insertions(+), 300 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 882ac4d..44c2325 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -11,6 +11,8 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Fmt check + run: cargo fmt --all -- --check - name: Build run: cargo build --verbose --workspace - name: Run tests diff --git a/axon/src/handler/mod.rs b/axon/src/handler/mod.rs index 32b762a..cd7329f 100644 --- a/axon/src/handler/mod.rs +++ b/axon/src/handler/mod.rs @@ -2,19 +2,16 @@ use alloc::string::ToString; use prost::Message; -use rlp::decode; use crate::consts::COMMITMENT_PREFIX; -use crate::get_channel_id_str; use crate::message::{ - Envelope, MsgAckPacket, MsgChannelCloseConfirm, MsgChannelCloseInit, MsgChannelOpenAck, - MsgChannelOpenConfirm, MsgChannelOpenInit, MsgChannelOpenTry, MsgConnectionOpenAck, - MsgConnectionOpenConfirm, MsgConnectionOpenInit, MsgConnectionOpenTry, MsgConsumeAckPacket, - MsgRecvPacket, MsgSendPacket, MsgType, MsgWriteAckPacket, + MsgAckPacket, MsgChannelCloseConfirm, MsgChannelOpenAck, MsgChannelOpenConfirm, + MsgChannelOpenTry, MsgConnectionOpenAck, MsgConnectionOpenConfirm, MsgConnectionOpenTry, + MsgRecvPacket, }; use crate::object::{ConnectionEnd, Ordering, State, VerifyError, Version}; use crate::proto::client::Height; -use crate::{commitment::*, connection_id, proto}; +use crate::{commitment::*, connection_id, proto, WriteOrVerifyCommitments}; use crate::{ChannelArgs, ConnectionArgs, PacketArgs}; mod objects; @@ -23,13 +20,12 @@ mod test; pub use objects::*; -pub fn handle_msg_connection_open_init( - _client: C, +pub fn handle_msg_connection_open_init( mut old_connections: IbcConnections, old_args: ConnectionArgs, new_connections: IbcConnections, new_args: ConnectionArgs, - _: MsgConnectionOpenInit, + commitment: impl WriteOrVerifyCommitments, ) -> Result<(), VerifyError> { if old_args != new_args { return Err(VerifyError::WrongConnectionArgs); @@ -59,7 +55,15 @@ pub fn handle_msg_connection_open_init( return Err(VerifyError::WrongConnectionState); } - Ok(()) + let connection_idx = new_connections.connections.len() - 1; + + let client_id = new_args.client_id(); + + write_connection_state( + commitment, + &connection_id(&client_id, connection_idx), + &new.clone().to_proto(client_id), + ) } pub fn handle_msg_connection_open_try( @@ -68,6 +72,7 @@ pub fn handle_msg_connection_open_try( old_args: ConnectionArgs, new_connections: IbcConnections, new_args: ConnectionArgs, + commitment: impl WriteOrVerifyCommitments, msg: MsgConnectionOpenTry, ) -> Result<(), VerifyError> { if old_args != new_args { @@ -92,11 +97,19 @@ pub fn handle_msg_connection_open_try( return Err(VerifyError::WrongConnectionState); } + let client_id = new_args.client_id(); + + write_connection_state( + commitment, + &connection_id(&client_id, new_connections.connections.len() - 1), + &connection.clone().to_proto(client_id.clone()), + )?; + let expected_connection_end_on_counterparty = proto::connection::ConnectionEnd { state: proto::connection::State::Init as _, client_id: counterparty.client_id.clone(), counterparty: Some(proto::connection::Counterparty { - client_id: new_args.client_id(), + client_id, connection_id: "".to_string(), prefix: Some(proto::commitment::MerklePrefix { key_prefix: COMMITMENT_PREFIX.to_vec(), @@ -118,6 +131,14 @@ pub fn handle_msg_connection_open_try( Ok(()) } +fn write_connection_state( + mut commitment: impl WriteOrVerifyCommitments, + connection_id: &str, + connection: &proto::connection::ConnectionEnd, +) -> Result<(), VerifyError> { + commitment.write_commitments([(connection_path(connection_id), connection.encode_to_vec())]) +} + fn verify_connection_state( client: &impl Client, proof_height: Height, @@ -139,6 +160,7 @@ pub fn handle_msg_connection_open_ack( old_args: ConnectionArgs, new: IbcConnections, new_args: ConnectionArgs, + commitment: impl WriteOrVerifyCommitments, msg: MsgConnectionOpenAck, ) -> Result<(), VerifyError> { if old_args != new_args { @@ -158,13 +180,21 @@ pub fn handle_msg_connection_open_ack( return Err(VerifyError::WrongConnectionState); } - // Verify counterparty connection state. let client_id = new_args.client_id(); + let connection_id = connection_id(&client_id, conn_idx); + + write_connection_state( + commitment, + &connection_id, + &new_connection.clone().to_proto(client_id.clone()), + )?; + + // Verify counterparty connection state. let expected = proto::connection::ConnectionEnd { state: proto::connection::State::Tryopen as _, client_id: new_connection.counterparty.client_id.clone(), counterparty: Some(proto::connection::Counterparty { - connection_id: connection_id(&client_id, conn_idx), + connection_id, client_id, prefix: Some(proto::commitment::MerklePrefix { key_prefix: COMMITMENT_PREFIX.to_vec(), @@ -191,6 +221,7 @@ pub fn handle_msg_connection_open_confirm( old_args: ConnectionArgs, new: IbcConnections, new_args: ConnectionArgs, + commitment: impl WriteOrVerifyCommitments, msg: MsgConnectionOpenConfirm, ) -> Result<(), VerifyError> { if old_args != new_args { @@ -210,13 +241,20 @@ pub fn handle_msg_connection_open_confirm( } let client_id = new_args.client_id(); + let connection_id = connection_id(&client_id, conn_idx); + + write_connection_state( + commitment, + &connection_id, + &new_connection.clone().to_proto(client_id.clone()), + )?; // Verify counterparty state. let expected = proto::connection::ConnectionEnd { state: proto::connection::State::Open as _, client_id: new_connection.counterparty.client_id.clone(), counterparty: Some(proto::connection::Counterparty { - connection_id: connection_id(&client_id, conn_idx), + connection_id, client_id, prefix: Some(proto::commitment::MerklePrefix { key_prefix: COMMITMENT_PREFIX.to_vec(), @@ -237,17 +275,16 @@ pub fn handle_msg_connection_open_confirm( Ok(()) } -pub fn handle_channel_open_init_and_try( - client: C, - channel: IbcChannel, - channel_args: ChannelArgs, - envelop: Envelope, +pub fn handle_msg_channel_open_init( mut old_connections: IbcConnections, old_connection_args: ConnectionArgs, new_connections: IbcConnections, new_connection_args: ConnectionArgs, + channel: IbcChannel, + channel_args: ChannelArgs, + commitment: impl WriteOrVerifyCommitments, ) -> Result<(), VerifyError> { - if channel.number != old_connections.next_channel_number { + if channel_args.channel_id != old_connections.next_channel_number { return Err(VerifyError::WrongChannel); } old_connections.next_channel_number += 1; @@ -259,51 +296,23 @@ pub fn handle_channel_open_init_and_try( return Err(VerifyError::WrongConnectionArgs); } - if channel_args.connection() != old_connection_args - || channel_args.open - || channel_args.channel_id != channel.number - || hex::encode(channel_args.port_id) != channel.port_id - { + if channel_args.connection() != old_connection_args || channel_args.open { return Err(VerifyError::WrongChannelArgs); } - match envelop.msg_type { - MsgType::MsgChannelOpenInit => { - let init_msg = decode::(&envelop.content) - .map_err(|_| VerifyError::SerdeError)?; - handle_msg_channel_open_init( - &new_connection_args.client_id(), - &new_connections, - channel, - init_msg, - ) - } - MsgType::MsgChannelOpenTry => { - let open_try_msg = decode::(&envelop.content) - .map_err(|_| VerifyError::SerdeError)?; - handle_msg_channel_open_try( - client, - &new_connection_args.client_id(), - &new_connections, - channel, - open_try_msg, - ) - } - _ => Err(VerifyError::EventNotMatch), + let new = channel; + + if new.number != channel_args.channel_id || new.port_id != channel_args.port_id_str() { + return Err(VerifyError::WrongChannel); } -} -pub fn handle_msg_channel_open_init( - client_id: &str, - ibc_connections: &IbcConnections, - new: IbcChannel, - _msg: MsgChannelOpenInit, -) -> Result<(), VerifyError> { + let client_id = new_connection_args.client_id(); + if new.connection_hops.len() != 1 { return Err(VerifyError::ConnectionsWrong); } - let conn = ibc_connections - .get_by_id(client_id, &new.connection_hops[0]) + let conn = new_connections + .get_by_id(&client_id, &new.connection_hops[0]) .ok_or(VerifyError::WrongConnectionId)?; if conn.state != State::Open { @@ -322,22 +331,55 @@ pub fn handle_msg_channel_open_init( return Err(VerifyError::WrongConnectionCounterparty); } - Ok(()) + write_channel_commitment( + commitment, + &new.port_id.clone(), + &channel_args.channel_id_str(), + &new.into(), + ) } pub fn handle_msg_channel_open_try( client: C, - client_id: &str, - ibc_connections: &IbcConnections, - new: IbcChannel, + mut old_connections: IbcConnections, + old_connection_args: ConnectionArgs, + new_connections: IbcConnections, + new_connection_args: ConnectionArgs, + channel: IbcChannel, + channel_args: ChannelArgs, + commitment: impl WriteOrVerifyCommitments, msg: MsgChannelOpenTry, ) -> Result<(), VerifyError> { + if channel_args.channel_id != old_connections.next_channel_number { + return Err(VerifyError::WrongChannel); + } + old_connections.next_channel_number += 1; + if old_connections != new_connections { + return Err(VerifyError::WrongConnectionState); + } + + if old_connection_args != new_connection_args { + return Err(VerifyError::WrongConnectionArgs); + } + + if channel_args.connection() != old_connection_args || channel_args.open { + return Err(VerifyError::WrongChannelArgs); + } + + let new = channel; + + if new.number != channel_args.channel_id || new.port_id != channel_args.port_id_str() { + return Err(VerifyError::WrongChannel); + } + + let client_id = new_connection_args.client_id(); + if new.connection_hops.len() != 1 { return Err(VerifyError::ConnectionsWrong); } - let conn = ibc_connections - .get_by_id(client_id, &new.connection_hops[0]) + let conn = new_connections + .get_by_id(&client_id, &new.connection_hops[0]) .ok_or(VerifyError::WrongConnectionId)?; if conn.state != State::Open { @@ -356,6 +398,15 @@ pub fn handle_msg_channel_open_try( return Err(VerifyError::WrongConnectionCounterparty); } + let port_id = new.port_id.clone(); + + write_channel_commitment( + commitment, + &port_id, + &channel_args.channel_id_str(), + &new.clone().into(), + )?; + let expected = proto::channel::Channel { state: proto::channel::State::Init as i32, ordering: proto::channel::Order::from(new.order) as i32, @@ -365,7 +416,7 @@ pub fn handle_msg_channel_open_try( version: new.version, counterparty: Some(proto::channel::Counterparty { channel_id: "".into(), - port_id: new.port_id, + port_id, }), }; @@ -381,6 +432,15 @@ pub fn handle_msg_channel_open_try( Ok(()) } +fn write_channel_commitment( + mut commitment: impl WriteOrVerifyCommitments, + port_id: &str, + channel_id: &str, + channel: &proto::channel::Channel, +) -> Result<(), VerifyError> { + commitment.write_commitments([(channel_path(port_id, channel_id), channel.encode_to_vec())]) +} + fn verify_channel_state( client: &impl Client, proof_height: Height, @@ -397,43 +457,23 @@ fn verify_channel_state( ) } -pub fn handle_channel_open_ack_and_confirm( +pub fn handle_msg_channel_open_ack( client: C, - envelope: Envelope, - old_channel: IbcChannel, - old_args: ChannelArgs, - new_channel: IbcChannel, + mut old: IbcChannel, + mut old_args: ChannelArgs, + new: IbcChannel, new_args: ChannelArgs, + commitment: impl WriteOrVerifyCommitments, + msg: MsgChannelOpenAck, ) -> Result<(), VerifyError> { - if old_args.open - || !new_args.open - || old_args.metadata_type_id != new_args.metadata_type_id - || old_args.channel_id != new_args.channel_id - || old_args.port_id != new_args.port_id - { + if old_args.open { return Err(VerifyError::WrongChannelArgs); } - match envelope.msg_type { - MsgType::MsgChannelOpenAck => { - let msg = decode::(&envelope.content) - .map_err(|_| VerifyError::SerdeError)?; - handle_msg_channel_open_ack(client, old_channel, new_channel, msg) - } - MsgType::MsgChannelOpenConfirm => { - let msg = decode::(&envelope.content) - .map_err(|_| VerifyError::SerdeError)?; - handle_msg_channel_open_confirm(client, old_channel, new_channel, msg) - } - _ => Err(VerifyError::EventNotMatch), + old_args.open = true; + if old_args != new_args { + return Err(VerifyError::WrongChannelArgs); } -} -pub fn handle_msg_channel_open_ack( - client: C, - mut old: IbcChannel, - new: IbcChannel, - msg: MsgChannelOpenAck, -) -> Result<(), VerifyError> { if old.state != State::Init { return Err(VerifyError::WrongChannelState); } @@ -446,14 +486,19 @@ pub fn handle_msg_channel_open_ack( return Err(VerifyError::WrongChannel); } + let port_id = new.port_id.clone(); + let channel_id = new_args.channel_id_str(); + + write_channel_commitment(commitment, &port_id, &channel_id, &new.clone().into())?; + let expected = proto::channel::Channel { state: proto::channel::State::Tryopen as i32, ordering: proto::channel::Order::from(new.order) as i32, connection_hops: vec![new.counterparty.connection_id], version: new.version, counterparty: Some(proto::channel::Counterparty { - channel_id: get_channel_id_str(new.number), - port_id: new.port_id, + channel_id, + port_id, }), }; @@ -472,9 +517,20 @@ pub fn handle_msg_channel_open_ack( pub fn handle_msg_channel_open_confirm( client: C, mut old: IbcChannel, + mut old_args: ChannelArgs, new: IbcChannel, + new_args: ChannelArgs, + commitment: impl WriteOrVerifyCommitments, msg: MsgChannelOpenConfirm, ) -> Result<(), VerifyError> { + if old_args.open { + return Err(VerifyError::WrongChannelArgs); + } + old_args.open = true; + if old_args != new_args { + return Err(VerifyError::WrongChannelArgs); + } + if old.state != State::OpenTry { return Err(VerifyError::WrongChannelState); } @@ -483,14 +539,19 @@ pub fn handle_msg_channel_open_confirm( return Err(VerifyError::WrongChannel); } + let port_id = new.port_id.clone(); + let channel_id = new_args.channel_id_str(); + + write_channel_commitment(commitment, &port_id, &channel_id, &new.clone().into())?; + let expected = proto::channel::Channel { state: proto::channel::State::Open as i32, ordering: proto::channel::Order::from(new.order) as i32, connection_hops: vec![new.counterparty.connection_id], version: new.version, counterparty: Some(proto::channel::Counterparty { - channel_id: get_channel_id_str(new.number), - port_id: new.port_id, + channel_id, + port_id, }), }; @@ -506,13 +567,12 @@ pub fn handle_msg_channel_open_confirm( Ok(()) } -pub fn handle_msg_channel_close_init( - _: C, +pub fn handle_msg_channel_close_init( mut old: IbcChannel, mut old_args: ChannelArgs, new: IbcChannel, new_args: ChannelArgs, - _: MsgChannelCloseInit, + commitment: impl WriteOrVerifyCommitments, ) -> Result<(), VerifyError> { if old.state != State::Open { return Err(VerifyError::WrongChannelState); @@ -530,6 +590,13 @@ pub fn handle_msg_channel_close_init( return Err(VerifyError::WrongChannelArgs); } + write_channel_commitment( + commitment, + &new.port_id.clone(), + &new_args.channel_id_str(), + &new.into(), + )?; + Ok(()) } @@ -539,6 +606,7 @@ pub fn handle_msg_channel_close_confirm( mut old_args: ChannelArgs, new: IbcChannel, new_args: ChannelArgs, + commitment: impl WriteOrVerifyCommitments, msg: MsgChannelCloseConfirm, ) -> Result<(), VerifyError> { if old.state != State::Open { @@ -557,14 +625,19 @@ pub fn handle_msg_channel_close_confirm( return Err(VerifyError::WrongChannelArgs); } + let port_id = new.port_id.clone(); + let channel_id = new_args.channel_id_str(); + + write_channel_commitment(commitment, &port_id, &channel_id, &new.clone().into())?; + let expected = proto::channel::Channel { state: proto::channel::State::Closed as i32, ordering: proto::channel::Order::from(new.order) as i32, connection_hops: vec![new.counterparty.connection_id], - version: "TODO".into(), + version: new.version, counterparty: Some(proto::channel::Counterparty { - channel_id: get_channel_id_str(new.number), - port_id: new.port_id, + channel_id, + port_id, }), }; @@ -578,15 +651,14 @@ pub fn handle_msg_channel_close_confirm( ) } -pub fn handle_msg_send_packet( - _: C, +pub fn handle_msg_send_packet( mut old_channel: IbcChannel, old_channel_args: ChannelArgs, new_channel: IbcChannel, new_channel_args: ChannelArgs, ibc_packet: IbcPacket, packet_args: PacketArgs, - _: MsgSendPacket, + mut commitment: impl WriteOrVerifyCommitments, ) -> Result<(), VerifyError> { if ibc_packet.packet.sequence != old_channel.sequence.next_sequence_sends { return Err(VerifyError::WrongPacketSequence); @@ -601,9 +673,11 @@ pub fn handle_msg_send_packet( return Err(VerifyError::WrongChannelArgs); } - if hex::encode(packet_args.port_id) != ibc_packet.packet.source_port_id + packet_args.is_channel(&new_channel_args)?; + + if new_channel_args.port_id_str() != ibc_packet.packet.source_port_id || packet_args.sequence != ibc_packet.packet.sequence - || get_channel_id_str(packet_args.channel_id) != ibc_packet.packet.source_channel_id + || new_channel_args.channel_id_str() != ibc_packet.packet.source_channel_id { return Err(VerifyError::WrongPacketArgs); } @@ -626,6 +700,21 @@ pub fn handle_msg_send_packet( return Err(VerifyError::WrongPacketAck); } + commitment.write_commitments([( + packet_commitment_path( + &ibc_packet.packet.source_port_id, + &ibc_packet.packet.source_channel_id, + ibc_packet.packet.sequence, + ), + sha256(&[ + &ibc_packet.packet.timeout_timestamp.to_le_bytes(), + // Revision number + &0u64.to_le_bytes(), + &ibc_packet.packet.timeout_height.to_le_bytes(), + &sha256(&[&ibc_packet.packet.data]), + ]), + )])?; + Ok(()) } @@ -638,6 +727,7 @@ pub fn handle_msg_recv_packet( useless_ibc_packet: Option, ibc_packet: IbcPacket, packet_args: PacketArgs, + mut commitment: impl WriteOrVerifyCommitments, msg: MsgRecvPacket, ) -> Result<(), VerifyError> { // A write_ack packet can be consumed. @@ -678,20 +768,24 @@ pub fn handle_msg_recv_packet( return Err(VerifyError::WrongChannelArgs); } - if hex::encode(packet_args.port_id) != ibc_packet.packet.destination_port_id + packet_args.is_channel(&new_channel_args)?; + + if new_channel_args.port_id_str() != ibc_packet.packet.destination_port_id || packet_args.sequence != ibc_packet.packet.sequence - || get_channel_id_str(packet_args.channel_id) != ibc_packet.packet.destination_channel_id + || new_channel_args.channel_id_str() != ibc_packet.packet.destination_channel_id { return Err(VerifyError::WrongPacketArgs); } + commitment.write_no_commitment()?; + client.verify_membership( msg.proof_height, &msg.proof_commitment, packet_commitment_path( &ibc_packet.packet.source_port_id, &ibc_packet.packet.source_channel_id, - ibc_packet.packet.sequence.into(), + ibc_packet.packet.sequence, ) .as_bytes(), &sha256(&[ @@ -723,6 +817,7 @@ pub fn handle_msg_ack_packet( old_packet_args: PacketArgs, new_ibc_packet: IbcPacket, new_packet_args: PacketArgs, + mut commitment: impl WriteOrVerifyCommitments, msg: MsgAckPacket, ) -> Result<(), VerifyError> { if old_ibc_packet.status != PacketStatus::Send { @@ -758,13 +853,15 @@ pub fn handle_msg_ack_packet( return Err(VerifyError::WrongChannel); } + commitment.write_no_commitment()?; + client.verify_membership( msg.proof_height, &msg.proof_acked, packet_acknowledgement_commitment_path( &new_ibc_packet.packet.destination_port_id, &new_ibc_packet.packet.destination_channel_id, - new_ibc_packet.packet.sequence.into(), + new_ibc_packet.packet.sequence, ) .as_bytes(), &sha256(&[&new_ibc_packet.ack.unwrap()]), @@ -780,7 +877,7 @@ pub fn handle_msg_write_ack_packet( old_packet_args: PacketArgs, new_ibc_packet: IbcPacket, new_packet_args: PacketArgs, - _: MsgWriteAckPacket, + mut commitment: impl WriteOrVerifyCommitments, ) -> Result<(), VerifyError> { if old_channel_args != new_channel_args { return Err(VerifyError::WrongChannelArgs); @@ -808,17 +905,27 @@ pub fn handle_msg_write_ack_packet( return Err(VerifyError::WrongPacketAck); } + commitment.write_commitments([( + packet_acknowledgement_commitment_path( + &new_ibc_packet.packet.destination_port_id, + &new_ibc_packet.packet.destination_channel_id, + new_ibc_packet.packet.sequence, + ), + sha256(&[new_ibc_packet.ack.as_deref().unwrap()]), + )])?; + Ok(()) } pub fn handle_msg_consume_ack_packet( old_ibc_packet: IbcPacket, - _: PacketArgs, - _: MsgConsumeAckPacket, + mut commitment: impl WriteOrVerifyCommitments, ) -> Result<(), VerifyError> { if old_ibc_packet.status != PacketStatus::Ack { return Err(VerifyError::WrongPacketStatus); } + commitment.write_no_commitment()?; + Ok(()) } diff --git a/axon/src/handler/objects.rs b/axon/src/handler/objects.rs index bd15fa6..f04d072 100644 --- a/axon/src/handler/objects.rs +++ b/axon/src/handler/objects.rs @@ -1,15 +1,17 @@ use alloc::{string::String, vec::Vec}; -use ethereum_types::H256; + use rlp_derive::RlpDecodable; use rlp_derive::RlpEncodable; use crate::connection_id; use crate::object::{ChannelCounterparty, ConnectionEnd, Ordering, Packet, State, VerifyError}; +use crate::proto; use crate::proto::client::Height; +use crate::ChannelArgs; #[derive(Debug, Default, Clone, RlpDecodable, RlpEncodable, PartialEq, Eq)] pub struct IbcConnections { - pub next_channel_number: u16, + pub next_channel_number: u64, pub connections: Vec, } @@ -37,7 +39,7 @@ fn extract_connection_index(connection_id: &str) -> Result { #[derive(Debug, Clone, RlpDecodable, RlpEncodable, PartialEq, Eq)] pub struct IbcChannel { - pub number: u16, + pub number: u64, pub port_id: String, pub state: State, pub order: Ordering, @@ -54,7 +56,7 @@ impl Default for IbcChannel { fn default() -> Self { Self { number: Default::default(), - port_id: hex::encode([0u8; 32]), + port_id: ChannelArgs::default().port_id_str(), state: Default::default(), order: Default::default(), sequence: Default::default(), @@ -65,10 +67,24 @@ impl Default for IbcChannel { } } +impl From for proto::channel::Channel { + fn from(value: IbcChannel) -> Self { + Self { + connection_hops: value.connection_hops, + counterparty: Some(proto::channel::Counterparty { + channel_id: value.counterparty.channel_id, + port_id: value.counterparty.port_id, + }), + version: value.version, + state: value.state.proto_channel_state() as i32, + ordering: proto::channel::Order::from(value.order) as i32, + } + } +} + #[derive(RlpEncodable, RlpDecodable, Debug, Clone, PartialEq, Eq)] pub struct IbcPacket { pub packet: Packet, - pub tx_hash: Option, pub status: PacketStatus, pub ack: Option>, } @@ -87,11 +103,11 @@ impl_enum_rlp! { #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] pub struct Sequence { - pub next_sequence_sends: u16, - pub next_sequence_recvs: u16, - pub next_sequence_acks: u16, + pub next_sequence_sends: u64, + pub next_sequence_recvs: u64, + pub next_sequence_acks: u64, /// Received sequences for unordered channel. Must be ordered. - pub received_sequences: Vec, + pub received_sequences: Vec, } impl Default for Sequence { @@ -106,7 +122,7 @@ impl Default for Sequence { } impl Sequence { - pub fn unorder_receive(&mut self, seq: u16) -> Result<(), VerifyError> { + pub fn unorder_receive(&mut self, seq: u64) -> Result<(), VerifyError> { match self.received_sequences.binary_search(&seq) { Ok(_) => Err(VerifyError::WrongPacketSequence), Err(idx) => { diff --git a/axon/src/handler/test.rs b/axon/src/handler/test.rs index 33b484e..02dd182 100644 --- a/axon/src/handler/test.rs +++ b/axon/src/handler/test.rs @@ -1,6 +1,7 @@ use alloc::string::String; use crate::handler::*; +use crate::message::CommitmentKV; use crate::object::ChannelCounterparty; use crate::object::ConnectionCounterparty; use crate::object::ConnectionEnd; @@ -24,8 +25,6 @@ impl Client for TestClient { #[test] fn test_handle_msg_connection_open_init() { - let client = TestClient::default(); - let new_connection_end = ConnectionEnd { state: State::Init, ..Default::default() @@ -39,14 +38,12 @@ fn test_handle_msg_connection_open_init() { let old_args = ConnectionArgs::default(); let new_args = ConnectionArgs::default(); - let msg = MsgConnectionOpenInit {}; handle_msg_connection_open_init( - client, old_connections, old_args, new_connections, new_args, - msg, + &mut Vec::new(), ) .unwrap(); } @@ -87,6 +84,7 @@ fn test_handle_msg_connection_open_try() { old_args, new_connections, new_args, + &mut Vec::new(), msg, ) .unwrap(); @@ -145,6 +143,7 @@ fn test_handle_msg_connection_open_ack() { old_args, new_connections, new_args, + &mut Vec::new(), msg, ) .unwrap(); @@ -207,6 +206,7 @@ fn test_handle_msg_connection_open_confirm() { old_args, new_connections, new_args, + &mut Vec::new(), msg, ) .unwrap(); @@ -218,22 +218,35 @@ fn test_handle_msg_channel_open_init() { state: State::Open, ..Default::default() }; + let connection_args = ConnectionArgs::default(); + let channel_args = ChannelArgs::default(); + + let old_connections = IbcConnections { + next_channel_number: 0, + connections: vec![connection_end.clone()], + }; let new_connections = IbcConnections { next_channel_number: 1, connections: vec![connection_end], }; - let client_id = "client-8"; - let channel = IbcChannel { state: State::Init, - connection_hops: vec![connection_id(client_id, 0)], + connection_hops: vec![connection_id(&connection_args.client_id(), 0)], ..Default::default() }; - let msg = MsgChannelOpenInit {}; - handle_msg_channel_open_init(client_id, &new_connections, channel, msg).unwrap(); + handle_msg_channel_open_init( + old_connections, + connection_args, + new_connections, + connection_args, + channel, + channel_args, + &mut Vec::new(), + ) + .unwrap(); } #[test] @@ -245,16 +258,22 @@ fn test_handle_msg_channel_open_try_success() { ..Default::default() }; + let connection_args = ConnectionArgs::default(); + let channel_args = ChannelArgs::default(); + + let old_connections = IbcConnections { + next_channel_number: 0, + connections: vec![connection_end.clone()], + }; + let new_connections = IbcConnections { next_channel_number: 1, connections: vec![connection_end], }; - let client_id = "client-8"; - let channel = IbcChannel { state: State::OpenTry, - connection_hops: vec![connection_id(client_id, 0)], + connection_hops: vec![connection_id(&connection_args.client_id(), 0)], ..Default::default() }; @@ -266,7 +285,18 @@ fn test_handle_msg_channel_open_try_success() { proof_init: vec![], }; - handle_msg_channel_open_try(client, client_id, &new_connections, channel, msg).unwrap() + handle_msg_channel_open_try( + client, + old_connections, + connection_args, + new_connections, + connection_args, + channel, + channel_args, + &mut Vec::new(), + msg, + ) + .unwrap() } #[test] @@ -283,6 +313,12 @@ fn test_handle_msg_channel_open_ack_success() { ..Default::default() }; + let old_channel_args = ChannelArgs::default(); + let new_channel_args = ChannelArgs { + open: true, + ..Default::default() + }; + let new_channel = IbcChannel { state: State::Open, counterparty: ChannelCounterparty { @@ -301,97 +337,14 @@ fn test_handle_msg_channel_open_ack_success() { proof_try: vec![], }; - handle_msg_channel_open_ack(client, old_channel, new_channel, msg).unwrap(); -} - -#[test] -fn test_handle_msg_channel_open_ack_failed() { - let old_args = ChannelArgs { - metadata_type_id: [ - 59, 202, 83, 204, 94, 60, 251, 53, 29, 14, 91, 232, 113, 191, 94, 227, 72, 206, 76, - 254, 177, 59, 247, 13, 54, 105, 235, 22, 75, 21, 45, 12, - ], - ibc_handler_address: [7; 20], - open: false, - channel_id: 0, - port_id: [ - 182, 172, 119, 152, 129, 180, 254, 5, 161, 103, 228, 19, 255, 83, 68, 105, 182, 181, - 246, 192, 109, 149, 228, 197, 35, 235, 41, 69, 216, 94, 212, 80, - ], - }; - - let new_args = ChannelArgs { - metadata_type_id: [ - 59, 202, 83, 204, 94, 60, 251, 53, 29, 14, 91, 232, 113, 191, 94, 227, 72, 206, 76, - 254, 177, 59, 247, 13, 54, 105, 235, 22, 75, 21, 45, 12, - ], - ibc_handler_address: [7; 20], - open: true, - channel_id: 0, - port_id: [ - 182, 172, 119, 152, 129, 180, 254, 5, 161, 103, 228, 19, 255, 83, 68, 105, 182, 181, - 246, 192, 109, 149, 228, 197, 35, 235, 41, 69, 216, 94, 212, 80, - ], - }; - - let client_id = ConnectionArgs { - metadata_type_id: new_args.metadata_type_id, - ibc_handler_address: new_args.ibc_handler_address, - } - .client_id(); - - let client = TestClient::default(); - let old_channel = IbcChannel { - number: 0, - port_id: String::from("b6ac779881b4fe05a167e413ff534469b6b5f6c06d95e4c523eb2945d85ed450"), - state: State::Init, - order: Ordering::Unordered, - sequence: Sequence::default(), - counterparty: ChannelCounterparty { - port_id: String::from( - "54d043fc84623f7a9f7383e1a332c524f0def68608446fc420316c30dfc00f01", - ), - channel_id: String::from(""), - connection_id: "connection-2".into(), - }, - connection_hops: vec![connection_id(&client_id, 0)], - version: "".into(), - }; - let new_channel = IbcChannel { - number: 0, - port_id: String::from("b6ac779881b4fe05a167e413ff534469b6b5f6c06d95e4c523eb2945d85ed450"), - state: State::Open, - order: Ordering::Unordered, - sequence: Sequence::default(), - counterparty: ChannelCounterparty { - port_id: String::from( - "54d043fc84623f7a9f7383e1a332c524f0def68608446fc420316c30dfc00f01", - ), - channel_id: String::from("channel-1"), - connection_id: "connection-2".into(), - }, - connection_hops: vec![connection_id(&client_id, 0)], - version: "".into(), - }; - - let envelope = Envelope { - msg_type: MsgType::MsgChannelOpenAck, - content: rlp::encode(&MsgChannelOpenAck { - proof_height: Height { - revision_number: 0, - revision_height: 0, - }, - proof_try: vec![], - }) - .to_vec(), - }; - handle_channel_open_ack_and_confirm( + handle_msg_channel_open_ack( client, - envelope, old_channel, - old_args, + old_channel_args, new_channel, - new_args, + new_channel_args, + &mut Vec::new(), + msg, ) .unwrap(); } @@ -410,6 +363,12 @@ fn handle_msg_channel_open_confirm_success() { ..Default::default() }; + let old_channel_args = ChannelArgs::default(); + let new_channel_args = ChannelArgs { + open: true, + ..Default::default() + }; + let msg = MsgChannelOpenConfirm { proof_height: Height { revision_number: 0, @@ -418,13 +377,20 @@ fn handle_msg_channel_open_confirm_success() { proof_ack: vec![], }; - handle_msg_channel_open_confirm(client, old_channel, new_channel, msg).unwrap(); + handle_msg_channel_open_confirm( + client, + old_channel, + old_channel_args, + new_channel, + new_channel_args, + &mut Vec::new(), + msg, + ) + .unwrap(); } #[test] fn handle_msg_channel_close_init_success() { - let client = TestClient::default(); - let old_channel = IbcChannel { state: State::Open, ..Default::default() @@ -445,16 +411,18 @@ fn handle_msg_channel_close_init_success() { ..Default::default() }; - let msg = MsgChannelCloseInit {}; - - handle_msg_channel_close_init(client, old_channel, old_args, new_channel, new_args, msg) - .unwrap(); + handle_msg_channel_close_init( + old_channel, + old_args, + new_channel, + new_args, + &mut Vec::new(), + ) + .unwrap(); } #[test] fn handle_msg_channel_close_init_failure() { - let client = TestClient::default(); - let old_channel = IbcChannel { state: State::Open, ..Default::default() @@ -475,11 +443,13 @@ fn handle_msg_channel_close_init_failure() { ..Default::default() }; - let msg = MsgChannelCloseInit {}; - - if let Err(VerifyError::WrongChannelArgs) = - handle_msg_channel_close_init(client, old_channel, old_args, new_channel, new_args, msg) - { + if let Err(VerifyError::WrongChannelArgs) = handle_msg_channel_close_init( + old_channel, + old_args, + new_channel, + new_args, + &mut Vec::new(), + ) { } else { panic!() } @@ -514,8 +484,16 @@ fn handle_msg_channel_close_confirm_success() { proof_init: vec![], }; - handle_msg_channel_close_confirm(client, old_channel, old_args, new_channel, new_args, msg) - .unwrap(); + handle_msg_channel_close_confirm( + client, + old_channel, + old_args, + new_channel, + new_args, + &mut Vec::new(), + msg, + ) + .unwrap(); } #[test] @@ -547,9 +525,15 @@ fn handle_msg_channel_close_confirm_failure() { proof_init: vec![], }; - if let Err(VerifyError::WrongChannel) = - handle_msg_channel_close_confirm(client, old_channel, old_args, new_channel, new_args, msg) - { + if let Err(VerifyError::WrongChannel) = handle_msg_channel_close_confirm( + client, + old_channel, + old_args, + new_channel, + new_args, + &mut Vec::new(), + msg, + ) { } else { panic!() } @@ -570,6 +554,12 @@ fn handle_msg_channel_open_confirm_channel_unmatch() { ..Default::default() }; + let old_channel_args = ChannelArgs::default(); + let new_channel_args = ChannelArgs { + open: true, + ..Default::default() + }; + let msg = MsgChannelOpenConfirm { proof_height: Height { revision_number: 0, @@ -578,9 +568,15 @@ fn handle_msg_channel_open_confirm_channel_unmatch() { proof_ack: vec![], }; - if let Err(VerifyError::WrongChannel) = - handle_msg_channel_open_confirm(client, old_channel, new_channel, msg) - { + if let Err(VerifyError::WrongChannel) = handle_msg_channel_open_confirm( + client, + old_channel, + old_channel_args, + new_channel, + new_channel_args, + &mut Vec::new(), + msg, + ) { } else { panic!() } @@ -588,8 +584,6 @@ fn handle_msg_channel_open_confirm_channel_unmatch() { #[test] fn test_handle_msg_send_packet_success() { - let client = TestClient::default(); - let mut seq2 = Sequence::default(); seq2.next_sequence_sends += 1; @@ -602,7 +596,6 @@ fn test_handle_msg_send_packet_success() { state: State::Open, ..Default::default() }; - let msg = MsgSendPacket {}; let ibc_packet = IbcPacket { packet: Packet { @@ -611,7 +604,6 @@ fn test_handle_msg_send_packet_success() { sequence: 1, ..Default::default() }, - tx_hash: None, status: PacketStatus::Send, ack: None, }; @@ -624,14 +616,13 @@ fn test_handle_msg_send_packet_success() { }; handle_msg_send_packet( - client, old_channel, old_channel_args, new_channel, new_channel_args, ibc_packet, packet_args, - msg, + &mut Vec::new(), ) .unwrap(); } @@ -659,7 +650,6 @@ fn test_msg_recv_packet_success() { sequence: 1, ..Packet::default() }, - tx_hash: None, status: PacketStatus::Recv, ack: None, }; @@ -679,6 +669,7 @@ fn test_msg_recv_packet_success() { None, ibc_packet, packet_args, + &mut Vec::new(), MsgRecvPacket { proof_height: Height { revision_number: 0, @@ -703,13 +694,11 @@ fn test_msg_ack_outbox_packet_success() { let packet = Packet::default(); let old_ibc_packet = IbcPacket { packet: packet.clone(), - tx_hash: None, status: PacketStatus::Recv, ack: None, }; let new_ibc_packet = IbcPacket { packet, - tx_hash: None, status: PacketStatus::WriteAck, ack: Some(vec![1]), }; @@ -722,7 +711,7 @@ fn test_msg_ack_outbox_packet_success() { PacketArgs::default(), new_ibc_packet, PacketArgs::default(), - MsgWriteAckPacket {}, + &mut Vec::new(), ) .unwrap(); } @@ -741,13 +730,11 @@ fn test_msg_write_ack_packet_channel_state_error() { let new_packet = old_packet.clone(); let old_ibc_packet = IbcPacket { packet: old_packet, - tx_hash: None, status: PacketStatus::Recv, ack: None, }; let new_ibc_packet = IbcPacket { packet: new_packet, - tx_hash: None, status: PacketStatus::WriteAck, ack: Some(vec![1]), }; @@ -760,7 +747,7 @@ fn test_msg_write_ack_packet_channel_state_error() { PacketArgs::default(), new_ibc_packet, PacketArgs::default(), - MsgWriteAckPacket {}, + &mut Vec::new(), ) { } else { panic!() @@ -782,13 +769,11 @@ fn test_msg_ack_outbox_packet_differenct_packet() { new_packet.sequence = 1; let old_ibc_packet = IbcPacket { packet: old_packet, - tx_hash: None, status: PacketStatus::Recv, ack: None, }; let new_ibc_packet = IbcPacket { packet: new_packet, - tx_hash: None, status: PacketStatus::WriteAck, ack: None, }; @@ -801,7 +786,7 @@ fn test_msg_ack_outbox_packet_differenct_packet() { PacketArgs::default(), new_ibc_packet, PacketArgs::default(), - MsgWriteAckPacket {}, + &mut Vec::new(), ) { } else { panic!() @@ -815,3 +800,420 @@ fn test_ibc_connection_encode_and_decode() { let a = rlp::encode(&conn); rlp::decode::(&a).unwrap(); } + +struct ClientWithCommitments { + commitments: Vec, +} + +fn client_with_commitments(commitments: Vec) -> ClientWithCommitments { + ClientWithCommitments { commitments } +} + +impl Client for ClientWithCommitments { + fn verify_membership( + &self, + _height: Height, + _proof: &[u8], + path: &[u8], + value: &[u8], + ) -> Result<(), VerifyError> { + let expected = CommitmentKV::hash(path, value); + if self.commitments.iter().any(|c| *c == expected) { + Ok(()) + } else { + Err(VerifyError::Mpt) + } + } +} + +#[test] +fn test_connection_commitment_ping_pong() { + let a_connections_before_init = IbcConnections::default(); + let a_args = ConnectionArgs::default(); + let b_args = ConnectionArgs { + metadata_type_id: [3; 32], + ibc_handler_address: [4; 20], + }; + let a_connections_after_init = IbcConnections { + connections: vec![ConnectionEnd { + state: State::Init, + counterparty: ConnectionCounterparty { + client_id: b_args.client_id(), + ..Default::default() + }, + ..Default::default() + }], + ..Default::default() + }; + + let mut init_commitments = Vec::new(); + handle_msg_connection_open_init( + a_connections_before_init.clone(), + a_args, + a_connections_after_init.clone(), + a_args, + &mut init_commitments, + ) + .unwrap(); + + let mut try_commitments = Vec::new(); + let b_connections_after_try = IbcConnections { + connections: vec![ConnectionEnd { + state: State::OpenTry, + counterparty: ConnectionCounterparty { + client_id: a_args.client_id(), + connection_id: connection_id(&a_args.client_id(), 0), + ..Default::default() + }, + ..Default::default() + }], + ..Default::default() + }; + handle_msg_connection_open_try( + client_with_commitments(init_commitments), + a_connections_before_init.clone(), + b_args, + b_connections_after_try.clone(), + b_args, + &mut try_commitments, + MsgConnectionOpenTry { + proof_height: Height::default(), + proof_init: vec![], + }, + ) + .unwrap(); + + let mut ack_commitments = Vec::new(); + let a_connection_after_ack = IbcConnections { + connections: vec![ConnectionEnd { + state: State::Open, + counterparty: ConnectionCounterparty { + client_id: b_args.client_id(), + connection_id: connection_id(&b_args.client_id(), 0), + ..Default::default() + }, + ..Default::default() + }], + ..Default::default() + }; + handle_msg_connection_open_ack( + client_with_commitments(try_commitments), + a_connections_after_init.clone(), + a_args, + a_connection_after_ack, + a_args, + &mut ack_commitments, + MsgConnectionOpenAck { + conn_id_on_a: 0, + proof_height: Height::default(), + proof_try: vec![], + }, + ) + .unwrap(); + + let b_connections_after_confirm = IbcConnections { + connections: vec![ConnectionEnd { + state: State::Open, + counterparty: ConnectionCounterparty { + client_id: a_args.client_id(), + connection_id: connection_id(&a_args.client_id(), 0), + ..Default::default() + }, + ..Default::default() + }], + ..Default::default() + }; + handle_msg_connection_open_confirm( + client_with_commitments(ack_commitments), + b_connections_after_try.clone(), + b_args, + b_connections_after_confirm, + b_args, + &mut Vec::new(), + MsgConnectionOpenConfirm { + conn_id_on_b: 0, + proof_height: Height::default(), + proof_ack: vec![], + }, + ) + .unwrap(); +} + +#[test] +fn test_channel_packet_commitment_ping_pong() { + let a_conn_args = ConnectionArgs::default(); + let b_conn_args = ConnectionArgs { + metadata_type_id: [3; 32], + ibc_handler_address: [4; 20], + }; + let b_conn_id = connection_id(&b_conn_args.client_id(), 1); + let a_conn_id = connection_id(&a_conn_args.client_id(), 0); + let a_conns = IbcConnections { + connections: vec![ConnectionEnd { + state: State::Open, + counterparty: ConnectionCounterparty { + client_id: b_conn_args.client_id(), + connection_id: b_conn_id.clone(), + ..Default::default() + }, + ..Default::default() + }], + next_channel_number: 0, + }; + let b_conns = IbcConnections { + connections: vec![ + ConnectionEnd::default(), + ConnectionEnd { + state: State::Open, + counterparty: ConnectionCounterparty { + client_id: a_conn_args.client_id(), + connection_id: a_conn_id.clone(), + ..Default::default() + }, + ..Default::default() + }, + ], + next_channel_number: 1, + }; + + let mut a_conns_after_init = a_conns.clone(); + a_conns_after_init.next_channel_number += 1; + let a_channel_args = ChannelArgs { + metadata_type_id: a_conn_args.metadata_type_id, + ibc_handler_address: a_conn_args.ibc_handler_address, + channel_id: 0, + open: false, + port_id: [7; 32], + }; + let b_channel_args = ChannelArgs { + metadata_type_id: b_conn_args.metadata_type_id, + ibc_handler_address: b_conn_args.ibc_handler_address, + channel_id: 1, + open: false, + port_id: [9; 32], + }; + let a_channel_init = IbcChannel { + state: State::Init, + number: 0, + order: Ordering::Unordered, + port_id: a_channel_args.port_id_str(), + connection_hops: vec![a_conn_id.clone()], + counterparty: ChannelCounterparty { + channel_id: "".into(), + port_id: b_channel_args.port_id_str(), + connection_id: b_conn_id.clone(), + }, + version: "a-version".into(), + sequence: Sequence::default(), + }; + let mut commitments = Vec::new(); + handle_msg_channel_open_init( + a_conns.clone(), + a_conn_args, + a_conns_after_init.clone(), + a_conn_args, + a_channel_init.clone(), + a_channel_args, + &mut commitments, + ) + .unwrap(); + + let mut b_conns_after_try = b_conns.clone(); + b_conns_after_try.next_channel_number += 1; + let b_channel = IbcChannel { + state: State::OpenTry, + number: 1, + order: Ordering::Unordered, + port_id: b_channel_args.port_id_str(), + connection_hops: vec![b_conn_id.clone()], + counterparty: ChannelCounterparty { + channel_id: a_channel_args.channel_id_str(), + port_id: a_channel_args.port_id_str(), + connection_id: a_conn_id, + }, + version: "a-version".into(), + sequence: Sequence::default(), + }; + let mut try_commitments = Vec::new(); + handle_msg_channel_open_try( + client_with_commitments(commitments), + b_conns, + b_conn_args, + b_conns_after_try, + b_conn_args, + b_channel.clone(), + b_channel_args, + &mut try_commitments, + MsgChannelOpenTry { + proof_height: Height::default(), + proof_init: vec![], + }, + ) + .unwrap(); + + let mut a_channel_args_open = a_channel_args; + a_channel_args_open.open = true; + let mut a_channel_ack = a_channel_init.clone(); + a_channel_ack.state = State::Open; + a_channel_ack.counterparty.channel_id = b_channel_args.channel_id_str(); + let mut ack_commitments = Vec::new(); + handle_msg_channel_open_ack( + client_with_commitments(try_commitments), + a_channel_init, + a_channel_args, + a_channel_ack.clone(), + a_channel_args_open, + &mut ack_commitments, + MsgChannelOpenAck { + proof_height: Height::default(), + proof_try: vec![], + }, + ) + .unwrap(); + + let mut b_channel_args_open = b_channel_args; + b_channel_args_open.open = true; + let mut b_channel_confirm = b_channel.clone(); + b_channel_confirm.state = State::Open; + handle_msg_channel_open_confirm( + client_with_commitments(ack_commitments), + b_channel, + b_channel_args, + b_channel_confirm.clone(), + b_channel_args_open, + &mut Vec::new(), + MsgChannelOpenConfirm { + proof_height: Height::default(), + proof_ack: vec![], + }, + ) + .unwrap(); + + let packet = IbcPacket { + packet: Packet { + sequence: 1, + source_port_id: a_channel_args.port_id_str(), + source_channel_id: a_channel_args.channel_id_str(), + destination_port_id: b_channel_args.port_id_str(), + destination_channel_id: b_channel_args.channel_id_str(), + data: vec![73; 8], + timeout_height: 0, + timeout_timestamp: 0, + }, + status: PacketStatus::Send, + ack: None, + }; + let a_packet_args = PacketArgs { + channel_id: a_channel_args.channel_id, + port_id: a_channel_args.port_id, + sequence: 1, + }; + + let mut a_channel_sent = a_channel_ack.clone(); + a_channel_sent.sequence.next_sequence_sends += 1; + let mut send_commitments = Vec::new(); + handle_msg_send_packet( + a_channel_ack, + a_channel_args_open, + a_channel_sent.clone(), + a_channel_args_open, + packet.clone(), + a_packet_args, + &mut send_commitments, + ) + .unwrap(); + + let mut b_channel_recv = b_channel_confirm.clone(); + b_channel_recv.sequence.unorder_receive(1).unwrap(); + let mut b_packet = packet.clone(); + b_packet.status = PacketStatus::Recv; + let b_packet_args = PacketArgs { + channel_id: b_channel_args.channel_id, + port_id: b_channel_args.port_id, + sequence: 1, + }; + handle_msg_recv_packet( + client_with_commitments(send_commitments), + b_channel_confirm, + b_channel_args_open, + b_channel_recv.clone(), + b_channel_args_open, + None, + b_packet.clone(), + b_packet_args, + &mut Vec::new(), + MsgRecvPacket { + proof_height: Height::default(), + proof_commitment: vec![], + }, + ) + .unwrap(); + + let mut b_packet_ack = b_packet.clone(); + b_packet_ack.status = PacketStatus::WriteAck; + b_packet_ack.ack = Some("ack".into()); + + let mut ack_commitments = Vec::new(); + handle_msg_write_ack_packet( + b_channel_recv.clone(), + b_channel_args_open, + b_channel_recv.clone(), + b_channel_args_open, + b_packet, + b_packet_args, + b_packet_ack, + b_packet_args, + &mut ack_commitments, + ) + .unwrap(); + + let mut a_packet_acked = packet.clone(); + a_packet_acked.status = PacketStatus::Ack; + a_packet_acked.ack = Some("ack".into()); + let a_channel_acked = a_channel_sent.clone(); + handle_msg_ack_packet( + client_with_commitments(ack_commitments), + a_channel_sent, + a_channel_args_open, + a_channel_acked.clone(), + a_channel_args_open, + packet, + a_packet_args, + a_packet_acked, + a_packet_args, + &mut Vec::new(), + MsgAckPacket { + proof_height: Height::default(), + proof_acked: vec![], + }, + ) + .unwrap(); + + let mut a_channel_closed = a_channel_acked.clone(); + a_channel_closed.state = State::Closed; + let mut close_commitments = Vec::new(); + handle_msg_channel_close_init( + a_channel_acked.clone(), + a_channel_args_open, + a_channel_closed, + a_channel_args, + &mut close_commitments, + ) + .unwrap(); + + let mut b_channel_close = b_channel_recv.clone(); + b_channel_close.state = State::Closed; + handle_msg_channel_close_confirm( + client_with_commitments(close_commitments), + b_channel_recv, + b_channel_args_open, + b_channel_close, + b_channel_args, + &mut Vec::new(), + MsgChannelCloseConfirm { + proof_height: Height::default(), + proof_init: vec![], + }, + ) + .unwrap(); +} diff --git a/axon/src/lib.rs b/axon/src/lib.rs index d16b6ed..1209653 100644 --- a/axon/src/lib.rs +++ b/axon/src/lib.rs @@ -74,7 +74,7 @@ macro_rules! try_read_last { } // The args of the connection cell's script -#[derive(Debug, Default, PartialEq, Eq)] +#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)] pub struct ConnectionArgs { pub metadata_type_id: [u8; 32], pub ibc_handler_address: [u8; 20], @@ -98,7 +98,7 @@ impl ConnectionArgs { } // The args of the channel cell's script -#[derive(Debug, Default, PartialEq, Eq, Clone)] +#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)] pub struct ChannelArgs { pub metadata_type_id: [u8; 32], pub ibc_handler_address: [u8; 20], @@ -107,7 +107,7 @@ pub struct ChannelArgs { // frequently. pub open: bool, // Relayer will search the specified channel by channel id and port id - pub channel_id: u16, + pub channel_id: u64, pub port_id: [u8; 32], } @@ -124,11 +124,19 @@ impl ChannelArgs { metadata_type_id: *try_read!(slice, 32), ibc_handler_address: *try_read!(slice, 20), open: try_read!(slice, 1) != &[0], - channel_id: u16::from_le_bytes(*try_read!(slice, 2)), + channel_id: u64::from_le_bytes(*try_read!(slice, 8)), port_id: *try_read_last!(slice, 32), }) } + pub fn channel_id_str(&self) -> String { + format!("{CHANNEL_ID_PREFIX}{}", self.channel_id) + } + + pub fn port_id_str(&self) -> String { + hex::encode(self.port_id) + } + pub fn get_prefix_for_searching_unopen(&self) -> Vec { [ &self.metadata_type_id[..], @@ -163,25 +171,27 @@ impl ChannelArgs { } } -#[derive(Debug, Default, PartialEq, Eq)] +#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)] pub struct PacketArgs { - pub channel_id: u16, + pub channel_id: u64, pub port_id: [u8; 32], // mark as owner_lockhash - pub sequence: u16, + pub sequence: u64, } impl PacketArgs { - pub fn from_slice(slice: &[u8]) -> Result { - if slice.len() != 36 { - return Err(VerifyError::WrongPacketArgs); + pub fn is_channel(&self, channel: &ChannelArgs) -> Result<(), VerifyError> { + if channel.channel_id != self.channel_id || channel.port_id != self.port_id { + Err(VerifyError::WrongPacketArgs) + } else { + Ok(()) } - let channel_id = u16::from_le_bytes(slice[0..2].try_into().unwrap()); - let port_id = slice[2..34].try_into().unwrap(); - let sequence = u16::from_le_bytes(slice[34..36].try_into().unwrap()); - Ok(PacketArgs { - channel_id, - port_id, - sequence, + } + + pub fn from_slice(mut slice: &[u8]) -> Result { + Ok(Self { + channel_id: u64::from_le_bytes(*try_read!(slice, 8)), + port_id: *try_read!(slice, 32), + sequence: u64::from_le_bytes(*try_read_last!(slice, 8)), }) } @@ -213,8 +223,34 @@ pub fn connection_id(client_id: &str, connection_idx: usize) -> String { ) } -pub fn get_channel_id_str(idx: u16) -> String { - format!("{CHANNEL_ID_PREFIX}{}", idx) +pub trait WriteOrVerifyCommitments { + fn write_no_commitment(&mut self) -> Result<(), VerifyError> { + self.write_commitments::>([]) + } + + fn write_commitments( + &mut self, + kvs: impl IntoIterator, + ) -> Result<(), VerifyError> + where + K: AsRef<[u8]>, + V: AsRef<[u8]>; +} + +impl WriteOrVerifyCommitments for &mut T +where + T: WriteOrVerifyCommitments, +{ + fn write_commitments( + &mut self, + kvs: impl IntoIterator, + ) -> Result<(), VerifyError> + where + K: AsRef<[u8]>, + V: AsRef<[u8]>, + { + T::write_commitments(self, kvs) + } } #[cfg(test)] @@ -230,7 +266,7 @@ mod tests { channel_id: 23, port_id: [2; 32], }; - let slice = channel_args.clone().to_args(); + let slice = channel_args.to_args(); let actual = ChannelArgs::from_slice(&slice).unwrap(); assert_eq!(channel_args, actual); } diff --git a/axon/src/message.rs b/axon/src/message.rs index f785149..39b9664 100644 --- a/axon/src/message.rs +++ b/axon/src/message.rs @@ -1,20 +1,59 @@ -use crate::proto::client::Height; +use axon_tools::keccak_256; +use ethereum_types::H256; +use rlp_derive::RlpDecodable; +use rlp_derive::RlpEncodable; -/// These messages are used to send to CKB. We named some fields with the -/// suffix `a or b` according to Cosmos's convention. use super::object::*; use super::Vec; use super::U256; -// use axon_protocol::types::{Bytes, U256}; -use rlp_derive::RlpDecodable; -use rlp_derive::RlpEncodable; +use crate::proto::client::Height; +use crate::WriteOrVerifyCommitments; #[derive(RlpDecodable, RlpEncodable)] pub struct Envelope { pub msg_type: MsgType, + pub commitments: Vec, pub content: Vec, } +// Verify. +impl WriteOrVerifyCommitments for &[CommitmentKV] { + fn write_commitments( + &mut self, + kvs: impl IntoIterator, + ) -> Result<(), VerifyError> + where + K: AsRef<[u8]>, + V: AsRef<[u8]>, + { + let mut expected: Vec = Vec::new(); + expected.write_commitments(kvs)?; + if **self == expected { + Ok(()) + } else { + Err(VerifyError::Commitment) + } + } +} + +// Write. +impl WriteOrVerifyCommitments for Vec { + fn write_commitments( + &mut self, + kvs: impl IntoIterator, + ) -> Result<(), VerifyError> + where + K: AsRef<[u8]>, + V: AsRef<[u8]>, + { + *self = kvs + .into_iter() + .map(|(k, v)| CommitmentKV::hash(k, v)) + .collect(); + Ok(()) + } +} + impl_enum_rlp!( #[repr(u8)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -207,3 +246,15 @@ pub struct MsgTimeoutPacket { // in Business side to be consumed to obtain its capacity #[derive(RlpDecodable, RlpEncodable)] pub struct MsgConsumeAckPacket {} + +#[derive(RlpDecodable, RlpEncodable, PartialEq, Eq, Default)] +pub struct CommitmentKV(pub H256, pub H256); + +impl CommitmentKV { + pub fn hash(path: impl AsRef<[u8]>, value: impl AsRef<[u8]>) -> Self { + Self( + keccak_256(path.as_ref()).into(), + keccak_256(value.as_ref()).into(), + ) + } +} diff --git a/axon/src/object.rs b/axon/src/object.rs index 32447ab..1c175c3 100644 --- a/axon/src/object.rs +++ b/axon/src/object.rs @@ -1,7 +1,7 @@ use crate::consts::COMMITMENT_PREFIX; -use crate::get_channel_id_str; use crate::proto; use crate::Bytes; +use crate::ChannelArgs; use alloc::borrow::ToOwned; use alloc::string::String; use alloc::string::ToString; @@ -46,6 +46,7 @@ pub enum VerifyError { WrongPacketArgs, WrongPacketAck, + Commitment = 98, Mpt = 99, } @@ -71,11 +72,31 @@ impl_enum_rlp!( OpenTry, Open, Closed, - Frozen, }, u8 ); +impl State { + pub fn proto_connection_state(self) -> proto::connection::State { + match self { + State::Init => proto::connection::State::Init, + State::OpenTry => proto::connection::State::Tryopen, + State::Open => proto::connection::State::Open, + _ => proto::connection::State::UninitializedUnspecified, + } + } + + pub fn proto_channel_state(self) -> proto::channel::State { + match self { + State::Init => proto::channel::State::Init, + State::OpenTry => proto::channel::State::Tryopen, + State::Open => proto::channel::State::Open, + State::Closed => proto::channel::State::Closed, + _ => proto::channel::State::UninitializedUnspecified, + } + } +} + impl_enum_rlp!( #[derive(Debug, PartialEq, Eq, Default, Clone, Copy)] #[repr(u8)] @@ -124,7 +145,7 @@ pub struct ChannelCounterparty { #[derive(Clone, PartialEq, Eq, RlpEncodable, RlpDecodable, Debug)] pub struct Packet { - pub sequence: u16, + pub sequence: u64, pub source_port_id: String, pub source_channel_id: String, pub destination_port_id: String, @@ -138,10 +159,10 @@ impl Default for Packet { fn default() -> Self { Self { sequence: Default::default(), - source_port_id: hex::encode([0u8; 32]), - source_channel_id: get_channel_id_str(0), - destination_port_id: hex::encode([0u8; 32]), - destination_channel_id: get_channel_id_str(0), + source_port_id: ChannelArgs::default().port_id_str(), + source_channel_id: ChannelArgs::default().channel_id_str(), + destination_port_id: ChannelArgs::default().port_id_str(), + destination_channel_id: ChannelArgs::default().channel_id_str(), data: Default::default(), timeout_height: 0, timeout_timestamp: 0, @@ -191,3 +212,21 @@ impl Default for ConnectionEnd { } } } + +impl ConnectionEnd { + pub fn to_proto(self, client_id: String) -> proto::connection::ConnectionEnd { + proto::connection::ConnectionEnd { + state: self.state.proto_connection_state() as i32, + counterparty: Some(proto::connection::Counterparty { + client_id: self.counterparty.client_id, + connection_id: self.counterparty.connection_id, + prefix: Some(proto::commitment::MerklePrefix { + key_prefix: self.counterparty.commitment_prefix, + }), + }), + client_id, + versions: self.versions.into_iter().map(|v| v.into()).collect(), + delay_period: self.delay_period, + } + } +}