diff --git a/cosmwasm/enclaves/shared/block-verifier/src/submit_block_signatures.rs b/cosmwasm/enclaves/shared/block-verifier/src/submit_block_signatures.rs index a50f8402f..3e59f0948 100644 --- a/cosmwasm/enclaves/shared/block-verifier/src/submit_block_signatures.rs +++ b/cosmwasm/enclaves/shared/block-verifier/src/submit_block_signatures.rs @@ -153,7 +153,7 @@ pub unsafe fn submit_block_signatures_impl( if header.header.height.value() != 1 && rp.app_hash != header.header.app_hash.as_bytes() { error!("error verifying app hash!"); debug!("calculated app_hash bytes {:?}", rp.app_hash); - debug!("header app_hash bytes {:?}", header.app_hash.as_bytes()); + // debug!("header app_hash bytes {:?}", header.app_hash.as_bytes()); return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } } diff --git a/integration-tests/contract-v0.10/src/contract.rs b/integration-tests/contract-v0.10/src/contract.rs index 68e2cae87..467f62e19 100644 --- a/integration-tests/contract-v0.10/src/contract.rs +++ b/integration-tests/contract-v0.10/src/contract.rs @@ -1,8 +1,4 @@ -use cosmwasm_std::{ - to_binary, Api, BalanceResponse, BankMsg, BankQuery, Binary, Coin, CosmosMsg, Empty, Env, - Extern, GovMsg, HandleResponse, HandleResult, HumanAddr, InitResponse, InitResult, - LogAttribute, Querier, QueryRequest, QueryResult, StakingMsg, Storage, VoteOption, WasmMsg, -}; +use cosmwasm_std::{to_binary, Api, BalanceResponse, BankMsg, BankQuery, Binary, Coin, CosmosMsg, Empty, Env, Extern, GovMsg, HandleResponse, HandleResult, HumanAddr, InitResponse, InitResult, LogAttribute, Querier, QueryRequest, QueryResult, StakingMsg, Storage, VoteOption, WasmMsg, StdError}; /////////////////////////////// Messages /////////////////////////////// @@ -56,21 +52,29 @@ pub enum Msg { send: Vec, }, CustomMsg {}, + Forward { + recipient_address: HumanAddr, + recipient_hash: String, + msg: Binary, + }, + FailTx {} } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryMsg { BankBalance { address: HumanAddr, denom: String }, + Forward {}, } /////////////////////////////// Init /////////////////////////////// pub fn init( - _deps: &mut Extern, + deps: &mut Extern, _env: Env, _msg: Msg, ) -> InitResult { + deps.storage.set("forwarded".as_bytes(), "no-fail".as_bytes()); return Ok(InitResponse { messages: vec![], log: vec![], @@ -80,7 +84,7 @@ pub fn init( /////////////////////////////// Handle /////////////////////////////// pub fn handle( - _deps: &mut Extern, + deps: &mut Extern, env: Env, msg: Msg, ) -> HandleResult { @@ -192,6 +196,22 @@ pub fn handle( log: vec![], data: None, }), + Msg::Forward { recipient_address, recipient_hash, msg } => { + deps.storage.set("forwarded".as_bytes(), "forwarded".as_bytes()); + Ok(HandleResponse { + messages: vec![CosmosMsg::Wasm( + WasmMsg::Execute { + contract_addr: recipient_address, + callback_code_hash: recipient_hash, + msg, + send: vec![] + }, + )], + log: vec![], + data: None, + }) + } + Msg::FailTx {} => Err (StdError::generic_err("this should always fail")), } } @@ -208,5 +228,7 @@ pub fn query(deps: &Extern, msg: QueryM }))?; return Ok(to_binary(&res)?); } + QueryMsg::Forward { } => Ok(to_binary(&deps.storage.get("forwarded".as_bytes()))?), } + } diff --git a/integration-tests/contract-v1/src/contract.rs b/integration-tests/contract-v1/src/contract.rs index 78864b4d1..102656ee8 100644 --- a/integration-tests/contract-v1/src/contract.rs +++ b/integration-tests/contract-v1/src/contract.rs @@ -1,17 +1,10 @@ use crate::ibc::PACKET_LIFETIME; -use cosmwasm_std::{ - entry_point, to_binary, to_vec, AllBalanceResponse, AllDelegationsResponse, - AllValidatorsResponse, BalanceResponse, BankMsg, BankQuery, Binary, BondedDenomResponse, - ChannelResponse, ContractInfoResponse, ContractResult, CosmosMsg, DelegationResponse, Deps, - DepsMut, DistributionMsg, Empty, Env, Event, GovMsg, IbcMsg, IbcQuery, IbcTimeout, - ListChannelsResponse, MessageInfo, PortIdResponse, QueryRequest, Response, StakingMsg, - StakingQuery, StdError, StdResult, ValidatorResponse, WasmMsg, WasmQuery, -}; +use cosmwasm_std::{entry_point, to_binary, to_vec, AllBalanceResponse, AllDelegationsResponse, AllValidatorsResponse, BalanceResponse, BankMsg, BankQuery, Binary, BondedDenomResponse, ChannelResponse, ContractInfoResponse, ContractResult, CosmosMsg, DelegationResponse, Deps, DepsMut, DistributionMsg, Empty, Env, Event, GovMsg, IbcMsg, IbcQuery, IbcTimeout, ListChannelsResponse, MessageInfo, PortIdResponse, QueryRequest, Response, StakingMsg, StakingQuery, StdError, StdResult, ValidatorResponse, WasmMsg, WasmQuery, SubMsg}; use crate::msg::{Msg, PacketMsg, QueryMsg}; use crate::state::{ ack_store, ack_store_read, channel_store, channel_store_read, receive_store, - receive_store_read, timeout_store, timeout_store_read, + receive_store_read, timeout_store, timeout_store_read, forward_store, forward_store_read, }; #[entry_point] @@ -20,6 +13,7 @@ pub fn instantiate(deps: DepsMut, env: Env, info: MessageInfo, msg: Msg) -> StdR ack_store(deps.storage).save(&"no ack yet".to_string())?; receive_store(deps.storage).save(&"no receive yet".to_string())?; timeout_store(deps.storage).save(&"no timeout yet".to_string())?; + forward_store(deps.storage).save(&"no-fail".to_string())?; return handle_msg(deps, env, info, msg); } @@ -29,7 +23,7 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: Msg) -> StdResul return handle_msg(deps, env, info, msg); } -fn handle_msg(deps: DepsMut, env: Env, info: MessageInfo, msg: Msg) -> StdResult { +fn handle_msg(deps: DepsMut, env: Env, _info: MessageInfo, msg: Msg) -> StdResult { match msg { Msg::Nop {} => { return Ok(Response::new().set_data(vec![137, 137].as_slice())); @@ -181,6 +175,19 @@ fn handle_msg(deps: DepsMut, env: Env, info: MessageInfo, msg: Msg) -> StdResult )) } }, + Msg::Forward { recipient_address, recipient_hash, msg } => { + forward_store(deps.storage).save(&"forwarded".to_string())?; + Ok(Response::new().add_submessage(SubMsg::new(CosmosMsg::Wasm( + WasmMsg::Execute { + contract_addr: recipient_address.into_string(), + code_hash: recipient_hash, + msg, + funds: vec![], + }, + )) + )) + } + Msg::FailTx {} => Err (StdError::generic_err("this should always fail")), // Msg::GetRandom {} => { // return Ok( // Response::new() @@ -295,5 +302,6 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { QueryMsg::LastIbcReceive {} => Ok(to_binary(&receive_store_read(deps.storage).load()?)?), QueryMsg::LastIbcAck {} => Ok(to_binary(&ack_store_read(deps.storage).load()?)?), QueryMsg::LastIbcTimeout {} => Ok(to_binary(&timeout_store_read(deps.storage).load()?)?), + QueryMsg::Forward {} => Ok(to_binary(&forward_store_read(deps.storage).load()?)?), } } diff --git a/integration-tests/contract-v1/src/msg.rs b/integration-tests/contract-v1/src/msg.rs index 9d172d28a..07c96b0e1 100644 --- a/integration-tests/contract-v1/src/msg.rs +++ b/integration-tests/contract-v1/src/msg.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Binary, Coin, IbcTimeout, VoteOption}; +use cosmwasm_std::{Addr, Binary, Coin, IbcTimeout, VoteOption}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -72,6 +72,12 @@ pub enum Msg { funds: Vec, }, GetTxId {}, + Forward { + recipient_address: Addr, + recipient_hash: String, + msg: Binary, + }, + FailTx {} //GetRandom {}, } @@ -121,6 +127,7 @@ pub enum QueryMsg { LastIbcReceive {}, LastIbcAck {}, LastIbcTimeout {}, + Forward {}, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] diff --git a/integration-tests/contract-v1/src/state.rs b/integration-tests/contract-v1/src/state.rs index c9cc12990..980f40b36 100644 --- a/integration-tests/contract-v1/src/state.rs +++ b/integration-tests/contract-v1/src/state.rs @@ -5,6 +5,7 @@ pub const CHANNEL_KEY: &[u8] = b"channel"; pub const ACK_KEY: &[u8] = b"ack"; pub const RECEIVE_KEY: &[u8] = b"receive"; pub const TIMEOUT_KEY: &[u8] = b"timeout"; +pub const FORWARD_KEY: &[u8] = b"forward"; pub fn channel_store(storage: &mut dyn Storage) -> Singleton { singleton(storage, CHANNEL_KEY) @@ -37,3 +38,11 @@ pub fn timeout_store(storage: &mut dyn Storage) -> Singleton { pub fn timeout_store_read(storage: &dyn Storage) -> ReadonlySingleton { singleton_read(storage, TIMEOUT_KEY) } + +pub fn forward_store(storage: &mut dyn Storage) -> Singleton { + singleton(storage, FORWARD_KEY) +} + +pub fn forward_store_read(storage: &dyn Storage) -> ReadonlySingleton { + singleton_read(storage, FORWARD_KEY) +} diff --git a/integration-tests/test.ts b/integration-tests/test.ts index 94210b209..1a225046a 100644 --- a/integration-tests/test.ts +++ b/integration-tests/test.ts @@ -134,7 +134,7 @@ beforeAll(async () => { }; } - // Send 100k SCRT from account 0 to each of accounts 1-itrations + // Send 100k SCRT from account 0 to each of accounts 1-iterations const { secretjs } = accounts[0]; @@ -520,6 +520,83 @@ describe("CustomMsg", () => { }); }); +describe.only("Rollback", () => { + test("v0.10", async () => { + const tx = await accounts[0].secretjs.tx.compute.executeContract( + { + sender: accounts[0].address, + contract_address: contracts["secretdev-1"].v010.address, + code_hash: contracts["secretdev-1"].v010.codeHash, + msg: { + forward: { + msg: toBase64(toUtf8(JSON.stringify({ fail_tx: {} }))), + recipient_address: contracts["secretdev-1"].v1.address, + recipient_hash: contracts["secretdev-1"].v1.codeHash, + } + }, + }, + { gasLimit: 250_000 } + ); + + if (tx.code !== 3) { + console.error(tx.rawLog); + } + expect(tx.code).toBe(3 /* WASM ErrExecuteFailed */); + expect(tx.rawLog).toContain("execute contract failed"); + + console.log("querying v10 contract state"); + // verify the value rolled back + const result: any = await readonly.query.compute.queryContract({ + contract_address: contracts["secretdev-1"].v010.address, + code_hash: contracts["secretdev-1"].v010.codeHash, + query: { + forward: {}, + } + }); + + let resultString = String.fromCharCode(...result) + console.log("got result:", resultString); + + expect(resultString).toBe("no-fail"); + }); + + test("v1", async () => { + const tx = await accounts[0].secretjs.tx.compute.executeContract( + { + sender: accounts[0].address, + contract_address: contracts["secretdev-1"].v1.address, + code_hash: contracts["secretdev-1"].v1.codeHash, + msg: { + forward: { + msg: toBase64(toUtf8(JSON.stringify({ fail_tx: {} }))), + recipient_address: contracts["secretdev-1"].v010.address, + recipient_hash: contracts["secretdev-1"].v010.codeHash, + } + }, + }, + { gasLimit: 250_000 } + ); + + if (tx.code !== 3) { + console.error(tx.rawLog); + } + expect(tx.code).toBe(3 /* WASM ErrExecuteFailed */); + expect(tx.rawLog).toContain("execute contract failed"); + + console.log("querying v1 contract state"); + // verify the value rolled back + const result: any = await readonly.query.compute.queryContract({ + contract_address: contracts["secretdev-1"].v1.address, + code_hash: contracts["secretdev-1"].v1.codeHash, + query: { + forward: {}, + } + }); + + expect(result).toBe("no-fail"); + }); +}); + describe("tx broadcast multi", () => { test("Send Multiple Messages Amino", async () => { const { validators } = await readonly.query.staking.validators({}); @@ -896,6 +973,7 @@ describe("Wasm", () => { expect(tx.rawLog).toContain("execute contract failed"); }); + }); describe("v0.10", () => { @@ -957,6 +1035,7 @@ describe("Wasm", () => { expect(tx.rawLog).toContain("execute contract failed"); }); + }); }); }); diff --git a/scripts/start-node.sh b/scripts/start-node.sh index f67142fe9..ab25a97de 100755 --- a/scripts/start-node.sh +++ b/scripts/start-node.sh @@ -9,7 +9,7 @@ CHAINID=${3:-secretdev-1} rm -rf $SECRETD_HOME # Build genesis file incl account for passed address -coins="10000000000uscrt,100000000000stake" +coins="1000000000000000000uscrt,100000000000stake" $SECRETD init --chain-id $CHAINID $CHAINID --home $SECRETD_HOME $SECRETD keys add validator --keyring-backend="test" --home $SECRETD_HOME $SECRETD add-genesis-account $($SECRETD keys show validator -a --keyring-backend="test" --home $SECRETD_HOME) $coins --home $SECRETD_HOME