diff --git a/Cargo.toml b/Cargo.toml index 8551a418b..96febcf5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,8 +24,10 @@ singlepass = ["cosmwasm-vm/default-singlepass"] cranelift = ["cosmwasm-vm/default-cranelift"] [dependencies] -cosmwasm-std = { git = "https://github.com/CosmWasm/cosmwasm", rev = "71f643f577184a23b2f1f122531c944f0de94c34", features = ["iterator"]} -cosmwasm-vm = { git = "https://github.com/CosmWasm/cosmwasm", rev = "71f643f577184a23b2f1f122531c944f0de94c34", features = ["iterator"] } +cosmwasm-std = { git = "https://github.com/reuvenpo/cosmwasm", rev = "c6f578a09ab331baa43413332bf488e9be7a76c0", features = ["iterator"]} +cosmwasm-vm = { git = "https://github.com/reuvenpo/cosmwasm", rev = "c6f578a09ab331baa43413332bf488e9be7a76c0", features = ["iterator"] } +#cosmwasm-std = { path = "../cosmwasm/packages/std", features = ["iterator"]} +#cosmwasm-vm = { path = "../cosmwasm/packages/vm", features = ["iterator"] } errno = "0.2" snafu = "0.6.3" serde_json = "1.0" diff --git a/src/api.rs b/src/api.rs index d566b9fff..1783ade4a 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,4 +1,5 @@ -use cosmwasm_std::{generic_err, invalid_utf8, Api, Binary, CanonicalAddr, HumanAddr, StdResult}; +use cosmwasm_std::{Binary, CanonicalAddr, HumanAddr}; +use cosmwasm_vm::{Api, FfiError, FfiResult}; use crate::error::GoResult; use crate::memory::Buffer; @@ -34,7 +35,7 @@ pub struct GoApi { unsafe impl Send for GoApi {} impl Api for GoApi { - fn canonical_address(&self, human: &HumanAddr) -> StdResult { + fn canonical_address(&self, human: &HumanAddr) -> FfiResult { let human_bytes = human.as_str().as_bytes(); let human_bytes = Buffer::from_vec(human_bytes.to_vec()); let mut output = Buffer::default(); @@ -42,12 +43,8 @@ impl Api for GoApi { (self.vtable.canonicalize_address)(self.state, human_bytes, &mut output as *mut Buffer) .into(); let _human = unsafe { human_bytes.consume() }; - if !go_result.is_ok() { - return Err(generic_err(format!( - "Go {}: canonical address for {}", - go_result, human - ))); - } + let go_result: FfiResult<()> = go_result.into(); + go_result?; let canon = if output.ptr.is_null() { Vec::new() } else { @@ -58,20 +55,16 @@ impl Api for GoApi { Ok(CanonicalAddr(Binary(canon))) } - fn human_address(&self, canonical: &CanonicalAddr) -> StdResult { + fn human_address(&self, canonical: &CanonicalAddr) -> FfiResult { let canonical = canonical.as_slice(); let canonical = Buffer::from_vec(canonical.to_vec()); let mut output = Buffer::default(); let go_result: GoResult = (self.vtable.humanize_address)(self.state, canonical, &mut output as *mut Buffer) .into(); - let canonical = unsafe { canonical.consume() }; - if !go_result.is_ok() { - return Err(generic_err(format!( - "Go {}: human address for {:?}", - go_result, canonical - ))); - } + let _canonical = unsafe { canonical.consume() }; + let go_result: FfiResult<()> = go_result.into(); + go_result?; let result = if output.ptr.is_null() { Vec::new() } else { @@ -79,7 +72,7 @@ impl Api for GoApi { // that means it was initialized by the go code, with values generated by `memory::allocate_rust` unsafe { output.consume() } }; - let human = String::from_utf8(result).map_err(invalid_utf8)?; + let human = String::from_utf8(result).or(Err(FfiError::Other))?; Ok(HumanAddr(human)) } } diff --git a/src/db.rs b/src/db.rs index a342f1c3c..e4a1535ff 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,5 +1,5 @@ use crate::iterator::GoIter; -use cosmwasm_std::{generic_err, ReadonlyStorage, StdResult, Storage}; +use cosmwasm_vm::{FfiResult, ReadonlyStorage, Storage}; use crate::error::GoResult; use crate::memory::Buffer; @@ -28,18 +28,14 @@ pub struct DB { } impl ReadonlyStorage for DB { - fn get(&self, key: &[u8]) -> StdResult>> { + fn get(&self, key: &[u8]) -> FfiResult>> { let key = Buffer::from_vec(key.to_vec()); let mut result_buf = Buffer::default(); let go_result: GoResult = (self.vtable.read_db)(self.state, key, &mut result_buf as *mut Buffer).into(); - let key = unsafe { key.consume() }; - if !go_result.is_ok() { - return Err(generic_err(format!( - "Go {}: reading key {:?}", - go_result, key - ))); - } + let _key = unsafe { key.consume() }; + let go_result: FfiResult<()> = go_result.into(); + go_result?; if result_buf.ptr.is_null() { return Ok(None); @@ -59,7 +55,7 @@ impl ReadonlyStorage for DB { start: Option<&[u8]>, end: Option<&[u8]>, order: cosmwasm_std::Order, - ) -> StdResult> + 'a>> { + ) -> FfiResult> + 'a>> { // returns nul pointer in Buffer in none, otherwise proper buffer let start = start .map(|s| Buffer::from_vec(s.to_vec())) @@ -79,41 +75,26 @@ impl ReadonlyStorage for DB { let _start = unsafe { start.consume() }; let _end = unsafe { end.consume() }; - if !go_result.is_ok() { - return Err(generic_err(format!("Go {}: creating iterator", go_result))); - } + let go_result: FfiResult<()> = go_result.into(); + go_result?; Ok(Box::new(iter)) } } impl Storage for DB { - fn set(&mut self, key: &[u8], value: &[u8]) -> StdResult<()> { + fn set(&mut self, key: &[u8], value: &[u8]) -> FfiResult<()> { let key = Buffer::from_vec(key.to_vec()); let value = Buffer::from_vec(value.to_vec()); let go_result: GoResult = (self.vtable.write_db)(self.state, key, value).into(); - let key = unsafe { key.consume() }; + let _key = unsafe { key.consume() }; let _value = unsafe { value.consume() }; - if !go_result.is_ok() { - Err(generic_err(format!( - "Go {}: writing key {:?}", - go_result, key - ))) - } else { - Ok(()) - } + go_result.into() } - fn remove(&mut self, key: &[u8]) -> StdResult<()> { + fn remove(&mut self, key: &[u8]) -> FfiResult<()> { let key = Buffer::from_vec(key.to_vec()); let go_result: GoResult = (self.vtable.remove_db)(self.state, key).into(); - let key = unsafe { key.consume() }; - if !go_result.is_ok() { - Err(generic_err(format!( - "Go {}: removing key {:?}", - go_result, key - ))) - } else { - Ok(()) - } + let _key = unsafe { key.consume() }; + go_result.into() } } diff --git a/src/error/go.rs b/src/error/go.rs index e5176d042..cc4a9e8e5 100644 --- a/src/error/go.rs +++ b/src/error/go.rs @@ -1,4 +1,6 @@ -use std::{convert, fmt}; +use std::fmt; + +use cosmwasm_vm::FfiError; /// This enum gives names to the status codes returned from Go callbacks to Rust. /// @@ -23,7 +25,19 @@ pub enum GoResult { Other = 4, } -impl convert::From for GoResult { +impl From for Result<(), FfiError> { + fn from(other: GoResult) -> Self { + match other { + GoResult::Ok => Ok(()), + GoResult::Panic => Err(FfiError::ForeignPanic), + GoResult::BadArgument => Err(FfiError::BadArgument), + GoResult::OutOfGas => Err(FfiError::OutOfGas), + GoResult::Other => Err(FfiError::Other), + } + } +} + +impl From for GoResult { fn from(n: i32) -> Self { use GoResult::*; // This conversion treats any number that is not otherwise an expected value as `GoError::Other` @@ -48,12 +62,3 @@ impl fmt::Display for GoResult { } } } - -impl GoResult { - pub fn is_ok(&self) -> bool { - match self { - GoResult::Ok => true, - _ => false, - } - } -} diff --git a/src/error/rust.rs b/src/error/rust.rs index 7f0a56782..5782c4d30 100644 --- a/src/error/rust.rs +++ b/src/error/rust.rs @@ -1,5 +1,4 @@ use errno::{set_errno, Errno}; -use std::fmt; use cosmwasm_vm::VmError; use snafu::Snafu; @@ -32,6 +31,11 @@ pub enum Error { #[cfg(feature = "backtraces")] backtrace: snafu::Backtrace, }, + #[snafu(display("Ran out of gas"))] + OutOfGas { + #[cfg(feature = "backtraces")] + backtrace: snafu::Backtrace, + }, } /// empty_err returns an error with stack trace. diff --git a/src/iterator.rs b/src/iterator.rs index 2d3be6f14..20900d0ca 100644 --- a/src/iterator.rs +++ b/src/iterator.rs @@ -1,7 +1,8 @@ -use cosmwasm_std::{generic_err, StdResult, KV}; +use cosmwasm_std::KV; use crate::error::GoResult; use crate::memory::Buffer; +use cosmwasm_vm::{FfiError, FfiResult}; // this represents something passed in from the caller side of FFI #[repr(C)] @@ -33,13 +34,13 @@ impl Default for GoIter { } impl Iterator for GoIter { - type Item = StdResult; + type Item = FfiResult; fn next(&mut self) -> Option { let next_db = match self.vtable.next_db { Some(f) => f, // TODO: return None here??? - None => return Some(Err(generic_err("iterator vtable not set"))), + None => return Some(Err(FfiError::Other)), }; let mut key_buf = Buffer::default(); @@ -50,21 +51,21 @@ impl Iterator for GoIter { &mut value_buf as *mut Buffer, ) .into(); - if !go_result.is_ok() { - return Some(Err(generic_err(format!( - "Go {}: iterator.next()", - go_result - )))); + let go_result: FfiResult<()> = go_result.into(); + if let Err(err) = go_result { + return Some(Err(err)); } - // TODO: Check if key is null, return none, otherwise, make KV let okey = unsafe { key_buf.read() }; match okey { Some(key) => { - // TODO: return error not unwrap?? - let value = unsafe { value_buf.read().unwrap() }; - let kv = (key.to_vec(), value.to_vec()); - Some(Ok(kv)) + let value = unsafe { value_buf.read() }; + if let Some(value) = value { + let kv = (key.to_vec(), value.to_vec()); + Some(Ok(kv)) + } else { + return Some(Err(FfiError::Other)); + } } None => None, } diff --git a/src/lib.rs b/src/lib.rs index 667efc2f7..580a67516 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ use std::str::from_utf8; use crate::error::{clear_error, handle_c_error, set_error}; use crate::error::{empty_err, EmptyArg, Error, Panic, Utf8Err, WasmErr}; -use cosmwasm_std::Extern; +use cosmwasm_vm::Extern; use cosmwasm_vm::{call_handle_raw, call_init_raw, call_query_raw, CosmCache}; #[repr(C)] diff --git a/src/querier.rs b/src/querier.rs index 2850cef03..c30856e0e 100644 --- a/src/querier.rs +++ b/src/querier.rs @@ -1,4 +1,5 @@ -use cosmwasm_std::{Querier, QuerierResult, SystemError}; +use cosmwasm_std::SystemError; +use cosmwasm_vm::{FfiResult, Querier, QuerierResult}; use crate::error::GoResult; use crate::memory::Buffer; @@ -35,18 +36,13 @@ impl Querier for GoQuerier { (self.vtable.query_external)(self.state, request, &mut result_buf as *mut Buffer) .into(); let _request = unsafe { request.consume() }; - if !go_result.is_ok() { - return Err(SystemError::InvalidRequest { - error: format!("Go {}: making query", go_result), - }); - } + let go_result: FfiResult<()> = go_result.into(); + go_result?; let bin_result = unsafe { result_buf.consume() }; match serde_json::from_slice(&bin_result) { - Ok(v) => v, - Err(e) => Err(SystemError::InvalidRequest { - error: format!("Parsing Go response: {}", e), - }), + Ok(system_result) => Ok(system_result), + Err(_) => Ok(Err(SystemError::InvalidResponse { msg: bin_result })), } } }