diff --git a/Cargo.lock b/Cargo.lock index 146f43b..e33964b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -124,7 +124,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus", "cw2", - "neutron-sdk 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "neutron-sdk", "schemars", "serde", ] @@ -559,7 +559,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus", "cw2", - "neutron-sdk 0.6.1 (git+https://github.com/neutron-org/neutron-sdk?rev=bb2188561a30d0a7fb293ff05f73907724eb2020)", + "neutron-sdk", "protobuf", "schemars", "serde", @@ -608,7 +608,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus", "cw2", - "neutron-sdk 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "neutron-sdk", "prost 0.11.9", "prost-types", "protobuf", @@ -662,26 +662,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "neutron-sdk" -version = "0.6.1" -source = "git+https://github.com/neutron-org/neutron-sdk?rev=bb2188561a30d0a7fb293ff05f73907724eb2020#bb2188561a30d0a7fb293ff05f73907724eb2020" -dependencies = [ - "base64 0.21.2", - "bech32", - "cosmos-sdk-proto 0.16.0", - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "prost 0.11.9", - "protobuf", - "schemars", - "serde", - "serde-json-wasm", - "serde_json", - "thiserror", -] - [[package]] name = "neutron_interchain_queries" version = "0.1.0" @@ -692,7 +672,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus", "cw2", - "neutron-sdk 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "neutron-sdk", "prost 0.11.9", "schemars", "serde", @@ -710,7 +690,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus", "cw2", - "neutron-sdk 0.6.1 (git+https://github.com/neutron-org/neutron-sdk?rev=bb2188561a30d0a7fb293ff05f73907724eb2020)", + "neutron-sdk", "prost 0.11.9", "prost-types", "protobuf", @@ -731,7 +711,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus", "cw2", - "neutron-sdk 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "neutron-sdk", "prost 0.11.9", "prost-types", "protobuf", @@ -1047,7 +1027,7 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw2", - "neutron-sdk 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "neutron-sdk", "schemars", "serde", ] @@ -1241,7 +1221,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus", "cw2", - "neutron-sdk 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "neutron-sdk", "osmosis-std", "prost 0.11.9", "prost-types", @@ -1395,7 +1375,7 @@ version = "0.1.0" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "neutron-sdk 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "neutron-sdk", "schemars", "serde", ] diff --git a/artifacts/checksums.txt b/artifacts/checksums.txt index e15afc4..ca4f4ef 100644 --- a/artifacts/checksums.txt +++ b/artifacts/checksums.txt @@ -1,22 +1,11 @@ -3a4c512a4ca6a26f80e8d351b101103248d6ddb51caf8eb1c96db3613feedf5f client_updater-aarch64.wasm c0190cf28da64b4058da71a9083c187d45f84ee7b9db11a0830025ecb0a687dc client_updater.wasm -ee36fe3b2c7b73bdaf00f92019adbbb7e0459cabf00b797336df16ca3cfd908d echo-aarch64.wasm 4ee0b1e8a1c39e7a440f236778e76935f29506f354b6a59712d267181da77678 echo.wasm -d72e2f3bd0e3cc7e38fe716144220e699023fd8013e52360dac2d3a01b2edad6 ibc_transfer-aarch64.wasm -cf4b2b555032cffa472b98122dee6d6c8f53d07be31c2565d651b4941584f4f1 ibc_transfer.wasm -72274baaf57f04f86ae5af938ac30d824953a28b1f9e8956910ed50f85335641 msg_receiver-aarch64.wasm +fec7d4b6280569bd4ca428d1f5b52702a3378533f50362e1c3f1c848c4e91303 ibc_transfer.wasm af52c56fb25355afa04d86c7d9e867f9db9295a455fb8a89f9cfdbd6374dd1ff msg_receiver.wasm -15a5c15af41227b8861e92a89830d9c76fba368c2be252709bd9868ce5f9a171 neutron_interchain_queries-aarch64.wasm 05e49fb2d0295c9a9e27a0077da856126f8285c2e949cb1f927f08fa8a867c8e neutron_interchain_queries.wasm -955075ca5b473e1a987d5384cd4e3d6aa730f412edc3049b6527239549319fec neutron_interchain_txs-aarch64.wasm -696362a84c5f8ef42eec10ea9ece3e77251b6de971e05aaa338ae1a1bb21f157 neutron_interchain_txs.wasm -08e912518f6f87119833a863b7562f52d043d80d78e0539c3f3cd50b1cfd4ac5 neutron_price_feed_mock-aarch64.wasm +19d3ea0f4f0a24d202edbd2a7989dcffa61ba3d6754ff382cbd89d4ecd034a67 neutron_interchain_txs.wasm 344ec19c522cc5e6135a77a181345f02a0f65ef19ad919d5236dc16f53d33e76 neutron_price_feed_mock.wasm -6e1a337b1f905cd6b4b5414beb64f67a16de525ad9618ebc5d917246dac4c131 neutron_validators_test-aarch64.wasm 4678704ef3ffd9f1240b719991dc629623929fa75499fd6ed9f76eda4c8a556a neutron_validators_test.wasm -c68ec42808159b006580e6868a7e8de0abfaa52a9a6ebaf90c25ffbf711aee33 reflect-aarch64.wasm c24970beb5a08bfc73dc422e63207342343802a329f28d527b4accaaf66209f8 reflect.wasm -d18b852f6c0c57b51e577825f454e82f233b26f86d441d264654c7a58f42f5dc stargate_querier-aarch64.wasm -d2ee71886a22631993bbe9f5add6878601897e2f11a31eb7a83296c6eb57eafa stargate_querier.wasm -9bc16491e14afe7f8b0aded8aaa01bbfa0d7b05394e14b0b10ac5e361bc4fa07 tokenfactory-aarch64.wasm +e3ab89e1d88381142c6a970daafceda3cb3fde6f8222e450834045d1f7c9f971 stargate_querier.wasm a9ee139212dca756adbde1e86723154b1fd79dc96cbc7e4885a851d8c978e946 tokenfactory.wasm diff --git a/artifacts/checksums_intermediate.txt b/artifacts/checksums_intermediate.txt index 0654a20..c96c774 100644 --- a/artifacts/checksums_intermediate.txt +++ b/artifacts/checksums_intermediate.txt @@ -1,11 +1,11 @@ -d89ba235e130977d1f79ac4d7f9252f6f6bed3002dfc1d08227ba138acec70b1 target/wasm32-unknown-unknown/release/client_updater.wasm a67c60c5853497b890d67dd2bfed1caf0984a03af01ec67c877e63688970814e target/wasm32-unknown-unknown/release/echo.wasm -b388b89207c69e9e243f5acf64b761e1cf1116adcc2d79e4eb59bf8cb6c9b99a target/wasm32-unknown-unknown/release/ibc_transfer.wasm -f1ec0aa2f9c84a8b0d63d877fb6dcaf2d25c30023740f3ef53072496124c7dce target/wasm32-unknown-unknown/release/msg_receiver.wasm +bebad52462ca1ddc557ae7ea3fc09aab0a11dd86497027a473f885bbe0c91d6c target/wasm32-unknown-unknown/release/ibc_transfer.wasm b09e4f513e19e78b5ea08e10d26dc4d61056a4c6f534e783039f32494c39021b target/wasm32-unknown-unknown/release/neutron_interchain_queries.wasm -78b1e6a83b5adc768345716f9eac1bbcc1c4676046d18efaa27d8a8d6c470cb7 target/wasm32-unknown-unknown/release/neutron_interchain_txs.wasm +43c926644f096ba26d356c34f0f409b94b793d8398b1845e5fe03ffee7400e0c target/wasm32-unknown-unknown/release/neutron_interchain_txs.wasm e947d71ddeb4f6e61d756b48981bedae6973e0b25a9d873c3bba5e9878079d8b target/wasm32-unknown-unknown/release/neutron_price_feed_mock.wasm 8893279611c69a5ca55628f0476e943ca60b8900cb0ae17fefc2f38c4e472215 target/wasm32-unknown-unknown/release/neutron_validators_test.wasm b260fdda36208b9017f0f142821fa3bb47f3d3dea86901d687cf3d3da00946e0 target/wasm32-unknown-unknown/release/reflect.wasm -46d5d18cf293f37cca582c669de1364635e9c69eaed629f9d5dfe4b6db1b352e target/wasm32-unknown-unknown/release/stargate_querier.wasm fc80abbf059bafa21b25162af22ddb963a1ea1c6ab4dd671855adb3e1f8a8a84 target/wasm32-unknown-unknown/release/tokenfactory.wasm +d89ba235e130977d1f79ac4d7f9252f6f6bed3002dfc1d08227ba138acec70b1 target/wasm32-unknown-unknown/release/client_updater.wasm +f1ec0aa2f9c84a8b0d63d877fb6dcaf2d25c30023740f3ef53072496124c7dce target/wasm32-unknown-unknown/release/msg_receiver.wasm +0cd5cb6ac3532b558fffa62d501936ccbe748cddf465746ad639ac3a166066ce target/wasm32-unknown-unknown/release/stargate_querier.wasm diff --git a/artifacts/ibc_transfer.wasm b/artifacts/ibc_transfer.wasm index f13930e..3709a29 100644 Binary files a/artifacts/ibc_transfer.wasm and b/artifacts/ibc_transfer.wasm differ diff --git a/artifacts/neutron_interchain_txs.wasm b/artifacts/neutron_interchain_txs.wasm index 222c7fd..41472e8 100644 Binary files a/artifacts/neutron_interchain_txs.wasm and b/artifacts/neutron_interchain_txs.wasm differ diff --git a/contracts/ibc_transfer/Cargo.toml b/contracts/ibc_transfer/Cargo.toml index f559091..b8ba945 100644 --- a/contracts/ibc_transfer/Cargo.toml +++ b/contracts/ibc_transfer/Cargo.toml @@ -39,7 +39,7 @@ schemars = "0.8.10" serde = { version = "1.0.180", default-features = false, features = ["derive"] } serde-json-wasm = { version = "0.5.1" } cw-storage-plus = { version = "1.1.0", features = ["iterator"]} -neutron-sdk = { package = "neutron-sdk", git = "https://github.com/neutron-org/neutron-sdk", rev = "bb2188561a30d0a7fb293ff05f73907724eb2020" } +neutron-sdk = { package = "neutron-sdk", version = "0.6.1" } protobuf = { version = "3.2.0", features = ["with-bytes"] } [dev-dependencies] diff --git a/contracts/ibc_transfer/schema/execute_msg.json b/contracts/ibc_transfer/schema/execute_msg.json index eacd7f4..910eb5d 100644 --- a/contracts/ibc_transfer/schema/execute_msg.json +++ b/contracts/ibc_transfer/schema/execute_msg.json @@ -82,28 +82,6 @@ }, "additionalProperties": false }, - { - "type": "object", - "required": [ - "resubmit_failure" - ], - "properties": { - "resubmit_failure": { - "type": "object", - "required": [ - "failure_id" - ], - "properties": { - "failure_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - } - } - }, - "additionalProperties": false - }, { "description": "Used only in integration tests framework to simulate failures. After executing this message, contract will fail, all of this happening in sudo callback handler.", "type": "object", @@ -112,15 +90,7 @@ ], "properties": { "integration_tests_set_sudo_failure_mock": { - "type": "object", - "required": [ - "state" - ], - "properties": { - "state": { - "$ref": "#/definitions/IntegrationTestsSudoFailureMock" - } - } + "type": "object" } }, "additionalProperties": false @@ -138,15 +108,5 @@ }, "additionalProperties": false } - ], - "definitions": { - "IntegrationTestsSudoFailureMock": { - "type": "string", - "enum": [ - "enabled", - "enabled_infinite_loop", - "disabled" - ] - } - } + ] } diff --git a/contracts/ibc_transfer/src/contract.rs b/contracts/ibc_transfer/src/contract.rs index 5370abf..93f3ad2 100644 --- a/contracts/ibc_transfer/src/contract.rs +++ b/contracts/ibc_transfer/src/contract.rs @@ -13,12 +13,12 @@ use serde::{Deserialize, Serialize}; use crate::state::{ read_reply_payload, read_sudo_payload, save_reply_payload, save_sudo_payload, IBC_FEE, - IBC_SUDO_ID_RANGE_END, IBC_SUDO_ID_RANGE_START, TEST_COUNTER_ITEM, + IBC_SUDO_ID_RANGE_END, IBC_SUDO_ID_RANGE_START, }; use crate::{ integration_tests_mock_handlers::{set_sudo_failure_mock, unset_sudo_failure_mock}, - state::{IntegrationTestsSudoFailureMock, INTEGRATION_TESTS_SUDO_FAILURE_MOCK}, + state::{IntegrationTestsSudoMock, INTEGRATION_TESTS_SUDO_MOCK}, }; // Default timeout for IbcTransfer is 10000000 blocks @@ -58,15 +58,10 @@ pub enum ExecuteMsg { timeout_fee: u128, denom: String, }, - ResubmitFailure { - failure_id: u64, - }, /// Used only in integration tests framework to simulate failures. /// After executing this message, contract will fail, all of this happening /// in sudo callback handler. - IntegrationTestsSetSudoFailureMock { - state: IntegrationTestsSudoFailureMock, - }, + IntegrationTestsSetSudoFailureMock {}, /// Used only in integration tests framework to simulate failures. /// After executing this message, contract will revert back to normal behaviour. IntegrationTestsUnsetSudoFailureMock {}, @@ -99,15 +94,10 @@ pub fn execute( timeout_fee, denom, } => execute_set_fees(deps, recv_fee, ack_fee, timeout_fee, denom), - - ExecuteMsg::ResubmitFailure { failure_id } => execute_resubmit_failure(deps, failure_id), - // Used only in integration tests framework to simulate failures. // After executing this message, contract fail, all of this happening // in sudo callback handler. - ExecuteMsg::IntegrationTestsSetSudoFailureMock { state } => { - set_sudo_failure_mock(deps, state) - } + ExecuteMsg::IntegrationTestsSetSudoFailureMock {} => set_sudo_failure_mock(deps), ExecuteMsg::IntegrationTestsUnsetSudoFailureMock {} => unset_sudo_failure_mock(deps), } } @@ -268,52 +258,18 @@ fn execute_send( Ok(Response::default().add_submessages(vec![submsg1, submsg2])) } -fn execute_resubmit_failure(_: DepsMut, failure_id: u64) -> StdResult> { - let msg = NeutronMsg::submit_resubmit_failure(failure_id); - Ok(Response::default().add_message(msg)) -} - -// Err result returned from the `sudo()` handler will result in the `Failure` object stored in the chain state. -// It can be resubmitted later using `NeutronMsg::ResubmitFailure { failure_id }` message. -#[allow(unreachable_code)] #[entry_point] pub fn sudo(deps: DepsMut, _env: Env, msg: TransferSudoMsg) -> StdResult { - match INTEGRATION_TESTS_SUDO_FAILURE_MOCK.may_load(deps.storage)? { - Some(IntegrationTestsSudoFailureMock::Enabled) => { - // Used only in integration tests framework to simulate failures. - deps.api - .debug("WASMDEBUG: sudo: mocked failure on the handler"); - - return Err(StdError::generic_err( - "Integrations test mock error".to_string(), - )); - } - Some(IntegrationTestsSudoFailureMock::EnabledInfiniteLoop) => { - // Used only in integration tests framework to simulate failures. - deps.api - .debug("WASMDEBUG: sudo: mocked infinite loop failure on the handler"); - - if let TransferSudoMsg::Response { request, data: _ } = msg { - deps.api.debug( - format!( - "WASMDEBUG: infinite loop failure response; sequence_id = {:?}", - &request.sequence.unwrap_or_default().to_string() - ) - .as_str(), - ); - } - - let mut counter: u64 = 0; - while counter < 18_446_744_073_709_551_615u64 { - counter = counter.checked_add(1).unwrap_or_default(); - TEST_COUNTER_ITEM.save(deps.storage, &counter)?; - } - deps.api.debug("WASMDEBUG: after infinite loop"); - TEST_COUNTER_ITEM.save(deps.storage, &counter)?; + if let Some(IntegrationTestsSudoMock::Enabled {}) = + INTEGRATION_TESTS_SUDO_MOCK.may_load(deps.storage)? + { + // Used only in integration tests framework to simulate failures. + deps.api + .debug("WASMDEBUG: sudo: mocked failure on the handler"); - return Ok(Response::default()); - } - _ => {} + return Err(StdError::GenericErr { + msg: "Integrations test mock error".to_string(), + }); } match msg { diff --git a/contracts/ibc_transfer/src/integration_tests_mock_handlers.rs b/contracts/ibc_transfer/src/integration_tests_mock_handlers.rs index c86490a..2a5316f 100644 --- a/contracts/ibc_transfer/src/integration_tests_mock_handlers.rs +++ b/contracts/ibc_transfer/src/integration_tests_mock_handlers.rs @@ -1,17 +1,13 @@ -use crate::state::{IntegrationTestsSudoFailureMock, INTEGRATION_TESTS_SUDO_FAILURE_MOCK}; +use crate::state::{IntegrationTestsSudoMock, INTEGRATION_TESTS_SUDO_MOCK}; use cosmwasm_std::{DepsMut, Response, StdResult}; use neutron_sdk::bindings::msg::NeutronMsg; -pub fn set_sudo_failure_mock( - deps: DepsMut, - state: IntegrationTestsSudoFailureMock, -) -> StdResult> { - INTEGRATION_TESTS_SUDO_FAILURE_MOCK.save(deps.storage, &state)?; +pub fn set_sudo_failure_mock(deps: DepsMut) -> StdResult> { + INTEGRATION_TESTS_SUDO_MOCK.save(deps.storage, &IntegrationTestsSudoMock::Enabled)?; Ok(Response::default()) } pub fn unset_sudo_failure_mock(deps: DepsMut) -> StdResult> { - INTEGRATION_TESTS_SUDO_FAILURE_MOCK - .save(deps.storage, &IntegrationTestsSudoFailureMock::Disabled)?; + INTEGRATION_TESTS_SUDO_MOCK.save(deps.storage, &IntegrationTestsSudoMock::Disabled)?; Ok(Response::default()) } diff --git a/contracts/ibc_transfer/src/state.rs b/contracts/ibc_transfer/src/state.rs index fb5a5a3..bcb9f23 100644 --- a/contracts/ibc_transfer/src/state.rs +++ b/contracts/ibc_transfer/src/state.rs @@ -68,16 +68,11 @@ pub fn read_sudo_payload( } /// Used only in integration tests framework to simulate failures. -pub const INTEGRATION_TESTS_SUDO_FAILURE_MOCK: Item = +pub const INTEGRATION_TESTS_SUDO_MOCK: Item = Item::new("integration_tests_sudo_mock"); #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum IntegrationTestsSudoFailureMock { +pub enum IntegrationTestsSudoMock { Enabled, - EnabledInfiniteLoop, Disabled, } - -// just to do something in infinite loop -pub const TEST_COUNTER_ITEM: Item = Item::new("test_counter"); diff --git a/contracts/neutron_interchain_txs/Cargo.toml b/contracts/neutron_interchain_txs/Cargo.toml index 826c18d..ef55f60 100644 --- a/contracts/neutron_interchain_txs/Cargo.toml +++ b/contracts/neutron_interchain_txs/Cargo.toml @@ -39,7 +39,7 @@ serde = { version = "1.0.180", default-features = false, features = ["derive"] } serde-json-wasm = { version = "0.5.1" } cw-storage-plus = { version = "1.1.0", features = ["iterator"]} cosmos-sdk-proto = { version = "0.16.0", default-features = false } -neutron-sdk = { package = "neutron-sdk", git = "https://github.com/neutron-org/neutron-sdk", rev = "bb2188561a30d0a7fb293ff05f73907724eb2020" } +neutron-sdk = { package = "neutron-sdk", version = "0.6.1" } base64 = "0.21.2" protobuf = { version = "3.2.0", features = ["with-bytes"] } prost = "0.11" diff --git a/contracts/neutron_interchain_txs/schema/execute_msg.json b/contracts/neutron_interchain_txs/schema/execute_msg.json index 3d54bf3..4f4e672 100644 --- a/contracts/neutron_interchain_txs/schema/execute_msg.json +++ b/contracts/neutron_interchain_txs/schema/execute_msg.json @@ -202,28 +202,6 @@ }, "additionalProperties": false }, - { - "type": "object", - "required": [ - "resubmit_failure" - ], - "properties": { - "resubmit_failure": { - "type": "object", - "required": [ - "failure_id" - ], - "properties": { - "failure_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - } - } - }, - "additionalProperties": false - }, { "description": "Used only in integration tests framework to simulate failures. After executing this message, any sudo call to the contract will result in an error.", "type": "object", @@ -232,15 +210,7 @@ ], "properties": { "integration_tests_set_sudo_failure_mock": { - "type": "object", - "required": [ - "state" - ], - "properties": { - "state": { - "$ref": "#/definitions/IntegrationTestsSudoFailureMock" - } - } + "type": "object" } }, "additionalProperties": false @@ -297,15 +267,5 @@ }, "additionalProperties": false } - ], - "definitions": { - "IntegrationTestsSudoFailureMock": { - "type": "string", - "enum": [ - "enabled", - "enabled_infinite_loop", - "disabled" - ] - } - } + ] } diff --git a/contracts/neutron_interchain_txs/src/contract.rs b/contracts/neutron_interchain_txs/src/contract.rs index 557562d..9a2f5b0 100644 --- a/contracts/neutron_interchain_txs/src/contract.rs +++ b/contracts/neutron_interchain_txs/src/contract.rs @@ -46,10 +46,9 @@ use neutron_sdk::NeutronResult; use crate::storage::{ add_error_to_queue, read_errors_from_queue, read_reply_payload, read_sudo_payload, save_reply_payload, save_sudo_payload, AcknowledgementResult, DoubleDelegateInfo, - IntegrationTestsSudoFailureMock, IntegrationTestsSudoSubmsgFailureMock, SudoPayload, - ACKNOWLEDGEMENT_RESULTS, IBC_FEE, INTEGRATION_TESTS_SUDO_FAILURE_MOCK, - INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK, INTERCHAIN_ACCOUNTS, SUDO_FAILING_SUBMSG_REPLY_ID, - SUDO_PAYLOAD_REPLY_ID, TEST_COUNTER_ITEM, + IntegrationTestsSudoMock, IntegrationTestsSudoSubmsgMock, SudoPayload, ACKNOWLEDGEMENT_RESULTS, + IBC_FEE, INTEGRATION_TESTS_SUDO_FAILURE_MOCK, INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK, + INTERCHAIN_ACCOUNTS, SUDO_FAILING_SUBMSG_REPLY_ID, SUDO_PAYLOAD_REPLY_ID, }; // Default timeout for SubmitTX is two weeks @@ -169,12 +168,9 @@ pub fn execute( timeout_fee, } => execute_set_fees(deps, denom, recv_fee, ack_fee, timeout_fee), ExecuteMsg::CleanAckResults {} => execute_clean_ack_results(deps), - ExecuteMsg::ResubmitFailure { failure_id } => execute_resubmit_failure(deps, failure_id), // The section below is used only in integration tests framework to simulate failures. - ExecuteMsg::IntegrationTestsSetSudoFailureMock { state } => { - set_sudo_failure_mock(deps, state) - } + ExecuteMsg::IntegrationTestsSetSudoFailureMock {} => set_sudo_failure_mock(deps), ExecuteMsg::IntegrationTestsSetSudoSubmsgFailureMock {} => { set_sudo_submsg_failure_mock(deps) } @@ -438,13 +434,8 @@ fn execute_clean_ack_results(deps: DepsMut) -> StdResult> { Ok(Response::default()) } -fn execute_resubmit_failure(_: DepsMut, failure_id: u64) -> StdResult> { - let msg = NeutronMsg::submit_resubmit_failure(failure_id); - Ok(Response::default().add_message(msg)) -} - fn integration_tests_sudo_submsg(deps: DepsMut) -> StdResult> { - if let Some(IntegrationTestsSudoSubmsgFailureMock::Enabled {}) = + if let Some(IntegrationTestsSudoSubmsgMock::Enabled {}) = INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK.may_load(deps.storage)? { // Used only in integration tests framework to simulate failures. @@ -458,35 +449,30 @@ fn integration_tests_sudo_submsg(deps: DepsMut) -> StdResult StdResult> { +pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> StdResult> { let api = deps.api; api.debug(format!("WASMDEBUG: sudo: received sudo msg: {:?}", msg).as_str()); - let mock_res = INTEGRATION_TESTS_SUDO_FAILURE_MOCK.may_load(deps.storage)?; - + let failure_mock_enabled = Some(IntegrationTestsSudoMock::Enabled {}) + == INTEGRATION_TESTS_SUDO_FAILURE_MOCK.may_load(deps.storage)?; let failure_submsg_mock_enabled = { let m = INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK.may_load(deps.storage)?; - m == Some(IntegrationTestsSudoSubmsgFailureMock::Enabled {}) - || m == Some(IntegrationTestsSudoSubmsgFailureMock::EnabledInReply {}) + m == Some(IntegrationTestsSudoSubmsgMock::Enabled {}) + || m == Some(IntegrationTestsSudoSubmsgMock::EnabledInReply {}) }; - let mut resp: Response = match msg.clone() { - SudoMsg::Response { request, data } => { - sudo_response(deps.branch(), env.clone(), request, data)? - } - SudoMsg::Error { request, details } => sudo_error(deps.branch(), request, details)?, - SudoMsg::Timeout { request } => sudo_timeout(deps.branch(), env.clone(), request)?, + let mut resp: Response = match msg { + SudoMsg::Response { request, data } => sudo_response(deps, env.clone(), request, data)?, + SudoMsg::Error { request, details } => sudo_error(deps, request, details)?, + SudoMsg::Timeout { request } => sudo_timeout(deps, env.clone(), request)?, SudoMsg::OpenAck { port_id, channel_id, counterparty_channel_id, counterparty_version, } => sudo_open_ack( - deps.branch(), + deps, env.clone(), port_id, channel_id, @@ -496,39 +482,13 @@ pub fn sudo(mut deps: DepsMut, env: Env, msg: SudoMsg) -> StdResult Response::default(), }; - match mock_res { - Some(IntegrationTestsSudoFailureMock::Enabled) => { - // Used only in integration tests framework to simulate failures. - api.debug("WASMDEBUG: sudo: mocked failure on the handler"); - - return Err(StdError::generic_err( - "Integrations test mock error".to_string(), - )); - } - Some(IntegrationTestsSudoFailureMock::EnabledInfiniteLoop) => { - // Used only in integration tests framework to simulate failures. - api.debug("WASMDEBUG: sudo: mocked failure on the handler"); - - if let SudoMsg::Response { request, data: _ } = msg { - deps.api.debug( - format!( - "WASMDEBUG: infinite loop failure response; sequence_id = {:?}", - &request.sequence.unwrap_or_default().to_string() - ) - .as_str(), - ); - } - - let mut counter: u64 = 0; - loop { - counter = counter.checked_add(1).unwrap_or_default(); - TEST_COUNTER_ITEM.save(deps.storage, &counter)?; - } - TEST_COUNTER_ITEM.save(deps.storage, &counter)?; + if failure_mock_enabled { + // Used only in integration tests framework to simulate failures. + api.debug("WASMDEBUG: sudo: mocked failure on the handler"); - return Ok(Response::default()); - } - _ => {} + return Err(StdError::generic_err( + "Integations test mock error".to_string(), + )); } if failure_submsg_mock_enabled { @@ -591,14 +551,30 @@ fn sudo_response( .as_str(), ); + // WARNING: RETURNING THIS ERROR CLOSES THE CHANNEL. + // AN ALTERNATIVE IS TO MAINTAIN AN ERRORS QUEUE AND PUT THE FAILED REQUEST THERE + // FOR LATER INSPECTION. + // In this particular case, we return an error because not having the sequence id + // in the request value implies that a fatal error occurred on Neutron side. let seq_id = request .sequence .ok_or_else(|| StdError::generic_err("sequence not found"))?; + // WARNING: RETURNING THIS ERROR CLOSES THE CHANNEL. + // AN ALTERNATIVE IS TO MAINTAIN AN ERRORS QUEUE AND PUT THE FAILED REQUEST THERE + // FOR LATER INSPECTION. + // In this particular case, we return an error because not having the sequence id + // in the request value implies that a fatal error occurred on Neutron side. let channel_id = request .source_channel .ok_or_else(|| StdError::generic_err("channel_id not found"))?; + // NOTE: NO ERROR IS RETURNED HERE. THE CHANNEL LIVES ON. + // In this particular example, this is a matter of developer's choice. Not being able to read + // the payload here means that there was a problem with the contract while submitting an + // interchain transaction. You can decide that this is not worth killing the channel, + // write an error log and / or save the acknowledgement to an errors queue for later manual + // processing. The decision is based purely on your application logic. let payload = read_sudo_payload(deps.storage, channel_id, seq_id).ok(); if payload.is_none() { let error_msg = "WASMDEBUG: Error: Unable to read sudo payload"; @@ -610,6 +586,12 @@ fn sudo_response( deps.api .debug(format!("WASMDEBUG: sudo_response: sudo payload: {:?}", payload).as_str()); + // WARNING: RETURNING THIS ERROR CLOSES THE CHANNEL. + // AN ALTERNATIVE IS TO MAINTAIN AN ERRORS QUEUE AND PUT THE FAILED REQUEST THERE + // FOR LATER INSPECTION. + // In this particular case, we return an error because not being able to parse this data + // that a fatal error occurred on Neutron side, or that the remote chain sent us unexpected data. + // Both cases require immediate attention. let parsed_data = decode_acknowledgement_response(data)?; let mut item_types = vec![]; @@ -618,8 +600,16 @@ fn sudo_response( item_types.push(item_type.to_string()); match item_type { "/cosmos.staking.v1beta1.MsgUndelegate" => { + // WARNING: RETURNING THIS ERROR CLOSES THE CHANNEL. + // AN ALTERNATIVE IS TO MAINTAIN AN ERRORS QUEUE AND PUT THE FAILED REQUEST THERE + // FOR LATER INSPECTION. + // In this particular case, a mismatch between the string message type and the + // serialised data layout looks like a fatal error that has to be investigated. let out: MsgUndelegateResponse = decode_message_response(&item.data)?; + // NOTE: NO ERROR IS RETURNED HERE. THE CHANNEL LIVES ON. + // In this particular case, we demonstrate that minor errors should not + // close the channel, and should be treated in a forgiving manner. let completion_time = out.completion_time.or_else(|| { let error_msg = "WASMDEBUG: sudo_response: Recoverable error. Failed to get completion time"; deps.api @@ -631,6 +621,11 @@ fn sudo_response( .debug(format!("Undelegation completion time: {:?}", completion_time).as_str()); } "/cosmos.staking.v1beta1.MsgDelegate" => { + // WARNING: RETURNING THIS ERROR CLOSES THE CHANNEL. + // AN ALTERNATIVE IS TO MAINTAIN AN ERRORS QUEUE AND PUT THE FAILED REQUEST THERE + // FOR LATER INSPECTION. + // In this particular case, a mismatch between the string message type and the + // serialised data layout looks like a fatal error that has to be investigated. let _out: MsgDelegateResponse = decode_message_response(&item.data)?; } _ => { @@ -702,15 +697,33 @@ fn sudo_timeout( deps.api .debug(format!("WASMDEBUG: sudo timeout request: {:?}", request).as_str()); + // WARNING: RETURNING THIS ERROR CLOSES THE CHANNEL. + // AN ALTERNATIVE IS TO MAINTAIN AN ERRORS QUEUE AND PUT THE FAILED REQUEST THERE + // FOR LATER INSPECTION. + // In this particular case, we return an error because not having the sequence id + // in the request value implies that a fatal error occurred on Neutron side. let seq_id = request .sequence .ok_or_else(|| StdError::generic_err("sequence not found"))?; + // WARNING: RETURNING THIS ERROR CLOSES THE CHANNEL. + // AN ALTERNATIVE IS TO MAINTAIN AN ERRORS QUEUE AND PUT THE FAILED REQUEST THERE + // FOR LATER INSPECTION. + // In this particular case, we return an error because not having the sequence id + // in the request value implies that a fatal error occurred on Neutron side. let channel_id = request .source_channel .ok_or_else(|| StdError::generic_err("channel_id not found"))?; // update but also check that we don't update same seq_id twice + // NOTE: NO ERROR IS RETURNED HERE. THE CHANNEL LIVES ON. + // In this particular example, this is a matter of developer's choice. Not being able to read + // the payload here means that there was a problem with the contract while submitting an + // interchain transaction. You can decide that this is not worth killing the channel, + // write an error log and / or save the acknowledgement to an errors queue for later manual + // processing. The decision is based purely on your application logic. + // Please be careful because it may lead to an unexpected state changes because state might + // has been changed before this call and will not be reverted because of supressed error. let payload = read_sudo_payload(deps.storage, channel_id, seq_id).ok(); if let Some(payload) = payload { // update but also check that we don't update same seq_id twice @@ -743,10 +756,20 @@ fn sudo_error( deps.api .debug(format!("WASMDEBUG: request packet: {:?}", request).as_str()); + // WARNING: RETURNING THIS ERROR CLOSES THE CHANNEL. + // AN ALTERNATIVE IS TO MAINTAIN AN ERRORS QUEUE AND PUT THE FAILED REQUEST THERE + // FOR LATER INSPECTION. + // In this particular case, we return an error because not having the sequence id + // in the request value implies that a fatal error occurred on Neutron side. let seq_id = request .sequence .ok_or_else(|| StdError::generic_err("sequence not found"))?; + // WARNING: RETURNING THIS ERROR CLOSES THE CHANNEL. + // AN ALTERNATIVE IS TO MAINTAIN AN ERRORS QUEUE AND PUT THE FAILED REQUEST THERE + // FOR LATER INSPECTION. + // In this particular case, we return an error because not having the sequence id + // in the request value implies that a fatal error occurred on Neutron side. let channel_id = request .source_channel .ok_or_else(|| StdError::generic_err("channel_id not found"))?; @@ -811,7 +834,7 @@ pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> StdResult { match msg.id { SUDO_PAYLOAD_REPLY_ID => prepare_sudo_payload(deps, env, msg), SUDO_FAILING_SUBMSG_REPLY_ID => { - if let Some(IntegrationTestsSudoSubmsgFailureMock::EnabledInReply {}) = + if let Some(IntegrationTestsSudoSubmsgMock::EnabledInReply {}) = INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK.may_load(deps.storage)? { // Used only in integration tests framework to simulate failures. @@ -819,7 +842,7 @@ pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> StdResult { .debug("WASMDEBUG: sudo: mocked reply failure on the handler"); return Err(StdError::GenericErr { - msg: "Integrations test mock reply error".to_string(), + msg: "Integations test mock reply error".to_string(), }); } Ok(Response::default()) diff --git a/contracts/neutron_interchain_txs/src/integration_tests_mock_handlers.rs b/contracts/neutron_interchain_txs/src/integration_tests_mock_handlers.rs index 2648c6c..9badfc0 100644 --- a/contracts/neutron_interchain_txs/src/integration_tests_mock_handlers.rs +++ b/contracts/neutron_interchain_txs/src/integration_tests_mock_handlers.rs @@ -1,40 +1,32 @@ use crate::storage::{ - IntegrationTestsSudoFailureMock, IntegrationTestsSudoSubmsgFailureMock, - INTEGRATION_TESTS_SUDO_FAILURE_MOCK, INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK, + IntegrationTestsSudoMock, IntegrationTestsSudoSubmsgMock, INTEGRATION_TESTS_SUDO_FAILURE_MOCK, + INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK, }; use cosmwasm_std::{DepsMut, Response, StdResult}; use neutron_sdk::bindings::msg::NeutronMsg; -pub fn set_sudo_failure_mock( - deps: DepsMut, - state: IntegrationTestsSudoFailureMock, -) -> StdResult> { - INTEGRATION_TESTS_SUDO_FAILURE_MOCK.save(deps.storage, &state)?; +pub fn set_sudo_failure_mock(deps: DepsMut) -> StdResult> { + INTEGRATION_TESTS_SUDO_FAILURE_MOCK.save(deps.storage, &IntegrationTestsSudoMock::Enabled)?; Ok(Response::default()) } pub fn set_sudo_submsg_failure_mock(deps: DepsMut) -> StdResult> { - INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK.save( - deps.storage, - &IntegrationTestsSudoSubmsgFailureMock::Enabled, - )?; + INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK + .save(deps.storage, &IntegrationTestsSudoSubmsgMock::Enabled)?; Ok(Response::default()) } pub fn set_sudo_submsg_failure_in_reply_mock(deps: DepsMut) -> StdResult> { INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK.save( deps.storage, - &IntegrationTestsSudoSubmsgFailureMock::EnabledInReply, + &IntegrationTestsSudoSubmsgMock::EnabledInReply, )?; Ok(Response::default()) } pub fn unset_sudo_failure_mock(deps: DepsMut) -> StdResult> { - INTEGRATION_TESTS_SUDO_FAILURE_MOCK - .save(deps.storage, &IntegrationTestsSudoFailureMock::Disabled)?; - INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK.save( - deps.storage, - &IntegrationTestsSudoSubmsgFailureMock::Disabled, - )?; + INTEGRATION_TESTS_SUDO_FAILURE_MOCK.save(deps.storage, &IntegrationTestsSudoMock::Disabled)?; + INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK + .save(deps.storage, &IntegrationTestsSudoSubmsgMock::Disabled)?; Ok(Response::default()) } diff --git a/contracts/neutron_interchain_txs/src/msg.rs b/contracts/neutron_interchain_txs/src/msg.rs index 7866370..b63ffbe 100644 --- a/contracts/neutron_interchain_txs/src/msg.rs +++ b/contracts/neutron_interchain_txs/src/msg.rs @@ -1,4 +1,4 @@ -use crate::storage::{AcknowledgementResult, IntegrationTestsSudoFailureMock}; +use crate::storage::AcknowledgementResult; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -66,14 +66,9 @@ pub enum ExecuteMsg { timeout: Option, }, CleanAckResults {}, - ResubmitFailure { - failure_id: u64, - }, /// Used only in integration tests framework to simulate failures. /// After executing this message, any sudo call to the contract will result in an error. - IntegrationTestsSetSudoFailureMock { - state: IntegrationTestsSudoFailureMock, - }, + IntegrationTestsSetSudoFailureMock {}, /// Used only in integration tests framework to simulate failures. /// After executing this message, any sudo call to the contract will result in an submessage /// processing error. diff --git a/contracts/neutron_interchain_txs/src/storage.rs b/contracts/neutron_interchain_txs/src/storage.rs index 1601343..87a1959 100644 --- a/contracts/neutron_interchain_txs/src/storage.rs +++ b/contracts/neutron_interchain_txs/src/storage.rs @@ -93,28 +93,22 @@ pub fn save_sudo_payload( } /// Used only in integration tests framework to simulate failures in sudo handler. -pub const INTEGRATION_TESTS_SUDO_FAILURE_MOCK: Item = +pub const INTEGRATION_TESTS_SUDO_FAILURE_MOCK: Item = Item::new("integration_tests_sudo_failure_mock"); /// Used only in integration tests framework to simulate failures in submessages created in /// sudo handler. -pub const INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK: Item = +pub const INTEGRATION_TESTS_SUDO_SUBMSG_FAILURE_MOCK: Item = Item::new("integration_tests_sudo_submsg_failure_mock"); #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum IntegrationTestsSudoFailureMock { +pub enum IntegrationTestsSudoMock { Enabled, - EnabledInfiniteLoop, Disabled, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum IntegrationTestsSudoSubmsgFailureMock { +pub enum IntegrationTestsSudoSubmsgMock { Enabled, EnabledInReply, Disabled, } - -// just to do something in infinite loop -pub const TEST_COUNTER_ITEM: Item = Item::new("test_counter"); diff --git a/contracts/neutron_interchain_txs/src/testing/tests.rs b/contracts/neutron_interchain_txs/src/testing/tests.rs index 17d312b..207960c 100644 --- a/contracts/neutron_interchain_txs/src/testing/tests.rs +++ b/contracts/neutron_interchain_txs/src/testing/tests.rs @@ -12,7 +12,6 @@ use crate::contract::sudo; use crate::msg::ExecuteMsg; -use crate::storage::IntegrationTestsSudoFailureMock; use crate::{ contract::{execute, query_errors_queue}, storage::{add_error_to_queue, read_errors_from_queue, ERRORS_QUEUE}, @@ -102,9 +101,7 @@ fn test_failure_mocks() { deps.as_mut(), mock_env(), mock_info("", &[]), - ExecuteMsg::IntegrationTestsSetSudoFailureMock { - state: IntegrationTestsSudoFailureMock::Enabled, - }, + ExecuteMsg::IntegrationTestsSetSudoFailureMock {}, ) .unwrap(); @@ -126,5 +123,5 @@ fn test_failure_mocks() { }; let err = sudo(deps.as_mut(), mock_env(), sudo_resp).unwrap_err(); - assert_eq!(err, StdError::generic_err("Integrations test mock error")); + assert_eq!(err, StdError::generic_err("Integations test mock error")); } diff --git a/contracts/reflect/README.md b/contracts/reflect/README.md index 32ff5c2..aa085dd 100644 --- a/contracts/reflect/README.md +++ b/contracts/reflect/README.md @@ -1,3 +1,3 @@ # Reflect -This contract is used for tests in the main neutron repository. +This contract is used for tests in the main neutron repository. \ No newline at end of file diff --git a/contracts/stargate_querier/src/contract.rs b/contracts/stargate_querier/src/contract.rs index b5b4c63..189fccb 100644 --- a/contracts/stargate_querier/src/contract.rs +++ b/contracts/stargate_querier/src/contract.rs @@ -71,6 +71,12 @@ pub fn query(deps: Deps, _: Env, msg: QueryMsg) -> NeutronResult { QueryMsg::TokenfactoryDenomsFromCreator { creator } => { query_tokenfactory_denoms_from_creator(deps, creator) } + QueryMsg::ContractmanagerAddressFailures { address } => { + query_contractmanager_query_address_failures(deps, address) + } + QueryMsg::ContractmanagerFailures { address } => { + query_contractmanager_query_failures(deps, address) + } QueryMsg::InterchaintxParams {} => query_interchaintx_params(deps), QueryMsg::InterchainqueriesParams {} => query_interchainqueries_params(deps), QueryMsg::FeeburnerParams {} => query_feeburner_params(deps), @@ -231,6 +237,34 @@ fn query_tokenfactory_denoms_from_creator(deps: Deps, creator: String) -> Neutro Ok(to_binary(&resp)?) } +fn query_contractmanager_query_address_failures( + deps: Deps, + address: String, +) -> NeutronResult { + let msg = stargate::contractmanager::QueryAddressFailuresRequest { address }; + let resp = make_stargate_query( + deps, + "/neutron.contractmanager.Query/AddressFailures".to_string(), + msg.encode_to_vec(), + )?; + + Ok(to_binary(&resp)?) +} + +fn query_contractmanager_query_failures(deps: Deps, address: String) -> NeutronResult { + let msg = stargate::contractmanager::QueryFailuresRequest { + address, + pagination: None, + }; + let resp = make_stargate_query( + deps, + "/neutron.contractmanager.Query/Failures".to_string(), + msg.encode_to_vec(), + )?; + + Ok(to_binary(&resp)?) +} + fn query_interchaintx_params(deps: Deps) -> NeutronResult { let msg = stargate::interchaintx::QueryParams {}; let resp = make_stargate_query( diff --git a/contracts/stargate_querier/src/msg.rs b/contracts/stargate_querier/src/msg.rs index b590dd2..61b0022 100644 --- a/contracts/stargate_querier/src/msg.rs +++ b/contracts/stargate_querier/src/msg.rs @@ -47,6 +47,12 @@ pub enum QueryMsg { TokenfactoryDenomsFromCreator { creator: String, }, + ContractmanagerAddressFailures { + address: String, + }, + ContractmanagerFailures { + address: String, + }, InterchaintxParams {}, InterchainqueriesParams {}, FeeburnerParams {}, diff --git a/contracts/stargate_querier/src/stargate.rs b/contracts/stargate_querier/src/stargate.rs index 5dc823d..9f25dfc 100644 --- a/contracts/stargate_querier/src/stargate.rs +++ b/contracts/stargate_querier/src/stargate.rs @@ -15,3 +15,20 @@ pub mod feeburner { #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryTotalBurnedNeutronsAmountRequest {} } + +pub mod contractmanager { + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct QueryAddressFailuresRequest { + #[prost(string, tag = "1")] + pub address: ::prost::alloc::string::String, + } + + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct QueryFailuresRequest { + #[prost(string, tag = "1")] + pub address: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub pagination: + ::core::option::Option<::cosmos_sdk_proto::cosmos::base::query::v1beta1::PageRequest>, + } +}