Skip to content

Commit

Permalink
Merge branch 'main' into ibc-callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
chipshort committed Jun 26, 2024
2 parents dab489b + 1de5cd8 commit 2153a14
Show file tree
Hide file tree
Showing 16 changed files with 811 additions and 138 deletions.
26 changes: 13 additions & 13 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
# All checks on the codebase that can run in parallel to build_shared_library
libwasmvm_sanity:
docker:
- image: cimg/rust:1.73.0
- image: cimg/rust:1.74.0
steps:
- checkout
- run:
Expand All @@ -18,8 +18,8 @@ jobs:
command: rustup component add rustfmt
- restore_cache:
keys:
- cargocache-v3-libwasmvm_sanity-rust:1.73.0-{{ checksum "libwasmvm/Cargo.lock" }}
- cargocache-v3-libwasmvm_sanity-rust:1.73.0-
- cargocache-v3-libwasmvm_sanity-rust:1.74.0-{{ checksum "libwasmvm/Cargo.lock" }}
- cargocache-v3-libwasmvm_sanity-rust:1.74.0-
- run:
name: Ensure libwasmvm/bindings.h is up-to-date
working_directory: libwasmvm
Expand Down Expand Up @@ -62,7 +62,7 @@ jobs:
- libwasmvm/target/release/.fingerprint
- libwasmvm/target/release/build
- libwasmvm/target/release/deps
key: cargocache-v3-libwasmvm_sanity-rust:1.73.0-{{ checksum "libwasmvm/Cargo.lock" }}
key: cargocache-v3-libwasmvm_sanity-rust:1.74.0-{{ checksum "libwasmvm/Cargo.lock" }}

libwasmvm_clippy:
parameters:
Expand Down Expand Up @@ -113,15 +113,15 @@ jobs:
command: |
set -o errexit
curl -sS --output rustup-init.exe https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe
./rustup-init.exe --no-modify-path --profile minimal --default-toolchain 1.73.0 -y
./rustup-init.exe --no-modify-path --profile minimal --default-toolchain 1.74.0 -y
echo 'export PATH="$PATH;$USERPROFILE/.cargo/bin"' >> "$BASH_ENV"
- run:
name: Show Rust version information
command: rustc --version; cargo --version; rustup --version
- restore_cache:
keys:
- cachev4-libwasmvm_sanity_windows-rust:1.73.0-{{ checksum "libwasmvm/Cargo.lock" }}
- cachev4-libwasmvm_sanity_windows-rust:1.73.0-
- cachev4-libwasmvm_sanity_windows-rust:1.74.0-{{ checksum "libwasmvm/Cargo.lock" }}
- cachev4-libwasmvm_sanity_windows-rust:1.74.0-
- run:
name: Run unit tests
working_directory: libwasmvm
Expand All @@ -133,7 +133,7 @@ jobs:
- libwasmvm/target/debug/.fingerprint
- libwasmvm/target/debug/build
- libwasmvm/target/debug/deps
key: cachev4-libwasmvm_sanity_windows-rust:1.73.0-{{ checksum "libwasmvm/Cargo.lock" }}
key: cachev4-libwasmvm_sanity_windows-rust:1.74.0-{{ checksum "libwasmvm/Cargo.lock" }}

libwasmvm_audit:
docker:
Expand Down Expand Up @@ -267,16 +267,16 @@ jobs:

build_shared_library:
docker:
- image: cimg/rust:1.73.0
- image: cimg/rust:1.74.0
steps:
- checkout
- run:
name: Show version information
command: rustc --version; cargo --version; rustup --version
- restore_cache:
keys:
- cargocache-v3-build_shared_library-rust:1.73.0-{{ checksum "libwasmvm/Cargo.lock" }}
- cargocache-v3-build_shared_library-rust:1.73.0-
- cargocache-v3-build_shared_library-rust:1.74.0-{{ checksum "libwasmvm/Cargo.lock" }}
- cargocache-v3-build_shared_library-rust:1.74.0-
- run:
name: Create release build of libwasmvm
command: make build-rust
Expand All @@ -293,7 +293,7 @@ jobs:
- libwasmvm/target/release/.fingerprint
- libwasmvm/target/release/build
- libwasmvm/target/release/deps
key: cargocache-v3-build_shared_library-rust:1.73.0-{{ checksum "libwasmvm/Cargo.lock" }}
key: cargocache-v3-build_shared_library-rust:1.74.0-{{ checksum "libwasmvm/Cargo.lock" }}

# Test the Go project and run benchmarks
wasmvm_test:
Expand Down Expand Up @@ -448,7 +448,7 @@ workflows:
matrix:
parameters:
# Run with MSRV and some modern stable Rust
rust-version: ["1.73.0", "1.75.0"]
rust-version: ["1.74.0", "1.75.0"]
- libwasmvm_audit
- format-go
- wasmvm_no_cgo
Expand Down
2 changes: 1 addition & 1 deletion docs/COMPILER_VERSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,5 @@ We currently use the following version:
| Type | Rust version | Note |
| ------------------------ | ------------ | --------------------------------- |
| Production Rust compiler | 1.77.0 | Builders version 0019 |
| Min Rust compiler | 1.73.0 | Supports builder versions >= 0017 |
| Min Rust compiler | 1.74.0 | Supports builder versions >= 0019 |
| Tooling Rust compiler | 1.75.0 | |
2 changes: 2 additions & 0 deletions ibc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ func TestAnalyzeCode(t *testing.T) {
require.NoError(t, err)
require.False(t, report.HasIBCEntryPoints)
require.Equal(t, "", report.RequiredCapabilities)
require.Equal(t, uint64(42), *report.ContractMigrateVersion)

// Store IBC contract
wasm2, err := os.ReadFile(IBC_TEST_CONTRACT)
Expand All @@ -313,6 +314,7 @@ func TestAnalyzeCode(t *testing.T) {
require.NoError(t, err)
require.True(t, report2.HasIBCEntryPoints)
require.Equal(t, "iterator,stargate", report2.RequiredCapabilities)
require.Nil(t, report2.ContractMigrateVersion)
}

func TestIBCMsgGetChannel(t *testing.T) {
Expand Down
15 changes: 15 additions & 0 deletions internal/api/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@ typedef struct UnmanagedVector {
uintptr_t cap;
} UnmanagedVector;

/**
* A version of `Option<u64>` that can be used safely in FFI.
*/
typedef struct OptionalU64 {
bool is_some;
uint64_t value;
} OptionalU64;

/**
* The result type of the FFI function analyze_code.
*
Expand All @@ -217,6 +225,13 @@ typedef struct AnalysisReport {
* This is never None/nil.
*/
struct UnmanagedVector required_capabilities;
/**
* The migrate version of the contract.
* This is None if the contract does not have a migrate version and the `migrate` entrypoint
* needs to be called for every migration (if present).
* If it is `Some(version)`, it only needs to be called if the `version` increased.
*/
struct OptionalU64 contract_migrate_version;
} AnalysisReport;

typedef struct Metrics {
Expand Down
17 changes: 8 additions & 9 deletions internal/api/callbacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ func cGet(ptr *C.db_t, gasMeter *C.gas_meter_t, usedGas *cu64, key C.U8SliceView
// we received an invalid pointer
return C.GoError_BadArgument
}
if !(*val).is_none || !(*errOut).is_none {
// errOut is unused and we don't check `is_none` because of https://github.com/CosmWasm/wasmvm/issues/536
if !(*val).is_none {
panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.")
}

Expand Down Expand Up @@ -185,9 +186,7 @@ func cSet(ptr *C.db_t, gasMeter *C.gas_meter_t, usedGas *cu64, key C.U8SliceView
// we received an invalid pointer
return C.GoError_BadArgument
}
if !(*errOut).is_none {
panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.")
}
// errOut is unused and we don't check `is_none` because of https://github.com/CosmWasm/wasmvm/issues/536

gm := *(*types.GasMeter)(unsafe.Pointer(gasMeter))
kv := *(*types.KVStore)(unsafe.Pointer(ptr))
Expand All @@ -210,9 +209,7 @@ func cDelete(ptr *C.db_t, gasMeter *C.gas_meter_t, usedGas *cu64, key C.U8SliceV
// we received an invalid pointer
return C.GoError_BadArgument
}
if !(*errOut).is_none {
panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.")
}
// errOut is unused and we don't check `is_none` because of https://github.com/CosmWasm/wasmvm/issues/536

gm := *(*types.GasMeter)(unsafe.Pointer(gasMeter))
kv := *(*types.KVStore)(unsafe.Pointer(ptr))
Expand Down Expand Up @@ -286,7 +283,8 @@ func cNext(ref C.IteratorReference, gasMeter *C.gas_meter_t, usedGas *cu64, key
// we received an invalid pointer
return C.GoError_BadArgument
}
if !(*key).is_none || !(*val).is_none || !(*errOut).is_none {
// errOut is unused and we don't check `is_none` because of https://github.com/CosmWasm/wasmvm/issues/536
if !(*key).is_none || !(*val).is_none {
panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.")
}

Expand Down Expand Up @@ -337,7 +335,8 @@ func nextPart(ref C.IteratorReference, gasMeter *C.gas_meter_t, usedGas *cu64, o
// we received an invalid pointer
return C.GoError_BadArgument
}
if !(*output).is_none || !(*errOut).is_none {
// errOut is unused and we don't check `is_none` because of https://github.com/CosmWasm/wasmvm/issues/536
if !(*output).is_none {
panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.")
}

Expand Down
8 changes: 5 additions & 3 deletions internal/api/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,12 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) {
}
requiredCapabilities := string(copyAndDestroyUnmanagedVector(report.required_capabilities))
entrypoints := string(copyAndDestroyUnmanagedVector(report.entrypoints))

res := types.AnalysisReport{
HasIBCEntryPoints: bool(report.has_ibc_entry_points),
RequiredCapabilities: requiredCapabilities,
Entrypoints: strings.Split(entrypoints, ","),
HasIBCEntryPoints: bool(report.has_ibc_entry_points),
RequiredCapabilities: requiredCapabilities,
Entrypoints: strings.Split(entrypoints, ","),
ContractMigrateVersion: optionalU64ToPtr(report.contract_migrate_version),
}
return &res, nil
}
Expand Down
34 changes: 17 additions & 17 deletions internal/api/lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ func TestGetMetrics(t *testing.T) {
require.Equal(t, uint32(0), metrics.HitsMemoryCache)
require.Equal(t, uint32(1), metrics.HitsFsCache)
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)

// Instantiate 2
msg2 := []byte(`{"verifier": "fred", "beneficiary": "susi"}`)
Expand All @@ -318,7 +318,7 @@ func TestGetMetrics(t *testing.T) {
require.Equal(t, uint32(1), metrics.HitsMemoryCache)
require.Equal(t, uint32(1), metrics.HitsFsCache)
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)

// Pin
err = Pin(cache, checksum)
Expand All @@ -331,8 +331,8 @@ func TestGetMetrics(t *testing.T) {
require.Equal(t, uint32(2), metrics.HitsFsCache)
require.Equal(t, uint64(1), metrics.ElementsPinnedMemoryCache)
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
require.InEpsilon(t, 2832576, metrics.SizePinnedMemoryCache, 0.25)
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
require.InEpsilon(t, 3700000, metrics.SizePinnedMemoryCache, 0.25)
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)

// Instantiate 3
msg3 := []byte(`{"verifier": "fred", "beneficiary": "bert"}`)
Expand All @@ -347,8 +347,8 @@ func TestGetMetrics(t *testing.T) {
require.Equal(t, uint32(2), metrics.HitsFsCache)
require.Equal(t, uint64(1), metrics.ElementsPinnedMemoryCache)
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
require.InEpsilon(t, 2832576, metrics.SizePinnedMemoryCache, 0.25)
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
require.InEpsilon(t, 3700000, metrics.SizePinnedMemoryCache, 0.25)
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)

// Unpin
err = Unpin(cache, checksum)
Expand All @@ -363,7 +363,7 @@ func TestGetMetrics(t *testing.T) {
require.Equal(t, uint64(0), metrics.ElementsPinnedMemoryCache)
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
require.Equal(t, uint64(0), metrics.SizePinnedMemoryCache)
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)

// Instantiate 4
msg4 := []byte(`{"verifier": "fred", "beneficiary": "jeff"}`)
Expand All @@ -379,7 +379,7 @@ func TestGetMetrics(t *testing.T) {
require.Equal(t, uint64(0), metrics.ElementsPinnedMemoryCache)
require.Equal(t, uint64(1), metrics.ElementsMemoryCache)
require.Equal(t, uint64(0), metrics.SizePinnedMemoryCache)
require.InEpsilon(t, 2832576, metrics.SizeMemoryCache, 0.25)
require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25)
}

func TestInstantiate(t *testing.T) {
Expand All @@ -405,7 +405,7 @@ func TestInstantiate(t *testing.T) {
res, cost, err := Instantiate(cache, checksum, env, info, msg, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG)
require.NoError(t, err)
requireOkResponse(t, res, 0)
assert.Equal(t, uint64(0x5088ea), cost.UsedInternally)
assert.Equal(t, uint64(0x540eb6), cost.UsedInternally)

var result types.ContractResult
err = json.Unmarshal(res, &result)
Expand Down Expand Up @@ -436,7 +436,7 @@ func TestExecute(t *testing.T) {
diff := time.Since(start)
require.NoError(t, err)
requireOkResponse(t, res, 0)
assert.Equal(t, uint64(0x5088ea), cost.UsedInternally)
assert.Equal(t, uint64(0x540eb6), cost.UsedInternally)
t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff)

// execute with the same store
Expand All @@ -449,7 +449,7 @@ func TestExecute(t *testing.T) {
res, cost, err = Execute(cache, checksum, env, info, []byte(`{"release":{}}`), &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG)
diff = time.Since(start)
require.NoError(t, err)
assert.Equal(t, uint64(0x8be9c6), cost.UsedInternally)
assert.Equal(t, uint64(0x975216), cost.UsedInternally)
t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff)

// make sure it read the balance properly and we got 250 atoms
Expand Down Expand Up @@ -557,7 +557,7 @@ func TestExecuteCpuLoop(t *testing.T) {
diff := time.Since(start)
require.NoError(t, err)
requireOkResponse(t, res, 0)
assert.Equal(t, uint64(0x365a42), cost.UsedInternally)
assert.Equal(t, uint64(0x3d997e), cost.UsedInternally)
t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff)

// execute a cpu loop
Expand Down Expand Up @@ -786,7 +786,7 @@ func TestMultipleInstances(t *testing.T) {
require.NoError(t, err)
requireOkResponse(t, res, 0)
// we now count wasm gas charges and db writes
assert.Equal(t, uint64(0x4ffce0), cost.UsedInternally)
assert.Equal(t, uint64(0x53541c), cost.UsedInternally)

// instance2 controlled by mary
gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT)
Expand All @@ -797,14 +797,14 @@ func TestMultipleInstances(t *testing.T) {
res, cost, err = Instantiate(cache, checksum, env, info, msg, &igasMeter2, store2, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG)
require.NoError(t, err)
requireOkResponse(t, res, 0)
assert.Equal(t, uint64(0x504dbc), cost.UsedInternally)
assert.Equal(t, uint64(0x53bbb4), cost.UsedInternally)

// fail to execute store1 with mary
resp := exec(t, cache, checksum, "mary", store1, api, querier, 0x4a20c2)
resp := exec(t, cache, checksum, "mary", store1, api, querier, 0x503f70)
require.Equal(t, "Unauthorized", resp.Err)

// succeed to execute store1 with fred
resp = exec(t, cache, checksum, "fred", store1, api, querier, 0x8ba826)
resp = exec(t, cache, checksum, "fred", store1, api, querier, 0x970662)
require.Equal(t, "", resp.Err)
require.Equal(t, 1, len(resp.Ok.Messages))
attributes := resp.Ok.Attributes
Expand All @@ -813,7 +813,7 @@ func TestMultipleInstances(t *testing.T) {
require.Equal(t, "bob", attributes[1].Value)

// succeed to execute store2 with mary
resp = exec(t, cache, checksum, "mary", store2, api, querier, 0x8bc8f6)
resp = exec(t, cache, checksum, "mary", store2, api, querier, 0x972c3c)
require.Equal(t, "", resp.Err)
require.Equal(t, 1, len(resp.Ok.Messages))
attributes = resp.Ok.Attributes
Expand Down
7 changes: 7 additions & 0 deletions internal/api/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ func copyAndDestroyUnmanagedVector(v C.UnmanagedVector) []byte {
return out
}

func optionalU64ToPtr(val C.OptionalU64) *uint64 {
if val.is_some {
return (*uint64)(&val.value)
}
return nil
}

// copyU8Slice copies the contents of an Option<&[u8]> that was allocated on the Rust side.
// Returns nil if and only if the source is None.
func copyU8Slice(view C.U8SliceView) []byte {
Expand Down
8 changes: 8 additions & 0 deletions lib_libwasmvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,14 @@ type hasSubMessages interface {
SubMessages() []types.SubMsg
}

// make sure the types implement the interface
// cannot put these next to the types, as the interface is private
var (
_ hasSubMessages = (*types.IBCBasicResult)(nil)
_ hasSubMessages = (*types.IBCReceiveResult)(nil)
_ hasSubMessages = (*types.ContractResult)(nil)
)

func DeserializeResponse(gasLimit uint64, deserCost types.UFraction, gasReport *types.GasReport, data []byte, response any) error {
gasForDeserialization := deserCost.Mul(uint64(len(data))).Floor()
if gasLimit < gasForDeserialization+gasReport.UsedInternally {
Expand Down
Loading

0 comments on commit 2153a14

Please sign in to comment.