Skip to content

Commit e38f652

Browse files
authored
Merge pull request #2474 from CosmWasm/aw/ibcv2-ack-recv
Introduce API for IBCv2 Acknowledge Receive
2 parents 7689ea4 + e4d2dbc commit e38f652

File tree

16 files changed

+218
-14
lines changed

16 files changed

+218
-14
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,7 @@ jobs:
12541254
name: Run tests with coverage
12551255
command: |
12561256
# Generate full coverage report
1257-
cargo llvm-cov nextest --lcov --output-path lcov.info
1257+
cargo llvm-cov nextest --all-features --lcov --output-path lcov.info
12581258
12591259
# List of package directories and their flags
12601260
# ToDo: Re-add "core:cosmwasm-core" when enabling core coverage again

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"rust-analyzer.cargo.features": [
3+
"ibc2",
34
"stargate",
45
"staking",
56
"cosmwasm_2_1"

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ and this project adheres to
2727
- cosmwasm-std: Add `cosmwasm_std::testing::Envs`, which is an `Env` factory for
2828
testing environments. It auto-increments block heights and timestamps. It
2929
allows for advanced configurations such as custom address prefixes. ([#2442])
30+
- cosmwasm-vm: Add support for `ibc2_packet_ack` endpoint ([#2474])
31+
- cosmwasm-std: Add support for `ibc2_packet_ack` endpoint ([#2474])
3032

3133
## Changed
3234

contracts/ibc2/schema/ibc2.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,18 @@
3737
"title": "State",
3838
"type": "object",
3939
"required": [
40+
"ibc2_packet_ack_counter",
4041
"ibc2_packet_receive_counter",
4142
"ibc2_packet_timeout_counter",
4243
"last_packet_seq",
4344
"last_source_client"
4445
],
4546
"properties": {
47+
"ibc2_packet_ack_counter": {
48+
"type": "integer",
49+
"format": "uint32",
50+
"minimum": 0.0
51+
},
4652
"ibc2_packet_receive_counter": {
4753
"type": "integer",
4854
"format": "uint32",

contracts/ibc2/schema/raw/response_to_query_state.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@
33
"title": "State",
44
"type": "object",
55
"required": [
6+
"ibc2_packet_ack_counter",
67
"ibc2_packet_receive_counter",
78
"ibc2_packet_timeout_counter",
89
"last_packet_seq",
910
"last_source_client"
1011
],
1112
"properties": {
13+
"ibc2_packet_ack_counter": {
14+
"type": "integer",
15+
"format": "uint32",
16+
"minimum": 0.0
17+
},
1218
"ibc2_packet_receive_counter": {
1319
"type": "integer",
1420
"format": "uint32",

contracts/ibc2/src/contract.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use cosmwasm_std::{
22
entry_point, from_json, to_json_vec, Binary, Deps, DepsMut, Empty, Env, Ibc2Msg,
3-
Ibc2PacketReceiveMsg, Ibc2PacketTimeoutMsg, Ibc2Payload, IbcAcknowledgement, IbcBasicResponse,
4-
IbcReceiveResponse, MessageInfo, QueryResponse, Response, StdAck, StdError, StdResult,
3+
Ibc2PacketAckMsg, Ibc2PacketReceiveMsg, Ibc2PacketTimeoutMsg, Ibc2Payload, IbcAcknowledgement,
4+
IbcBasicResponse, IbcReceiveResponse, MessageInfo, QueryResponse, Response, StdAck, StdError,
5+
StdResult,
56
};
67

78
use crate::msg::{IbcPayload, QueryMsg};
@@ -17,6 +18,7 @@ pub fn instantiate(
1718
deps.storage.set(
1819
STATE_KEY,
1920
&to_json_vec(&State {
21+
ibc2_packet_ack_counter: 0,
2022
ibc2_packet_receive_counter: 0,
2123
ibc2_packet_timeout_counter: 0,
2224
last_source_client: "".to_owned(),
@@ -40,6 +42,29 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<QueryResponse> {
4042
}
4143
}
4244

45+
#[entry_point]
46+
pub fn ibc2_packet_ack(
47+
deps: DepsMut,
48+
_env: Env,
49+
_msg: Ibc2PacketAckMsg,
50+
) -> StdResult<IbcBasicResponse> {
51+
let data = deps
52+
.storage
53+
.get(STATE_KEY)
54+
.ok_or_else(|| StdError::generic_err("State not found."))?;
55+
let state: State = from_json(data)?;
56+
57+
deps.storage.set(
58+
STATE_KEY,
59+
&to_json_vec(&State {
60+
ibc2_packet_ack_counter: state.ibc2_packet_ack_counter + 1,
61+
..state
62+
})?,
63+
);
64+
65+
Ok(IbcBasicResponse::default())
66+
}
67+
4368
#[entry_point]
4469
pub fn ibc2_packet_receive(
4570
deps: DepsMut,

contracts/ibc2/src/state.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};
33

44
#[derive(Default, Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
55
pub struct State {
6+
pub ibc2_packet_ack_counter: u32,
67
pub ibc2_packet_receive_counter: u32,
78
pub ibc2_packet_timeout_counter: u32,
89
pub last_source_client: String,

packages/std/src/exports/exports.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::ibc::{
2626
};
2727
use crate::ibc::{IbcChannelOpenMsg, IbcChannelOpenResponse};
2828
#[cfg(feature = "ibc2")]
29-
use crate::ibc2::{Ibc2PacketReceiveMsg, Ibc2PacketTimeoutMsg};
29+
use crate::ibc2::{Ibc2PacketAckMsg, Ibc2PacketReceiveMsg, Ibc2PacketTimeoutMsg};
3030
use crate::query::CustomQuery;
3131
use crate::results::{ContractResult, QueryResponse, Reply, Response};
3232
use crate::serde::{from_json, to_json_vec};
@@ -525,6 +525,35 @@ where
525525
Region::from_vec(v).to_heap_ptr() as u32
526526
}
527527

528+
/// do_ibc2_packet_ack is designed for use with #[entry_point] to make a "C" extern
529+
///
530+
/// contract_fn is called when this chain receives an Ibc2 acknowledge payload on port belonging
531+
/// to this contract
532+
///
533+
/// - `Q`: custom query type (see QueryRequest)
534+
/// - `C`: custom response message type (see CosmosMsg)
535+
/// - `E`: error type for responses
536+
#[cfg(feature = "ibc2")]
537+
pub fn do_ibc2_packet_ack<Q, C, E>(
538+
contract_fn: &dyn Fn(DepsMut<Q>, Env, Ibc2PacketAckMsg) -> Result<IbcBasicResponse<C>, E>,
539+
env_ptr: u32,
540+
msg_ptr: u32,
541+
) -> u32
542+
where
543+
Q: CustomQuery,
544+
C: CustomMsg,
545+
E: ToString,
546+
{
547+
install_panic_handler();
548+
let res = _do_ibc2_packet_ack(
549+
contract_fn,
550+
env_ptr as *mut Region<Owned>,
551+
msg_ptr as *mut Region<Owned>,
552+
);
553+
let v = to_json_vec(&res).unwrap();
554+
Region::from_vec(v).to_heap_ptr() as u32
555+
}
556+
528557
/// do_ibc2_packet_receive is designed for use with #[entry_point] to make a "C" extern
529558
///
530559
/// contract_fn is called when this chain receives an Ibc2 payload on port belonging
@@ -938,6 +967,29 @@ where
938967
contract_fn(deps.as_mut(), env, msg).into()
939968
}
940969

970+
#[cfg(feature = "ibc2")]
971+
fn _do_ibc2_packet_ack<Q, C, E>(
972+
contract_fn: &dyn Fn(DepsMut<Q>, Env, Ibc2PacketAckMsg) -> Result<IbcBasicResponse<C>, E>,
973+
env_ptr: *mut Region<Owned>,
974+
msg_ptr: *mut Region<Owned>,
975+
) -> ContractResult<IbcBasicResponse<C>>
976+
where
977+
Q: CustomQuery,
978+
C: CustomMsg,
979+
E: ToString,
980+
{
981+
let env: Vec<u8> =
982+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
983+
let msg: Vec<u8> =
984+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
985+
986+
let env: Env = try_into_contract_result!(from_json(env));
987+
let msg: Ibc2PacketAckMsg = try_into_contract_result!(from_json(msg));
988+
989+
let mut deps = deps_from_imports();
990+
contract_fn(deps.as_mut(), env, msg).into()
991+
}
992+
941993
#[cfg(feature = "ibc2")]
942994
fn _do_ibc2_packet_receive<Q, C, E>(
943995
contract_fn: &dyn Fn(DepsMut<Q>, Env, Ibc2PacketReceiveMsg) -> Result<IbcReceiveResponse<C>, E>,

packages/std/src/exports/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub use exports::{
1010
do_query, do_reply, do_sudo,
1111
};
1212
#[cfg(feature = "ibc2")]
13-
pub use exports::{do_ibc2_packet_receive, do_ibc2_packet_timeout};
13+
pub use exports::{do_ibc2_packet_ack, do_ibc2_packet_receive, do_ibc2_packet_timeout};
1414
#[cfg(feature = "stargate")]
1515
pub use exports::{
1616
do_ibc_channel_close, do_ibc_channel_connect, do_ibc_channel_open, do_ibc_packet_ack,

packages/std/src/ibc2.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,35 @@ impl Ibc2PacketTimeoutMsg {
132132
}
133133
}
134134

135+
/// Message sent to the IBCv2 app upon receiving an acknowledgement packet
136+
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
137+
#[non_exhaustive]
138+
pub struct Ibc2PacketAckMsg {
139+
pub source_client: String,
140+
pub destination_client: String,
141+
pub data: Ibc2Payload,
142+
pub acknowledgement: Vec<u8>,
143+
pub relayer: Addr,
144+
}
145+
146+
impl Ibc2PacketAckMsg {
147+
pub fn new(
148+
source_client: String,
149+
destination_client: String,
150+
data: Ibc2Payload,
151+
acknowledgement: Vec<u8>,
152+
relayer: Addr,
153+
) -> Self {
154+
Self {
155+
source_client,
156+
destination_client,
157+
data,
158+
acknowledgement,
159+
relayer,
160+
}
161+
}
162+
}
163+
135164
#[cfg(test)]
136165
mod tests {
137166
use serde_json::to_string;

0 commit comments

Comments
 (0)