Skip to content

Commit

Permalink
Merge pull request #796 from CosmWasm/sub-calls-and-entry-point
Browse files Browse the repository at this point in the history
Sub calls and entry point
  • Loading branch information
webmaster128 authored Mar 1, 2021
2 parents b4a89d6 + 84f8fb1 commit c7bdef9
Show file tree
Hide file tree
Showing 29 changed files with 539 additions and 33 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ and this project adheres to
(eg. multisig) be the admin and migrate another contract ([#768])
- cosmwasm-std: Added optional `system` entry point that can only be called by
native (blockchain) modules to expose admin functionality if desired. ([#793])
- cosmwasm-std: Add extra field `submessages` to `Response`, such that you can
get a callback from these messages after their execution (success or failure).
([#796])
- cosmwasm-std: Added `reply` entry point that will receive all
callbacks from submessages dispatched by this contract. This is only required
if contract returns "submessages" (above). ([#796])

[#692]: https://github.com/CosmWasm/cosmwasm/issues/692
[#706]: https://github.com/CosmWasm/cosmwasm/pull/706
Expand All @@ -53,6 +59,7 @@ and this project adheres to
[#716]: https://github.com/CosmWasm/cosmwasm/pull/716
[#768]: https://github.com/CosmWasm/cosmwasm/pull/768
[#793]: https://github.com/CosmWasm/cosmwasm/pull/793
[#796]: https://github.com/CosmWasm/cosmwasm/pull/796

### Changed

Expand Down
1 change: 1 addition & 0 deletions contracts/burner/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub fn migrate(deps: DepsMut, env: Env, msg: MigrateMsg) -> StdResult<Response>
let data_msg = format!("burnt {} keys", count).into_bytes();

Ok(Response {
submessages: vec![],
messages: vec![send.into()],
attributes: vec![attr("action", "burn"), attr("payout", msg.payout)],
data: Some(data_msg.into()),
Expand Down
5 changes: 5 additions & 0 deletions contracts/ibc-reflect-send/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub fn init(deps: DepsMut, _env: Env, info: MessageInfo, _msg: InitMsg) -> StdRe

Ok(Response {
data: None,
submessages: vec![],
messages: vec![],
attributes: vec![attr("action", "init")],
})
Expand Down Expand Up @@ -54,6 +55,7 @@ pub fn handle_update_admin(
config(deps.storage).save(&cfg)?;

Ok(Response {
submessages: vec![],
messages: vec![],
attributes: vec![
attr("action", "handle_update_admin"),
Expand Down Expand Up @@ -88,6 +90,7 @@ pub fn handle_send_msgs(
};

Ok(Response {
submessages: vec![],
messages: vec![msg.into()],
attributes: vec![attr("action", "handle_send_msgs")],
data: None,
Expand Down Expand Up @@ -118,6 +121,7 @@ pub fn handle_check_remote_balance(
};

Ok(Response {
submessages: vec![],
messages: vec![msg.into()],
attributes: vec![attr("action", "handle_check_remote_balance")],
data: None,
Expand Down Expand Up @@ -168,6 +172,7 @@ pub fn handle_send_funds(
};

Ok(Response {
submessages: vec![],
messages: vec![msg.into()],
attributes: vec![attr("action", "handle_send_funds")],
data: None,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "AcknowledgementMsgBalances",
"description": "This is the final result type that is created and serialized in a contract for every init/handle/migrate call. The VM then deserializes this type to distinguish between successful and failed executions.\n\nWe use a custom type here instead of Rust's Result because we want to be able to define the serialization, which is a public interface. Every language that compiles to Wasm and runs in the ComsWasm VM needs to create the same JSON representation.\n\n# Examples\n\nSuccess:\n\n``` # use cosmwasm_std::{to_vec, ContractResult, Response}; let response: Response = Response::default(); let result: ContractResult<Response> = ContractResult::Ok(response); assert_eq!(to_vec(&result).unwrap(), br#\"{\"ok\":{\"messages\":[],\"attributes\":[],\"data\":null}}\"#.to_vec()); ```\n\nFailure:\n\n``` # use cosmwasm_std::{to_vec, ContractResult, Response}; let error_msg = String::from(\"Something went wrong\"); let result: ContractResult<Response> = ContractResult::Err(error_msg); assert_eq!(to_vec(&result).unwrap(), br#\"{\"error\":\"Something went wrong\"}\"#.to_vec()); ```",
"description": "This is the final result type that is created and serialized in a contract for every init/handle/migrate call. The VM then deserializes this type to distinguish between successful and failed executions.\n\nWe use a custom type here instead of Rust's Result because we want to be able to define the serialization, which is a public interface. Every language that compiles to Wasm and runs in the ComsWasm VM needs to create the same JSON representation.\n\n# Examples\n\nSuccess:\n\n``` # use cosmwasm_std::{to_vec, ContractResult, Response}; let response: Response = Response::default(); let result: ContractResult<Response> = ContractResult::Ok(response); assert_eq!(to_vec(&result).unwrap(), br#\"{\"ok\":{\"submessages\":[],\"messages\":[],\"attributes\":[],\"data\":null}}\"#.to_vec()); ```\n\nFailure:\n\n``` # use cosmwasm_std::{to_vec, ContractResult, Response}; let error_msg = String::from(\"Something went wrong\"); let result: ContractResult<Response> = ContractResult::Err(error_msg); assert_eq!(to_vec(&result).unwrap(), br#\"{\"error\":\"Something went wrong\"}\"#.to_vec()); ```",
"anyOf": [
{
"type": "object",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "AcknowledgementMsgDispatch",
"description": "This is the final result type that is created and serialized in a contract for every init/handle/migrate call. The VM then deserializes this type to distinguish between successful and failed executions.\n\nWe use a custom type here instead of Rust's Result because we want to be able to define the serialization, which is a public interface. Every language that compiles to Wasm and runs in the ComsWasm VM needs to create the same JSON representation.\n\n# Examples\n\nSuccess:\n\n``` # use cosmwasm_std::{to_vec, ContractResult, Response}; let response: Response = Response::default(); let result: ContractResult<Response> = ContractResult::Ok(response); assert_eq!(to_vec(&result).unwrap(), br#\"{\"ok\":{\"messages\":[],\"attributes\":[],\"data\":null}}\"#.to_vec()); ```\n\nFailure:\n\n``` # use cosmwasm_std::{to_vec, ContractResult, Response}; let error_msg = String::from(\"Something went wrong\"); let result: ContractResult<Response> = ContractResult::Err(error_msg); assert_eq!(to_vec(&result).unwrap(), br#\"{\"error\":\"Something went wrong\"}\"#.to_vec()); ```",
"description": "This is the final result type that is created and serialized in a contract for every init/handle/migrate call. The VM then deserializes this type to distinguish between successful and failed executions.\n\nWe use a custom type here instead of Rust's Result because we want to be able to define the serialization, which is a public interface. Every language that compiles to Wasm and runs in the ComsWasm VM needs to create the same JSON representation.\n\n# Examples\n\nSuccess:\n\n``` # use cosmwasm_std::{to_vec, ContractResult, Response}; let response: Response = Response::default(); let result: ContractResult<Response> = ContractResult::Ok(response); assert_eq!(to_vec(&result).unwrap(), br#\"{\"ok\":{\"submessages\":[],\"messages\":[],\"attributes\":[],\"data\":null}}\"#.to_vec()); ```\n\nFailure:\n\n``` # use cosmwasm_std::{to_vec, ContractResult, Response}; let error_msg = String::from(\"Something went wrong\"); let result: ContractResult<Response> = ContractResult::Err(error_msg); assert_eq!(to_vec(&result).unwrap(), br#\"{\"error\":\"Something went wrong\"}\"#.to_vec()); ```",
"anyOf": [
{
"type": "object",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "AcknowledgementMsgWhoAmI",
"description": "This is the final result type that is created and serialized in a contract for every init/handle/migrate call. The VM then deserializes this type to distinguish between successful and failed executions.\n\nWe use a custom type here instead of Rust's Result because we want to be able to define the serialization, which is a public interface. Every language that compiles to Wasm and runs in the ComsWasm VM needs to create the same JSON representation.\n\n# Examples\n\nSuccess:\n\n``` # use cosmwasm_std::{to_vec, ContractResult, Response}; let response: Response = Response::default(); let result: ContractResult<Response> = ContractResult::Ok(response); assert_eq!(to_vec(&result).unwrap(), br#\"{\"ok\":{\"messages\":[],\"attributes\":[],\"data\":null}}\"#.to_vec()); ```\n\nFailure:\n\n``` # use cosmwasm_std::{to_vec, ContractResult, Response}; let error_msg = String::from(\"Something went wrong\"); let result: ContractResult<Response> = ContractResult::Err(error_msg); assert_eq!(to_vec(&result).unwrap(), br#\"{\"error\":\"Something went wrong\"}\"#.to_vec()); ```",
"description": "This is the final result type that is created and serialized in a contract for every init/handle/migrate call. The VM then deserializes this type to distinguish between successful and failed executions.\n\nWe use a custom type here instead of Rust's Result because we want to be able to define the serialization, which is a public interface. Every language that compiles to Wasm and runs in the ComsWasm VM needs to create the same JSON representation.\n\n# Examples\n\nSuccess:\n\n``` # use cosmwasm_std::{to_vec, ContractResult, Response}; let response: Response = Response::default(); let result: ContractResult<Response> = ContractResult::Ok(response); assert_eq!(to_vec(&result).unwrap(), br#\"{\"ok\":{\"submessages\":[],\"messages\":[],\"attributes\":[],\"data\":null}}\"#.to_vec()); ```\n\nFailure:\n\n``` # use cosmwasm_std::{to_vec, ContractResult, Response}; let error_msg = String::from(\"Something went wrong\"); let result: ContractResult<Response> = ContractResult::Err(error_msg); assert_eq!(to_vec(&result).unwrap(), br#\"{\"error\":\"Something went wrong\"}\"#.to_vec()); ```",
"anyOf": [
{
"type": "object",
Expand Down
2 changes: 2 additions & 0 deletions contracts/ibc-reflect/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub fn init(deps: DepsMut, _env: Env, _info: MessageInfo, msg: InitMsg) -> StdRe
config(deps.storage).save(&cfg)?;

Ok(Response {
submessages: vec![],
messages: vec![],
attributes: vec![attr("action", "init")],
data: None,
Expand Down Expand Up @@ -61,6 +62,7 @@ pub fn handle_init_callback(
})?;

Ok(Response {
submessages: vec![],
messages: vec![],
attributes: vec![attr("action", "handle_init_callback")],
data: None,
Expand Down
48 changes: 48 additions & 0 deletions contracts/reflect/schema/handle_msg.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,28 @@
}
}
},
{
"type": "object",
"required": [
"reflect_sub_call"
],
"properties": {
"reflect_sub_call": {
"type": "object",
"required": [
"msgs"
],
"properties": {
"msgs": {
"type": "array",
"items": {
"$ref": "#/definitions/SubMsg_for_CustomMsg"
}
}
}
}
}
},
{
"type": "object",
"required": [
Expand Down Expand Up @@ -471,6 +493,32 @@
}
]
},
"SubMsg_for_CustomMsg": {
"description": "A sub-message that will guarantee a subcall_response callback on success or error Note on error the subcall will revert any partial state changes due to this message, but not revert any state changes in the calling contract (that must be done in the subcall_response entry point)",
"type": "object",
"required": [
"id",
"msg"
],
"properties": {
"gas_limit": {
"type": [
"integer",
"null"
],
"format": "uint64",
"minimum": 0.0
},
"id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"msg": {
"$ref": "#/definitions/CosmosMsg_for_CustomMsg"
}
}
},
"Uint128": {
"type": "string"
},
Expand Down
22 changes: 22 additions & 0 deletions contracts/reflect/schema/query_msg.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,28 @@
}
}
}
},
{
"description": "If there was a previous ReflectSubCall with this ID, returns cosmwasm_std::Reply",
"type": "object",
"required": [
"sub_call_result"
],
"properties": {
"sub_call_result": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
}
}
}
}
],
"definitions": {
Expand Down
39 changes: 37 additions & 2 deletions contracts/reflect/schema/response_for__custom_msg.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Response_for_CustomMsg",
"description": "A response of a contract entry point, such as `init`, `handle` or `migrate`.\n\nThis type can be constructed directly at the end of the call. Alternatively a mutable response instance can be created early in the contract's logic and incrementally be updated.\n\n## Examples\n\nDirect:\n\n``` # use cosmwasm_std::{Binary, DepsMut, Env, MessageInfo, MigrateResponse}; # type InitMsg = (); # use cosmwasm_std::{attr, Response, StdResult};\n\npub fn init( deps: DepsMut, _env: Env, _info: MessageInfo, msg: InitMsg, ) -> StdResult<Response> { // ...\n\nOk(Response { messages: vec![], attributes: vec![attr(\"action\", \"init\")], data: None, }) } ```\n\nMutating:\n\n``` # use cosmwasm_std::{coins, BankMsg, Binary, DepsMut, Env, HumanAddr, MessageInfo, MigrateResponse}; # type InitMsg = (); # type MyError = (); # use cosmwasm_std::Response;\n\npub fn init( deps: DepsMut, _env: Env, info: MessageInfo, msg: InitMsg, ) -> Result<Response, MyError> { let mut response = Response::new(); // ... response.add_attribute(\"Let the\", \"hacking begin\"); // ... response.add_message(BankMsg::Send { to_address: HumanAddr::from(\"recipient\"), amount: coins(128, \"uint\"), }); response.add_attribute(\"foo\", \"bar\"); // ... response.set_data(Binary::from(b\"the result data\")); Ok(response) } ```",
"description": "A response of a contract entry point, such as `init`, `handle` or `migrate`.\n\nThis type can be constructed directly at the end of the call. Alternatively a mutable response instance can be created early in the contract's logic and incrementally be updated.\n\n## Examples\n\nDirect:\n\n``` # use cosmwasm_std::{Binary, DepsMut, Env, MessageInfo}; # type InitMsg = (); # use cosmwasm_std::{attr, Response, StdResult};\n\npub fn init( deps: DepsMut, _env: Env, _info: MessageInfo, msg: InitMsg, ) -> StdResult<Response> { // ...\n\nOk(Response { submessages: vec![], messages: vec![], attributes: vec![attr(\"action\", \"init\")], data: None, }) } ```\n\nMutating:\n\n``` # use cosmwasm_std::{coins, BankMsg, Binary, DepsMut, Env, HumanAddr, MessageInfo}; # type InitMsg = (); # type MyError = (); # use cosmwasm_std::Response;\n\npub fn init( deps: DepsMut, _env: Env, info: MessageInfo, msg: InitMsg, ) -> Result<Response, MyError> { let mut response = Response::new(); // ... response.add_attribute(\"Let the\", \"hacking begin\"); // ... response.add_message(BankMsg::Send { to_address: HumanAddr::from(\"recipient\"), amount: coins(128, \"uint\"), }); response.add_attribute(\"foo\", \"bar\"); // ... response.set_data(Binary::from(b\"the result data\")); Ok(response) } ```",
"type": "object",
"required": [
"attributes",
"messages"
"messages",
"submessages"
],
"properties": {
"attributes": {
Expand All @@ -26,10 +27,18 @@
]
},
"messages": {
"description": "After any submessages are processed, these are all dispatched in the host blockchain. If they all succeed, then the transaction is committed. If any fail, then the transaction and any local contract state changes are reverted.",
"type": "array",
"items": {
"$ref": "#/definitions/CosmosMsg_for_CustomMsg"
}
},
"submessages": {
"description": "Optional list of \"subcalls\" to make. These will be executed in order (and this contract's subcall_response entry point invoked) *before* any of the \"fire and forget\" messages get executed.",
"type": "array",
"items": {
"$ref": "#/definitions/SubMsg_for_CustomMsg"
}
}
},
"definitions": {
Expand Down Expand Up @@ -475,6 +484,32 @@
}
]
},
"SubMsg_for_CustomMsg": {
"description": "A sub-message that will guarantee a subcall_response callback on success or error Note on error the subcall will revert any partial state changes due to this message, but not revert any state changes in the calling contract (that must be done in the subcall_response entry point)",
"type": "object",
"required": [
"id",
"msg"
],
"properties": {
"gas_limit": {
"type": [
"integer",
"null"
],
"format": "uint64",
"minimum": 0.0
},
"id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"msg": {
"$ref": "#/definitions/CosmosMsg_for_CustomMsg"
}
}
},
"Uint128": {
"type": "string"
},
Expand Down
Loading

0 comments on commit c7bdef9

Please sign in to comment.