Skip to content

Commit

Permalink
implemented propagation of out-of-gas events from the FFI to the wasm…
Browse files Browse the repository at this point in the history
…er VM instance
  • Loading branch information
reuvenpo committed May 13, 2020
1 parent a89e9f8 commit c6f578a
Show file tree
Hide file tree
Showing 18 changed files with 570 additions and 428 deletions.
15 changes: 8 additions & 7 deletions contracts/hackatom/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Then running `cargo integration-test` will validate we can properly call into that generated Wasm.
//!
//! You can easily convert unit tests to integration tests.
//! 1. First copy them over verbatum,
//! 1. First copy them over verbatim,
//! 2. Then change
//! let mut deps = mock_dependencies(20);
//! to
Expand All @@ -17,14 +17,15 @@
//! });
//! 4. Anywhere you see query(&deps, ...) you must replace it with query(&mut deps, ...)
use cosmwasm_std::testing::mock_env;
use cosmwasm_std::{
coins, from_binary, log, AllBalanceResponse, Api, BankMsg, HandleResponse, HandleResult,
HumanAddr, InitResponse, InitResult, ReadonlyStorage, StdError,
coins, from_binary, log, AllBalanceResponse, BankMsg, HandleResponse, HandleResult, HumanAddr,
InitResponse, InitResult, StdError,
};
use cosmwasm_vm::from_slice;
use cosmwasm_vm::testing::{
handle, init, mock_instance, mock_instance_with_balances, query, test_io,
use cosmwasm_vm::{
from_slice,
mock::mock_env,
testing::{handle, init, mock_instance, mock_instance_with_balances, query, test_io},
Api, ReadonlyStorage,
};

use hackatom::contract::{HandleMsg, InitMsg, QueryMsg, State, CONFIG_KEY};
Expand Down
8 changes: 5 additions & 3 deletions contracts/queue/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
//! });
//! 4. Anywhere you see query(&deps, ...) you must replace it with query(&mut deps, ...)
use cosmwasm_std::testing::{mock_env, MockApi, MockQuerier, MockStorage};
use cosmwasm_std::{from_binary, from_slice, Env, HandleResponse, HumanAddr, InitResponse};
use cosmwasm_vm::testing::{handle, init, mock_instance, query};
use cosmwasm_vm::Instance;
use cosmwasm_vm::{
mock::{mock_env, MockApi, MockQuerier, MockStorage},
testing::{handle, init, mock_instance, query},
Instance,
};

use queue::contract::{
CountResponse, HandleMsg, InitMsg, Item, QueryMsg, ReducerResponse, SumResponse,
Expand Down
4 changes: 2 additions & 2 deletions contracts/reflect/src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ impl Querier for CustomQuerier {
// parse into our custom query class
let request: QueryRequest<CustomQuery> = match from_slice(bin_request) {
Ok(v) => v,
Err(e) => {
Err(_) => {
return Err(SystemError::InvalidRequest {
error: format!("Parsing QueryRequest: {}", e),
msg: bin_request.to_vec(),
})
}
};
Expand Down
67 changes: 61 additions & 6 deletions contracts/reflect/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,78 @@
//! });
//! 4. Anywhere you see query(&deps, ...) you must replace it with query(&mut deps, ...)
use cosmwasm_std::testing::mock_env;
use cosmwasm_std::{
coin, coins, from_binary, Api, BankMsg, Binary, HandleResponse, HandleResult, HumanAddr,
coin, coins, from_binary, BankMsg, Binary, HandleResponse, HandleResult, HumanAddr,
InitResponse, StakingMsg, StdError,
};
use cosmwasm_vm::{
mock::mock_env,
testing::{handle, init, mock_instance, query},
Api, Instance,
};

use cosmwasm_vm::testing::{handle, init, mock_instance, query};
use cosmwasm_vm::Instance;

use mock::mock_dependencies;
use reflect::msg::{CustomMsg, CustomResponse, HandleMsg, InitMsg, OwnerResponse, QueryMsg};
use reflect::testing::mock_dependencies;

// This line will test the output of cargo wasm
static WASM: &[u8] = include_bytes!("../target/wasm32-unknown-unknown/release/reflect.wasm");
// You can uncomment this line instead to test productionified build from cosmwasm-opt
// static WASM: &[u8] = include_bytes!("../contract.wasm");

mod mock {
use reflect::msg::{CustomQuery, CustomResponse};

use cosmwasm_std::{from_slice, to_binary, Binary, Coin, QueryRequest, StdResult};
use cosmwasm_vm::{
mock::{MockApi, MockQuerier, MockStorage},
Extern, FfiError, Querier, QuerierResult,
};

#[derive(Clone)]
pub struct CustomQuerier {
base: MockQuerier,
}

impl CustomQuerier {
pub fn new(base: MockQuerier) -> Self {
CustomQuerier { base }
}
}

impl Querier for CustomQuerier {
fn raw_query(&self, bin_request: &[u8]) -> QuerierResult {
// parse into our custom query class
let request: QueryRequest<CustomQuery> = match from_slice(bin_request) {
Ok(v) => v,
Err(_) => return Err(FfiError::Other),
};
if let QueryRequest::Custom(custom_query) = &request {
Ok(Ok(execute(&custom_query)))
} else {
self.base.handle_query(&request)
}
}
}

/// mock_dependencies is a drop-in replacement for cosmwasm_std::testing::mock_dependencies
/// this uses our CustomQuerier.
pub fn mock_dependencies(
canonical_length: usize,
contract_balance: &[Coin],
) -> Extern<MockStorage, MockApi, CustomQuerier> {
let base = cosmwasm_vm::mock::mock_dependencies(canonical_length, contract_balance);
base.change_querier(CustomQuerier::new)
}

fn execute(query: &CustomQuery) -> StdResult<Binary> {
let msg = match query {
CustomQuery::Ping {} => "pong".to_string(),
CustomQuery::Capital { text } => text.to_uppercase(),
};
to_binary(&CustomResponse { msg })
}
}

#[test]
fn proper_initialization() {
let mut deps = mock_instance(WASM, &[]);
Expand Down
16 changes: 11 additions & 5 deletions packages/std/src/errors/system_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};

use crate::HumanAddr;

/// SystemError is used for errors inside the VM and is API frindly (i.e. serializable).
/// SystemError is used for errors inside the VM and is API friendly (i.e. serializable).
///
/// This is used on return values for Querier as a nested result: Result<StdResult<T>, SystemError>
/// The first wrap (SystemError) will trigger if the contract address doesn't exist,
Expand All @@ -16,9 +16,10 @@ use crate::HumanAddr;
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum SystemError {
InvalidRequest { error: String },
InvalidRequest { msg: Vec<u8> },
InvalidResponse { msg: Vec<u8> },
NoSuchContract { addr: HumanAddr },
Unknown {},
Unknown,
UnsupportedRequest { kind: String },
}

Expand All @@ -27,9 +28,14 @@ impl std::error::Error for SystemError {}
impl std::fmt::Display for SystemError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SystemError::InvalidRequest { error } => write!(f, "Cannot parse request: {}", error),
SystemError::InvalidRequest { msg } => {
write!(f, "Cannot parse request: {}", String::from_utf8_lossy(msg))
}
SystemError::InvalidResponse { msg } => {
write!(f, "Cannot parse response: {}", String::from_utf8_lossy(msg))
}
SystemError::NoSuchContract { addr } => write!(f, "No such contract: {}", addr),
SystemError::Unknown {} => write!(f, "Unknown system error"),
SystemError::Unknown => write!(f, "Unknown system error"),
SystemError::UnsupportedRequest { kind } => write!(f, "Unsupport query type: {}", kind),
}
}
Expand Down
4 changes: 3 additions & 1 deletion packages/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ pub use crate::query::{
pub use crate::serde::{from_binary, from_slice, to_binary, to_vec};
pub use crate::storage::MemoryStorage;
pub use crate::traits::{Api, Extern, Querier, QuerierResult, ReadonlyStorage, Storage};
pub use crate::types::{CanonicalAddr, Env, HumanAddr, Never};
pub use crate::types::{
BlockInfo, CanonicalAddr, ContractInfo, Env, HumanAddr, MessageInfo, Never,
};

#[cfg(feature = "staking")]
pub use crate::init_handle::StakingMsg;
Expand Down
4 changes: 2 additions & 2 deletions packages/std/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ impl Querier for MockQuerier {
// MockQuerier doesn't support Custom, so we ignore it completely here
let request: QueryRequest<Never> = match from_slice(bin_request) {
Ok(v) => v,
Err(e) => {
Err(_) => {
return Err(SystemError::InvalidRequest {
error: format!("Parsing QueryRequest: {}", e),
msg: bin_request.to_vec(),
})
}
};
Expand Down
4 changes: 2 additions & 2 deletions packages/vm/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::path::PathBuf;
use lru::LruCache;
use snafu::ResultExt;

use cosmwasm_std::{Api, Extern, Querier, Storage};
use crate::traits::{Api, Extern, Querier, Storage};

use crate::backends::{backend, compile};
use crate::compatability::check_wasm;
Expand Down Expand Up @@ -141,7 +141,7 @@ mod test {
use super::*;
use crate::calls::{call_handle, call_init};
use crate::errors::VmError;
use cosmwasm_std::testing::{mock_dependencies, mock_env, MockApi, MockQuerier, MockStorage};
use crate::mock::{mock_dependencies, mock_env, MockApi, MockQuerier, MockStorage};
use cosmwasm_std::{coins, Never};
use tempfile::TempDir;

Expand Down
5 changes: 3 additions & 2 deletions packages/vm/src/calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ use snafu::ResultExt;
use std::fmt;

use cosmwasm_std::{
Api, Env, HandleResponse, HandleResult, InitResponse, InitResult, Querier, QueryResponse,
QueryResult, StdResult, Storage,
Env, HandleResponse, HandleResult, InitResponse, InitResult, QueryResponse, QueryResult,
StdResult,
};

use crate::errors::{RuntimeErr, VmResult, WasmerRuntimeErr};
use crate::instance::{Func, Instance};
use crate::serde::{from_slice, to_vec};
use crate::traits::{Api, Querier, Storage};
use schemars::JsonSchema;

static MAX_LENGTH_INIT: usize = 100_000;
Expand Down
Loading

0 comments on commit c6f578a

Please sign in to comment.