Skip to content

Commit 81c6ab8

Browse files
authored
Merge pull request #2130 from CosmWasm/chipshort/async-ack
Async Acknowledgement
2 parents 6416b95 + e1be535 commit 81c6ab8

File tree

12 files changed

+288
-17
lines changed

12 files changed

+288
-17
lines changed

.circleci/config.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,8 +695,10 @@ jobs:
695695
- restore_cache:
696696
keys:
697697
- cargocache-v2-contract_ibc_reflect-rust:1.74-{{ checksum "Cargo.lock" }}
698+
# TODO: Enable this once 2.1 has been released to crates.io
698699
- check_contract:
699-
min_version: "2.0"
700+
min_version: "2.1"
701+
skip_cosmwasm_check: true
700702
- save_cache:
701703
paths:
702704
- /usr/local/cargo/registry

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ and this project adheres to
5454
- cosmwasm-std: Add `TransferMsgBuilder` to more easily create an
5555
`IbcMsg::Transfer` with different kinds of memo values, including IBC
5656
Callbacks memo values. ([#2167])
57+
- cosmwasm-std: Add `IbcMsg::WriteAcknowledgement` for async IBC
58+
acknowledgements ([#2130])
5759

5860
[#1983]: https://github.com/CosmWasm/cosmwasm/pull/1983
5961
[#2025]: https://github.com/CosmWasm/cosmwasm/pull/2025
@@ -69,6 +71,7 @@ and this project adheres to
6971
[#2120]: https://github.com/CosmWasm/cosmwasm/pull/2120
7072
[#2124]: https://github.com/CosmWasm/cosmwasm/pull/2124
7173
[#2129]: https://github.com/CosmWasm/cosmwasm/pull/2129
74+
[#2130]: https://github.com/CosmWasm/cosmwasm/pull/2130
7275
[#2166]: https://github.com/CosmWasm/cosmwasm/pull/2166
7376
[#2167]: https://github.com/CosmWasm/cosmwasm/pull/2167
7477

contracts/ibc-reflect/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ cranelift = ["cosmwasm-vm/cranelift"]
3030

3131
[dependencies]
3232
cosmwasm-schema = { path = "../../packages/schema" }
33-
cosmwasm-std = { path = "../../packages/std", features = ["iterator", "stargate", "cosmwasm_2_0"] }
33+
cosmwasm-std = { path = "../../packages/std", features = ["iterator", "stargate", "cosmwasm_2_1"] }
3434
schemars = "0.8.12"
3535
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
3636

contracts/ibc-reflect/schema/ibc-reflect.json

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,74 @@
1919
},
2020
"additionalProperties": false
2121
},
22-
"execute": null,
22+
"execute": {
23+
"$schema": "http://json-schema.org/draft-07/schema#",
24+
"title": "ExecuteMsg",
25+
"oneOf": [
26+
{
27+
"type": "object",
28+
"required": [
29+
"async_ack"
30+
],
31+
"properties": {
32+
"async_ack": {
33+
"type": "object",
34+
"required": [
35+
"ack",
36+
"channel_id",
37+
"packet_sequence"
38+
],
39+
"properties": {
40+
"ack": {
41+
"description": "The acknowledgement to send back",
42+
"allOf": [
43+
{
44+
"$ref": "#/definitions/IbcAcknowledgement"
45+
}
46+
]
47+
},
48+
"channel_id": {
49+
"description": "Existing channel where the packet was received",
50+
"type": "string"
51+
},
52+
"packet_sequence": {
53+
"description": "Sequence number of the packet that was received",
54+
"allOf": [
55+
{
56+
"$ref": "#/definitions/Uint64"
57+
}
58+
]
59+
}
60+
},
61+
"additionalProperties": false
62+
}
63+
},
64+
"additionalProperties": false
65+
}
66+
],
67+
"definitions": {
68+
"Binary": {
69+
"description": "Binary is a wrapper around Vec<u8> to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec<u8>. See also <https://github.com/CosmWasm/cosmwasm/blob/main/docs/MESSAGE_TYPES.md>.",
70+
"type": "string"
71+
},
72+
"IbcAcknowledgement": {
73+
"type": "object",
74+
"required": [
75+
"data"
76+
],
77+
"properties": {
78+
"data": {
79+
"$ref": "#/definitions/Binary"
80+
}
81+
},
82+
"additionalProperties": false
83+
},
84+
"Uint64": {
85+
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
86+
"type": "string"
87+
}
88+
}
89+
},
2390
"query": {
2491
"$schema": "http://json-schema.org/draft-07/schema#",
2592
"title": "QueryMsg",

contracts/ibc-reflect/schema/ibc/packet_msg.json

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,19 @@
109109
}
110110
},
111111
"additionalProperties": false
112+
},
113+
{
114+
"type": "object",
115+
"required": [
116+
"no_ack"
117+
],
118+
"properties": {
119+
"no_ack": {
120+
"type": "object",
121+
"additionalProperties": false
122+
}
123+
},
124+
"additionalProperties": false
112125
}
113126
],
114127
"definitions": {
@@ -390,6 +403,18 @@
390403
}
391404
]
392405
},
406+
"IbcAcknowledgement": {
407+
"type": "object",
408+
"required": [
409+
"data"
410+
],
411+
"properties": {
412+
"data": {
413+
"$ref": "#/definitions/Binary"
414+
}
415+
},
416+
"additionalProperties": false
417+
},
393418
"IbcMsg": {
394419
"description": "These are messages in the IBC lifecycle. Only usable by IBC-enabled contracts (contracts that directly speak the IBC protocol via 6 entry points)",
395420
"oneOf": [
@@ -481,6 +506,45 @@
481506
},
482507
"additionalProperties": false
483508
},
509+
{
510+
"description": "Acknowledges a packet that this contract received over IBC. This allows acknowledging a packet that was not acknowledged yet in the `ibc_packet_receive` call.",
511+
"type": "object",
512+
"required": [
513+
"write_acknowledgement"
514+
],
515+
"properties": {
516+
"write_acknowledgement": {
517+
"type": "object",
518+
"required": [
519+
"ack",
520+
"channel_id",
521+
"packet_sequence"
522+
],
523+
"properties": {
524+
"ack": {
525+
"description": "The acknowledgement to send back",
526+
"allOf": [
527+
{
528+
"$ref": "#/definitions/IbcAcknowledgement"
529+
}
530+
]
531+
},
532+
"channel_id": {
533+
"description": "Existing channel where the packet was received",
534+
"type": "string"
535+
},
536+
"packet_sequence": {
537+
"description": "Sequence number of the packet that was received",
538+
"type": "integer",
539+
"format": "uint64",
540+
"minimum": 0.0
541+
}
542+
},
543+
"additionalProperties": false
544+
}
545+
},
546+
"additionalProperties": false
547+
},
484548
{
485549
"description": "This will close an existing channel that is owned by this contract. Port is auto-assigned to the contract's IBC port",
486550
"type": "object",
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"title": "ExecuteMsg",
4+
"oneOf": [
5+
{
6+
"type": "object",
7+
"required": [
8+
"async_ack"
9+
],
10+
"properties": {
11+
"async_ack": {
12+
"type": "object",
13+
"required": [
14+
"ack",
15+
"channel_id",
16+
"packet_sequence"
17+
],
18+
"properties": {
19+
"ack": {
20+
"description": "The acknowledgement to send back",
21+
"allOf": [
22+
{
23+
"$ref": "#/definitions/IbcAcknowledgement"
24+
}
25+
]
26+
},
27+
"channel_id": {
28+
"description": "Existing channel where the packet was received",
29+
"type": "string"
30+
},
31+
"packet_sequence": {
32+
"description": "Sequence number of the packet that was received",
33+
"allOf": [
34+
{
35+
"$ref": "#/definitions/Uint64"
36+
}
37+
]
38+
}
39+
},
40+
"additionalProperties": false
41+
}
42+
},
43+
"additionalProperties": false
44+
}
45+
],
46+
"definitions": {
47+
"Binary": {
48+
"description": "Binary is a wrapper around Vec<u8> to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec<u8>. See also <https://github.com/CosmWasm/cosmwasm/blob/main/docs/MESSAGE_TYPES.md>.",
49+
"type": "string"
50+
},
51+
"IbcAcknowledgement": {
52+
"type": "object",
53+
"required": [
54+
"data"
55+
],
56+
"properties": {
57+
"data": {
58+
"$ref": "#/definitions/Binary"
59+
}
60+
},
61+
"additionalProperties": false
62+
},
63+
"Uint64": {
64+
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
65+
"type": "string"
66+
}
67+
}
68+
}

contracts/ibc-reflect/src/bin/schema.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ use cosmwasm_schema::{export_schema, export_schema_with_title, schema_for, write
44
use cosmwasm_std::Empty;
55

66
use ibc_reflect::msg::{
7-
AcknowledgementMsg, BalancesResponse, DispatchResponse, InstantiateMsg, PacketMsg, QueryMsg,
8-
WhoAmIResponse,
7+
AcknowledgementMsg, BalancesResponse, DispatchResponse, ExecuteMsg, InstantiateMsg, PacketMsg,
8+
QueryMsg, WhoAmIResponse,
99
};
1010

1111
fn main() {
1212
// Clear & write standard API
1313
write_api! {
1414
instantiate: InstantiateMsg,
15+
execute: ExecuteMsg,
1516
query: QueryMsg,
1617
migrate: Empty,
1718
}

contracts/ibc-reflect/src/contract.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
use cosmwasm_std::{
22
entry_point, from_json, to_json_binary, wasm_execute, BankMsg, Binary, CosmosMsg, Deps,
3-
DepsMut, Empty, Env, Event, Ibc3ChannelOpenResponse, IbcBasicResponse, IbcChannelCloseMsg,
4-
IbcChannelConnectMsg, IbcChannelOpenMsg, IbcChannelOpenResponse, IbcOrder, IbcPacketAckMsg,
5-
IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse, MessageInfo, Never,
6-
QueryResponse, Reply, Response, StdError, StdResult, SubMsg, SubMsgResponse, SubMsgResult,
7-
WasmMsg,
3+
DepsMut, Empty, Env, Event, Ibc3ChannelOpenResponse, IbcAcknowledgement, IbcBasicResponse,
4+
IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg, IbcChannelOpenResponse, IbcMsg,
5+
IbcOrder, IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse,
6+
MessageInfo, Never, QueryResponse, Reply, Response, StdError, StdResult, SubMsg,
7+
SubMsgResponse, SubMsgResult, WasmMsg,
88
};
99

1010
use crate::msg::{
1111
AccountInfo, AccountResponse, AcknowledgementMsg, BalancesResponse, DispatchResponse,
12-
InstantiateMsg, ListAccountsResponse, PacketMsg, QueryMsg, ReflectExecuteMsg,
12+
ExecuteMsg, InstantiateMsg, ListAccountsResponse, PacketMsg, QueryMsg, ReflectExecuteMsg,
1313
ReturnMsgsResponse, WhoAmIResponse,
1414
};
1515
use crate::state::{
@@ -37,6 +37,34 @@ pub fn instantiate(
3737
Ok(Response::new().add_attribute("action", "instantiate"))
3838
}
3939

40+
#[entry_point]
41+
pub fn execute(
42+
_deps: DepsMut,
43+
_env: Env,
44+
_info: MessageInfo,
45+
msg: ExecuteMsg,
46+
) -> StdResult<Response> {
47+
match msg {
48+
ExecuteMsg::AsyncAck {
49+
channel_id,
50+
packet_sequence,
51+
ack,
52+
} => execute_async_ack(channel_id, packet_sequence.u64(), ack),
53+
}
54+
}
55+
56+
fn execute_async_ack(
57+
channel_id: String,
58+
packet_sequence: u64,
59+
ack: IbcAcknowledgement,
60+
) -> StdResult<Response> {
61+
Ok(Response::new().add_message(IbcMsg::WriteAcknowledgement {
62+
channel_id,
63+
packet_sequence,
64+
ack,
65+
}))
66+
}
67+
4068
#[entry_point]
4169
pub fn reply(deps: DepsMut, _env: Env, reply: Reply) -> StdResult<Response> {
4270
match (reply.id, reply.result) {
@@ -249,6 +277,7 @@ pub fn ibc_packet_receive(
249277
PacketMsg::Panic {} => execute_panic(),
250278
PacketMsg::ReturnErr { text } => execute_error(text),
251279
PacketMsg::ReturnMsgs { msgs } => execute_return_msgs(msgs),
280+
PacketMsg::NoAck {} => Ok(IbcReceiveResponse::without_ack()),
252281
}
253282
})()
254283
.or_else(|e| {
@@ -607,7 +636,7 @@ mod tests {
607636
// acknowledgement is an error
608637
let ack: AcknowledgementMsg<DispatchResponse> =
609638
from_json(res.acknowledgement.unwrap()).unwrap();
610-
assert_eq!(ack.unwrap_err(), "invalid packet: Error parsing into type ibc_reflect::msg::PacketMsg: unknown variant `reflect_code_id`, expected one of `dispatch`, `who_am_i`, `balances`, `panic`, `return_err`, `return_msgs`");
639+
assert_eq!(ack.unwrap_err(), "invalid packet: Error parsing into type ibc_reflect::msg::PacketMsg: unknown variant `reflect_code_id`, expected one of `dispatch`, `who_am_i`, `balances`, `panic`, `return_err`, `return_msgs`, `no_ack`");
611640
}
612641

613642
#[test]

contracts/ibc-reflect/src/msg.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
use cosmwasm_schema::{cw_serde, QueryResponses};
2-
use cosmwasm_std::{Coin, CosmosMsg};
2+
use cosmwasm_std::{Coin, CosmosMsg, IbcAcknowledgement, Uint64};
33

44
/// Just needs to know the code_id of a reflect contract to spawn sub-accounts
55
#[cw_serde]
66
pub struct InstantiateMsg {
77
pub reflect_code_id: u64,
88
}
99

10+
#[cw_serde]
11+
pub enum ExecuteMsg {
12+
AsyncAck {
13+
/// Existing channel where the packet was received
14+
channel_id: String,
15+
/// Sequence number of the packet that was received
16+
packet_sequence: Uint64,
17+
/// The acknowledgement to send back
18+
ack: IbcAcknowledgement,
19+
},
20+
}
21+
1022
#[cw_serde]
1123
#[derive(QueryResponses)]
1224
pub enum QueryMsg {
@@ -49,6 +61,7 @@ pub enum PacketMsg {
4961
Panic {},
5062
ReturnErr { text: String },
5163
ReturnMsgs { msgs: Vec<CosmosMsg> },
64+
NoAck {},
5265
}
5366

5467
/// A custom acknowledgement type.

0 commit comments

Comments
 (0)