Skip to content

Commit 145d3f2

Browse files
authored
Don't require ICS20 module to implement Channel{Reader,Keeper} (#244)
* Add SendPacketReader trait with blanket impl for all types implementing ChannelReader * Have SendPacket handler depend on SendPacketReader and return SendPacketResult * Define Ics20ChannelKeeper and depend on that instead of Channel{Reader,Keeper} * Update tests * Add blanket impl for Ics20ChannelKeeper * Add changelog entry * Use where clause for trait bounds * Avoid trait object param in send_packet handler * Apply suggestion to merge Ics20ChannelKeeper into Ics20Keeper * Rename Ics20Keeper -> TokenTransferKeeper * Rename Ics20Reader -> TokenTransferReader
1 parent 450fcae commit 145d3f2

File tree

6 files changed

+170
-192
lines changed

6 files changed

+170
-192
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- `Ics20Context` no longer requires types implementing it to implement `ChannelReader` and `ChannelKeeper`, and instead depends on the `Ics20ChannelKeeper`
2+
and `SendPacketReader` traits. Additionally, the `send_packet` handler now requires the calling context to implement `SendPacketReader` and returns
3+
a `SendPacketResult`.
4+
([#182](https://github.com/cosmos/ibc-rs/issues/182))

crates/ibc/src/applications/transfer/context.rs

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,53 @@ use crate::applications::transfer::relay::on_recv_packet::process_recv_packet;
99
use crate::applications::transfer::relay::on_timeout_packet::process_timeout_packet;
1010
use crate::applications::transfer::{PrefixedCoin, PrefixedDenom, VERSION};
1111
use crate::core::ics04_channel::channel::{Counterparty, Order};
12-
use crate::core::ics04_channel::context::{ChannelKeeper, ChannelReader};
12+
use crate::core::ics04_channel::commitment::PacketCommitment;
13+
use crate::core::ics04_channel::context::{ChannelKeeper, SendPacketReader};
14+
use crate::core::ics04_channel::error::Error as Ics04Error;
15+
use crate::core::ics04_channel::handler::send_packet::SendPacketResult;
1316
use crate::core::ics04_channel::handler::ModuleExtras;
1417
use crate::core::ics04_channel::msgs::acknowledgement::Acknowledgement as GenericAcknowledgement;
15-
use crate::core::ics04_channel::packet::Packet;
18+
use crate::core::ics04_channel::packet::{Packet, Sequence};
1619
use crate::core::ics04_channel::Version;
1720
use crate::core::ics24_host::identifier::{ChannelId, ConnectionId, PortId};
1821
use crate::core::ics26_routing::context::{ModuleOutputBuilder, OnRecvPacketAck};
1922
use crate::prelude::*;
2023
use crate::signer::Signer;
2124

22-
pub trait Ics20Keeper:
23-
ChannelKeeper + BankKeeper<AccountId = <Self as Ics20Keeper>::AccountId>
24-
{
25-
type AccountId;
25+
pub trait TokenTransferKeeper: BankKeeper {
26+
fn store_send_packet_result(&mut self, result: SendPacketResult) -> Result<(), Ics04Error> {
27+
self.store_next_sequence_send(
28+
result.port_id.clone(),
29+
result.channel_id.clone(),
30+
result.seq_number,
31+
)?;
32+
33+
self.store_packet_commitment(
34+
result.port_id,
35+
result.channel_id,
36+
result.seq,
37+
result.commitment,
38+
)?;
39+
Ok(())
40+
}
41+
42+
fn store_packet_commitment(
43+
&mut self,
44+
port_id: PortId,
45+
channel_id: ChannelId,
46+
sequence: Sequence,
47+
commitment: PacketCommitment,
48+
) -> Result<(), Ics04Error>;
49+
50+
fn store_next_sequence_send(
51+
&mut self,
52+
port_id: PortId,
53+
channel_id: ChannelId,
54+
seq: Sequence,
55+
) -> Result<(), Ics04Error>;
2656
}
2757

28-
pub trait Ics20Reader: ChannelReader {
58+
pub trait TokenTransferReader: SendPacketReader {
2959
type AccountId: TryFrom<Signer>;
3060

3161
/// get_port returns the portID for the transfer module.
@@ -36,7 +66,7 @@ pub trait Ics20Reader: ChannelReader {
3666
&self,
3767
port_id: &PortId,
3868
channel_id: &ChannelId,
39-
) -> Result<<Self as Ics20Reader>::AccountId, Ics20Error>;
69+
) -> Result<<Self as TokenTransferReader>::AccountId, Ics20Error>;
4070

4171
/// Returns true iff send is enabled.
4272
fn is_send_enabled(&self) -> bool;
@@ -51,6 +81,30 @@ pub trait Ics20Reader: ChannelReader {
5181
}
5282
}
5383

84+
impl<T> TokenTransferKeeper for T
85+
where
86+
T: ChannelKeeper + BankKeeper,
87+
{
88+
fn store_packet_commitment(
89+
&mut self,
90+
port_id: PortId,
91+
channel_id: ChannelId,
92+
sequence: Sequence,
93+
commitment: PacketCommitment,
94+
) -> Result<(), Ics04Error> {
95+
ChannelKeeper::store_packet_commitment(self, port_id, channel_id, sequence, commitment)
96+
}
97+
98+
fn store_next_sequence_send(
99+
&mut self,
100+
port_id: PortId,
101+
channel_id: ChannelId,
102+
seq: Sequence,
103+
) -> Result<(), Ics04Error> {
104+
ChannelKeeper::store_next_sequence_send(self, port_id, channel_id, seq)
105+
}
106+
}
107+
54108
// https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md
55109
pub fn cosmos_adr028_escrow_address(port_id: &PortId, channel_id: &ChannelId) -> Vec<u8> {
56110
let contents = format!("{}/{}", port_id, channel_id);
@@ -94,8 +148,8 @@ pub trait BankKeeper {
94148
/// Captures all the dependencies which the ICS20 module requires to be able to dispatch and
95149
/// process IBC messages.
96150
pub trait Ics20Context:
97-
Ics20Keeper<AccountId = <Self as Ics20Context>::AccountId>
98-
+ Ics20Reader<AccountId = <Self as Ics20Context>::AccountId>
151+
TokenTransferKeeper<AccountId = <Self as Ics20Context>::AccountId>
152+
+ TokenTransferReader<AccountId = <Self as Ics20Context>::AccountId>
99153
{
100154
type AccountId: TryFrom<Signer>;
101155
}
@@ -197,7 +251,7 @@ pub fn on_recv_packet<Ctx: 'static + Ics20Context>(
197251
Err(_) => {
198252
return OnRecvPacketAck::Failed(Box::new(Acknowledgement::Error(
199253
Ics20Error::packet_data_deserialization().to_string(),
200-
)))
254+
)));
201255
}
202256
};
203257

crates/ibc/src/applications/transfer/relay/send_transfer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ where
9494
events,
9595
} = send_packet(ctx, packet).map_err(Error::ics04_channel)?;
9696

97-
ctx.store_packet_result(result)
97+
ctx.store_send_packet_result(result)
9898
.map_err(Error::ics04_channel)?;
9999

100100
output.merge_output(

crates/ibc/src/core/ics04_channel/context.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,89 @@ pub trait ChannelReader {
150150
}
151151
}
152152

153+
pub trait SendPacketReader {
154+
/// Returns the ChannelEnd for the given `port_id` and `chan_id`.
155+
fn channel_end(&self, port_id: &PortId, channel_id: &ChannelId) -> Result<ChannelEnd, Error>;
156+
157+
/// Returns the ConnectionState for the given identifier `connection_id`.
158+
fn connection_end(&self, connection_id: &ConnectionId) -> Result<ConnectionEnd, Error>;
159+
160+
/// Returns the ClientState for the given identifier `client_id`. Necessary dependency towards
161+
/// proof verification.
162+
fn client_state(&self, client_id: &ClientId) -> Result<Box<dyn ClientState>, Error>;
163+
164+
fn client_consensus_state(
165+
&self,
166+
client_id: &ClientId,
167+
height: Height,
168+
) -> Result<Box<dyn ConsensusState>, Error>;
169+
170+
fn get_next_sequence_send(
171+
&self,
172+
port_id: &PortId,
173+
channel_id: &ChannelId,
174+
) -> Result<Sequence, Error>;
175+
176+
fn hash(&self, value: Vec<u8>) -> Vec<u8>;
177+
178+
fn packet_commitment(
179+
&self,
180+
packet_data: Vec<u8>,
181+
timeout_height: TimeoutHeight,
182+
timeout_timestamp: Timestamp,
183+
) -> PacketCommitment {
184+
let mut hash_input = timeout_timestamp.nanoseconds().to_be_bytes().to_vec();
185+
186+
let revision_number = timeout_height.commitment_revision_number().to_be_bytes();
187+
hash_input.append(&mut revision_number.to_vec());
188+
189+
let revision_height = timeout_height.commitment_revision_height().to_be_bytes();
190+
hash_input.append(&mut revision_height.to_vec());
191+
192+
let packet_data_hash = self.hash(packet_data);
193+
hash_input.append(&mut packet_data_hash.to_vec());
194+
195+
self.hash(hash_input).into()
196+
}
197+
}
198+
199+
impl<T> SendPacketReader for T
200+
where
201+
T: ChannelReader,
202+
{
203+
fn channel_end(&self, port_id: &PortId, channel_id: &ChannelId) -> Result<ChannelEnd, Error> {
204+
ChannelReader::channel_end(self, port_id, channel_id)
205+
}
206+
207+
fn connection_end(&self, connection_id: &ConnectionId) -> Result<ConnectionEnd, Error> {
208+
ChannelReader::connection_end(self, connection_id)
209+
}
210+
211+
fn client_state(&self, client_id: &ClientId) -> Result<Box<dyn ClientState>, Error> {
212+
ChannelReader::client_state(self, client_id)
213+
}
214+
215+
fn client_consensus_state(
216+
&self,
217+
client_id: &ClientId,
218+
height: Height,
219+
) -> Result<Box<dyn ConsensusState>, Error> {
220+
ChannelReader::client_consensus_state(self, client_id, height)
221+
}
222+
223+
fn get_next_sequence_send(
224+
&self,
225+
port_id: &PortId,
226+
channel_id: &ChannelId,
227+
) -> Result<Sequence, Error> {
228+
ChannelReader::get_next_sequence_send(self, port_id, channel_id)
229+
}
230+
231+
fn hash(&self, value: Vec<u8>) -> Vec<u8> {
232+
ChannelReader::hash(self, value)
233+
}
234+
}
235+
153236
/// A context supplying all the necessary write-only dependencies (i.e., storage writing facility)
154237
/// for processing any `ChannelMsg`.
155238
pub trait ChannelKeeper {

crates/ibc/src/core/ics04_channel/handler/send_packet.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use crate::core::ics04_channel::channel::Counterparty;
22
use crate::core::ics04_channel::channel::State;
33
use crate::core::ics04_channel::commitment::PacketCommitment;
44
use crate::core::ics04_channel::events::SendPacket;
5-
use crate::core::ics04_channel::packet::{PacketResult, Sequence};
6-
use crate::core::ics04_channel::{context::ChannelReader, error::Error, packet::Packet};
5+
use crate::core::ics04_channel::packet::Sequence;
6+
use crate::core::ics04_channel::{context::SendPacketReader, error::Error, packet::Packet};
77
use crate::core::ics24_host::identifier::{ChannelId, PortId};
88
use crate::events::IbcEvent;
99
use crate::handler::{HandlerOutput, HandlerResult};
@@ -19,7 +19,10 @@ pub struct SendPacketResult {
1919
pub commitment: PacketCommitment,
2020
}
2121

22-
pub fn send_packet(ctx: &dyn ChannelReader, packet: Packet) -> HandlerResult<PacketResult, Error> {
22+
pub fn send_packet(
23+
ctx: &impl SendPacketReader,
24+
packet: Packet,
25+
) -> HandlerResult<SendPacketResult, Error> {
2326
let mut output = HandlerOutput::builder();
2427

2528
let source_channel_end = ctx.channel_end(&packet.source_port, &packet.source_channel)?;
@@ -78,7 +81,7 @@ pub fn send_packet(ctx: &dyn ChannelReader, packet: Packet) -> HandlerResult<Pac
7881

7982
output.log("success: packet send ");
8083

81-
let result = PacketResult::Send(SendPacketResult {
84+
let result = SendPacketResult {
8285
port_id: packet.source_port.clone(),
8386
channel_id: packet.source_channel.clone(),
8487
seq: packet.sequence,
@@ -88,7 +91,7 @@ pub fn send_packet(ctx: &dyn ChannelReader, packet: Packet) -> HandlerResult<Pac
8891
packet.timeout_height,
8992
packet.timeout_timestamp,
9093
),
91-
});
94+
};
9295

9396
output.emit(IbcEvent::SendPacket(SendPacket::new(
9497
packet,

0 commit comments

Comments
 (0)