Skip to content

Commit

Permalink
Merge pull request #132 from CosmWasm/upgrade-to-0.10.0
Browse files Browse the repository at this point in the history
Upgrade to 0.10.0
  • Loading branch information
ethanfrey authored Jul 30, 2020
2 parents 61cf768 + ca5e6f1 commit fd31e87
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 41 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "go-cosmwasm"
version = "0.10.0-alpha3"
version = "0.10.0"
authors = ["Ethan Frey <ethanfrey@users.noreply.github.com>"]
edition = "2018"
description = "Go bindings for cosmwasm contracts"
Expand Down Expand Up @@ -31,8 +31,8 @@ singlepass = ["cosmwasm-vm/default-singlepass"]
cranelift = ["cosmwasm-vm/default-cranelift"]

[dependencies]
cosmwasm-std = { version = "0.10.0-alpha3", features = ["iterator"]}
cosmwasm-vm = { version = "0.10.0-alpha3", features = ["iterator"] }
cosmwasm-std = { version = "0.10.0", features = ["iterator"]}
cosmwasm-vm = { version = "0.10.0", features = ["iterator"] }
errno = "0.2"
snafu = "0.6.3"
serde_json = "1.0"
Expand Down
40 changes: 36 additions & 4 deletions api/lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func TestHandle(t *testing.T) {
res, cost, err = Handle(cache, id, params, []byte(`{"release":{}}`), &igasMeter2, store, api, &querier, 100000000)
diff = time.Now().Sub(start)
require.NoError(t, err)
assert.Equal(t, uint64(0x19c34), cost)
assert.Equal(t, uint64(0x19c40), cost)
t.Logf("Time (%d gas): %s\n", cost, diff)

// make sure it read the balance properly and we got 250 atoms
Expand Down Expand Up @@ -257,6 +257,38 @@ func TestHandleStorageLoop(t *testing.T) {
require.Equal(t, int64(maxGas), int64(totalCost))
}

func TestHandleUserErrorsInApiCalls(t *testing.T) {
cache, cleanup := withCache(t)
defer cleanup()
id := createTestContract(t, cache)

maxGas := uint64(40_000_000)
gasMeter1 := NewMockGasMeter(maxGas)
igasMeter1 := GasMeter(gasMeter1)
// instantiate it with this store
store := NewLookup(gasMeter1)
balance := types.Coins{types.NewCoin(250, "ATOM")}
querier := DefaultQuerier(mockContractAddr, balance)
params, err := json.Marshal(mockEnv("creator"))
require.NoError(t, err)

defaultApi := NewMockAPI()
msg := []byte(`{"verifier": "fred", "beneficiary": "bob"}`)
res, _, err := Instantiate(cache, id, params, msg, &igasMeter1, store, defaultApi, &querier, maxGas)
require.NoError(t, err)
requireOkResponse(t, res, 0)

gasMeter2 := NewMockGasMeter(maxGas)
igasMeter2 := GasMeter(gasMeter2)
store.SetGasMeter(gasMeter2)
params, err = json.Marshal(mockEnv("fred"))
require.NoError(t, err)
failingApi := NewMockFailureAPI()
res, _, err = Handle(cache, id, params, []byte(`{"user_errors_in_api_calls":{}}`), &igasMeter2, store, failingApi, &querier, maxGas)
require.NoError(t, err)
requireOkResponse(t, res, 0)
}

func TestMigrate(t *testing.T) {
cache, cleanup := withCache(t)
defer cleanup()
Expand Down Expand Up @@ -337,13 +369,13 @@ func TestMultipleInstances(t *testing.T) {
assert.Equal(t, uint64(0x1093d), cost)

// fail to execute store1 with mary
resp := exec(t, cache, id, "mary", store1, api, querier, 0xeff2)
resp := exec(t, cache, id, "mary", store1, api, querier, 0xeffe)
require.Equal(t, resp.Err, &types.StdError{
Unauthorized: &types.Unauthorized{},
})

// succeed to execute store1 with fred
resp = exec(t, cache, id, "fred", store1, api, querier, 0x19c34)
resp = exec(t, cache, id, "fred", store1, api, querier, 0x19c40)
require.Nil(t, resp.Err, "%v", resp.Err)
require.Equal(t, 1, len(resp.Ok.Messages))
logs := resp.Ok.Log
Expand All @@ -352,7 +384,7 @@ func TestMultipleInstances(t *testing.T) {
require.Equal(t, "bob", logs[1].Value)

// succeed to execute store2 with mary
resp = exec(t, cache, id, "mary", store2, api, querier, 0x19c34)
resp = exec(t, cache, id, "mary", store2, api, querier, 0x19c40)
require.Nil(t, resp.Err)
require.Equal(t, 1, len(resp.Ok.Messages))
logs = resp.Ok.Log
Expand Down
Binary file modified api/testdata/hackatom.wasm
Binary file not shown.
Binary file modified api/testdata/queue.wasm
Binary file not shown.
Binary file modified api/testdata/reflect.wasm
Binary file not shown.
40 changes: 11 additions & 29 deletions src/error/go.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use std::convert::TryFrom;
use cosmwasm_vm::FfiError;
use std::fmt;

use crate::Buffer;
use cosmwasm_vm::FfiError;

/// This enum gives names to the status codes returned from Go callbacks to Rust.
///
Expand Down Expand Up @@ -30,21 +29,6 @@ pub enum GoResult {
User = 5,
}

impl TryFrom<GoResult> for Result<(), FfiError> {
type Error = &'static str;

fn try_from(other: GoResult) -> Result<Self, Self::Error> {
match other {
GoResult::Ok => Ok(Ok(())),
GoResult::Panic => Ok(Err(FfiError::foreign_panic())),
GoResult::BadArgument => Ok(Err(FfiError::bad_argument())),
GoResult::OutOfGas => Ok(Err(FfiError::out_of_gas())),
GoResult::Other => Err("Unspecified error in Go code"), // no conversion possible due to missing error message
GoResult::User => Err("Unspecified error in Go code"), // no conversion possible due to missing error message
}
}
}

impl From<i32> for GoResult {
fn from(n: i32) -> Self {
use GoResult::*;
Expand Down Expand Up @@ -74,25 +58,23 @@ impl fmt::Display for GoResult {
}

impl GoResult {
/// This is a wrapper around `impl TryFrom<GoResult> for Result<(), FfiError>` that uses a fallback
/// if output is not-empty, use that as the error message
/// otherwise, call default() to generate a default message.
/// This converts a GoResult to a `Result<(), FfiError>`, using a fallback error message for some cases.
/// If it is GoResult::User the error message will be returned to the contract.
/// Otherwise, the returned error will trigger a trap in the VM and abort contract execution immediately.
///
/// Safety: this reads data from an externally provided buffer and assumes valid utf-8 encoding
/// Only call if you trust the code that provides output to be correct
pub unsafe fn into_ffi_result<F>(self, output: Buffer, default: F) -> Result<(), FfiError>
/// Only call if you trust the code that provides `error_msg` to be correct.
pub unsafe fn into_ffi_result<F>(self, error_msg: Buffer, default: F) -> Result<(), FfiError>
where
F: Fn() -> String,
{
let make_msg = || {
if output.ptr.is_null() {
let read_error_msg = || {
// We initialize `error_msg` with a null pointer. if it is not null,
// that means it was initialized by the go code, with values generated by `memory::allocate_rust`
if error_msg.ptr.is_null() {
default()
} else {
// We initialize `output` with a null pointer. if it is not null,
// that means it was initialized by the go code, with values generated by `memory::allocate_rust`
String::from_utf8_lossy(&output.consume()).into()
String::from_utf8_lossy(&error_msg.consume()).into()
}
};

Expand All @@ -101,8 +83,8 @@ impl GoResult {
GoResult::Panic => Err(FfiError::foreign_panic()),
GoResult::BadArgument => Err(FfiError::bad_argument()),
GoResult::OutOfGas => Err(FfiError::out_of_gas()),
GoResult::Other => Err(FfiError::unknown(make_msg())),
GoResult::User => Err(FfiError::user_err(make_msg())),
GoResult::Other => Err(FfiError::unknown(read_error_msg())),
GoResult::User => Err(FfiError::user_err(read_error_msg())),
}
}
}

0 comments on commit fd31e87

Please # to comment.