From d64e876f52691c232e3a5b5b109579161a88899b Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Thu, 25 Jan 2024 17:46:13 +0100 Subject: [PATCH 1/8] Update cosmwasm and add ValidateAddress --- internal/api/bindings.h | 4 ++ internal/api/callbacks.go | 26 ++++++++++++ internal/api/callbacks_cgo.go | 4 ++ internal/api/mocks.go | 19 +++++++++ libwasmvm/Cargo.lock | 77 ++++++++++++----------------------- libwasmvm/Cargo.toml | 4 +- libwasmvm/bindings.h | 4 ++ libwasmvm/src/api.rs | 35 +++++++++++++++- types/api.go | 3 ++ 9 files changed, 121 insertions(+), 55 deletions(-) diff --git a/internal/api/bindings.h b/internal/api/bindings.h index 9d7717b2f..00bb0ec3a 100644 --- a/internal/api/bindings.h +++ b/internal/api/bindings.h @@ -337,6 +337,10 @@ typedef struct GoApiVtable { struct UnmanagedVector *canonicalized_address_out, struct UnmanagedVector *err_msg_out, uint64_t *gas_used); + int32_t (*validate_address)(const struct api_t *api, + struct U8SliceView input, + struct UnmanagedVector *err_msg_out, + uint64_t *gas_used); } GoApiVtable; typedef struct GoApi { diff --git a/internal/api/callbacks.go b/internal/api/callbacks.go index 9638f55b4..7292f7b2d 100644 --- a/internal/api/callbacks.go +++ b/internal/api/callbacks.go @@ -25,6 +25,7 @@ GoError cNextValue_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_g // api GoError cHumanizeAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas); GoError cCanonicalizeAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas); +GoError cValidateAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *errOut, uint64_t *used_gas); // and querier GoError cQueryExternal_cgo(querier_t *ptr, uint64_t gas_limit, uint64_t *used_gas, U8SliceView request, UnmanagedVector *result, UnmanagedVector *errOut); @@ -365,6 +366,7 @@ func nextPart(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, output * var api_vtable = C.GoApiVtable{ humanize_address: C.any_function_t(C.cHumanizeAddress_cgo), canonicalize_address: C.any_function_t(C.cCanonicalizeAddress_cgo), + validate_address: C.any_function_t(C.cValidateAddress_cgo), } // contract: original pointer/struct referenced must live longer than C.GoApi struct @@ -431,6 +433,30 @@ func cCanonicalizeAddress(ptr *C.api_t, src C.U8SliceView, dest *C.UnmanagedVect return C.GoError_None } +//export cValidateAddress +func cValidateAddress(ptr *C.api_t, src C.U8SliceView, errOut *C.UnmanagedVector, used_gas *cu64) (ret C.GoError) { + defer recoverPanic(&ret) + + if errOut == nil { + 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.") + } + + api := (*types.GoAPI)(unsafe.Pointer(ptr)) + s := string(copyU8Slice(src)) + cost, err := api.ValidateAddress(s) + + *used_gas = cu64(cost) + if err != nil { + // store the actual error message in the return buffer + *errOut = newUnmanagedVector([]byte(err.Error())) + return C.GoError_User + } + return C.GoError_None +} + /****** Go Querier ********/ var querier_vtable = C.QuerierVtable{ diff --git a/internal/api/callbacks_cgo.go b/internal/api/callbacks_cgo.go index 7f6c49368..c8f237f61 100644 --- a/internal/api/callbacks_cgo.go +++ b/internal/api/callbacks_cgo.go @@ -16,6 +16,7 @@ GoError cNextValue(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, // imports (api) GoError cHumanizeAddress(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas); GoError cCanonicalizeAddress(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas); +GoError cValidateAddress(api_t *ptr, U8SliceView src, UnmanagedVector *errOut, uint64_t *used_gas); // imports (querier) GoError cQueryExternal(querier_t *ptr, uint64_t gas_limit, uint64_t *used_gas, U8SliceView request, UnmanagedVector *result, UnmanagedVector *errOut); @@ -51,6 +52,9 @@ GoError cCanonicalizeAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *d GoError cHumanizeAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas) { return cHumanizeAddress(ptr, src, dest, errOut, used_gas); } +GoError cValidateAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *errOut, uint64_t *used_gas) { + return cValidateAddress(ptr, src, errOut, used_gas); +} // Gateway functions (querier) GoError cQueryExternal_cgo(querier_t *ptr, uint64_t gas_limit, uint64_t *used_gas, U8SliceView request, UnmanagedVector *result, UnmanagedVector *errOut) { diff --git a/internal/api/mocks.go b/internal/api/mocks.go index ee7f20111..dbc5eecc4 100644 --- a/internal/api/mocks.go +++ b/internal/api/mocks.go @@ -361,10 +361,29 @@ func MockHumanizeAddress(canon []byte) (string, uint64, error) { return human, CostHuman, nil } +func MockValidateAddress(input string) (gasCost uint64, _ error) { + canonicalized, gasCostCanonicalize, err := MockCanonicalizeAddress(input) + gasCost += gasCostCanonicalize + if err != nil { + return gasCost, err + } + humanized, gasCostHumanize, err := MockHumanizeAddress(canonicalized) + gasCost += gasCostHumanize + if err != nil { + return gasCost, err + } + if humanized != strings.ToLower(input) { + return gasCost, fmt.Errorf("address validation failed") + } + + return gasCost, nil +} + func NewMockAPI() *types.GoAPI { return &types.GoAPI{ HumanizeAddress: MockHumanizeAddress, CanonicalizeAddress: MockCanonicalizeAddress, + ValidateAddress: MockValidateAddress, } } diff --git a/libwasmvm/Cargo.lock b/libwasmvm/Cargo.lock index 1030d8460..f0c7430ee 100644 --- a/libwasmvm/Cargo.lock +++ b/libwasmvm/Cargo.lock @@ -263,8 +263,8 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "2.0.0-beta.0" -source = "git+https://github.com/CosmWasm/cosmwasm.git?rev=v2.0.0-beta.0#1ce73c6b91466fc46e8b574e381cdaa1fb0b298e" +version = "2.0.0-beta.1" +source = "git+https://github.com/CosmWasm/cosmwasm.git?rev=v2.0.0-beta.1#6b987d508fffdc2ba40dd8661797e8c27a6c9544" dependencies = [ "digest 0.10.7", "ecdsa", @@ -276,16 +276,16 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "2.0.0-beta.0" -source = "git+https://github.com/CosmWasm/cosmwasm.git?rev=v2.0.0-beta.0#1ce73c6b91466fc46e8b574e381cdaa1fb0b298e" +version = "2.0.0-beta.1" +source = "git+https://github.com/CosmWasm/cosmwasm.git?rev=v2.0.0-beta.1#6b987d508fffdc2ba40dd8661797e8c27a6c9544" dependencies = [ "syn 1.0.109", ] [[package]] name = "cosmwasm-std" -version = "2.0.0-beta.0" -source = "git+https://github.com/CosmWasm/cosmwasm.git?rev=v2.0.0-beta.0#1ce73c6b91466fc46e8b574e381cdaa1fb0b298e" +version = "2.0.0-beta.1" +source = "git+https://github.com/CosmWasm/cosmwasm.git?rev=v2.0.0-beta.1#6b987d508fffdc2ba40dd8661797e8c27a6c9544" dependencies = [ "base64", "bech32", @@ -305,8 +305,8 @@ dependencies = [ [[package]] name = "cosmwasm-vm" -version = "2.0.0-beta.0" -source = "git+https://github.com/CosmWasm/cosmwasm.git?rev=v2.0.0-beta.0#1ce73c6b91466fc46e8b574e381cdaa1fb0b298e" +version = "2.0.0-beta.1" +source = "git+https://github.com/CosmWasm/cosmwasm.git?rev=v2.0.0-beta.1#6b987d508fffdc2ba40dd8661797e8c27a6c9544" dependencies = [ "bech32", "bitflags 1.3.2", @@ -317,7 +317,6 @@ dependencies = [ "cosmwasm-std", "crc32fast", "derivative", - "enumset", "hex", "schemars", "serde", @@ -1017,9 +1016,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] @@ -1806,29 +1805,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-downcast" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dac026d43bcca6e7ce1c0956ba68f59edf6403e8e930a5d891be72c31a44340" -dependencies = [ - "js-sys", - "once_cell", - "wasm-bindgen", - "wasm-bindgen-downcast-macros", -] - -[[package]] -name = "wasm-bindgen-downcast-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5020cfa87c7cecefef118055d44e3c1fc122c7ec25701d528ee458a0b45f38f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.90" @@ -1860,9 +1836,9 @@ checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "wasmer" -version = "4.2.2" +version = "4.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e626f958755a90a6552b9528f59b58a62ae288e6c17fcf40e99495bc33c60f0" +checksum = "5467c7a23f9be04d5691590bea509dbea27e5ba5810d0020bef908456a495f33" dependencies = [ "bytes", "cfg-if", @@ -1877,7 +1853,6 @@ dependencies = [ "target-lexicon", "thiserror", "wasm-bindgen", - "wasm-bindgen-downcast", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-compiler-singlepass", @@ -1889,9 +1864,9 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "4.2.2" +version = "4.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "848e1922694cf97f4df680a0534c9d72c836378b5eb2313c1708fe1a75b40044" +checksum = "510ad01a668d774f3a103a7c219bbc0970be93e8f1b27e2fdb48d1f4ccd1deff" dependencies = [ "backtrace", "bytes", @@ -1916,9 +1891,9 @@ dependencies = [ [[package]] name = "wasmer-compiler-cranelift" -version = "4.2.2" +version = "4.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d96bce6fad15a954edcfc2749b59e47ea7de524b6ef3df392035636491a40b4" +checksum = "54bf93078990d83960d798de3c5935bddaba771fc2fefb9ed6bab9c0bbdea5c1" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -1935,9 +1910,9 @@ dependencies = [ [[package]] name = "wasmer-compiler-singlepass" -version = "4.2.2" +version = "4.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebaa865b40ffb3351b03dab9fe9930a5248c25daebd55b464b79b862d9b55ccd" +checksum = "8f4d6359d66a8bcefac26d48fcb0f3f0882bdf122b52121a1ae21f918706e040" dependencies = [ "byteorder", "dynasm", @@ -1954,9 +1929,9 @@ dependencies = [ [[package]] name = "wasmer-derive" -version = "4.2.2" +version = "4.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f08f80d166a9279671b7af7a09409c28ede2e0b4e3acabbf0e3cb22c8038ba7" +checksum = "1b374fd34d97b1c091d8675f9bc472df52dc6787d139d3762d42c7dc84813a9b" dependencies = [ "proc-macro-error", "proc-macro2", @@ -1966,9 +1941,9 @@ dependencies = [ [[package]] name = "wasmer-middlewares" -version = "4.2.2" +version = "4.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb4b87c0ea9f8636c81a8ab8f52bad01c8623c9fcbb3db5f367d5f157fada30" +checksum = "aab1347a1f81bf5929289db82b4f3966e9aecc4f874115110b6c0894ee8d9e77" dependencies = [ "wasmer", "wasmer-types", @@ -1977,9 +1952,9 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "4.2.2" +version = "4.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae2c892882f0b416783fb4310e5697f5c30587f6f9555f9d4f2be85ab39d5d3d" +checksum = "0caf1c87937b52aba8e9f920a278e1beda282f7439612c0b48f51a58e7a87bab" dependencies = [ "bytecheck", "enum-iterator", @@ -1993,9 +1968,9 @@ dependencies = [ [[package]] name = "wasmer-vm" -version = "4.2.2" +version = "4.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c0a9a57b627fb39e5a491058d4365f099bc9b140031c000fded24a3306d9480" +checksum = "58315c25492bc72a33f47a7d7fb0869a0106fc0164ec051e349a9e1eddba9a01" dependencies = [ "backtrace", "cc", diff --git a/libwasmvm/Cargo.toml b/libwasmvm/Cargo.toml index 6cef5d3c1..5821254b1 100644 --- a/libwasmvm/Cargo.toml +++ b/libwasmvm/Cargo.toml @@ -26,8 +26,8 @@ default = [] backtraces = [] [dependencies] -cosmwasm-std = { git = "https://github.com/CosmWasm/cosmwasm.git", rev = "v2.0.0-beta.0", features = ["staking", "stargate", "iterator"] } -cosmwasm-vm = { git = "https://github.com/CosmWasm/cosmwasm.git", rev = "v2.0.0-beta.0", features = ["staking", "stargate", "iterator"] } +cosmwasm-std = { git = "https://github.com/CosmWasm/cosmwasm.git", rev = "v2.0.0-beta.1", features = ["staking", "stargate", "iterator"] } +cosmwasm-vm = { git = "https://github.com/CosmWasm/cosmwasm.git", rev = "v2.0.0-beta.1", features = ["staking", "stargate", "iterator"] } errno = "0.3.8" serde_json = "1.0.91" thiserror = "1.0.38" diff --git a/libwasmvm/bindings.h b/libwasmvm/bindings.h index 9d7717b2f..00bb0ec3a 100644 --- a/libwasmvm/bindings.h +++ b/libwasmvm/bindings.h @@ -337,6 +337,10 @@ typedef struct GoApiVtable { struct UnmanagedVector *canonicalized_address_out, struct UnmanagedVector *err_msg_out, uint64_t *gas_used); + int32_t (*validate_address)(const struct api_t *api, + struct U8SliceView input, + struct UnmanagedVector *err_msg_out, + uint64_t *gas_used); } GoApiVtable; typedef struct GoApi { diff --git a/libwasmvm/src/api.rs b/libwasmvm/src/api.rs index 1cc0bd642..a50a43f88 100644 --- a/libwasmvm/src/api.rs +++ b/libwasmvm/src/api.rs @@ -34,6 +34,14 @@ pub struct GoApiVtable { gas_used: *mut u64, ) -> i32, >, + pub validate_address: Option< + extern "C" fn( + api: *const api_t, + input: U8SliceView, + err_msg_out: *mut UnmanagedVector, + gas_used: *mut u64, + ) -> i32, + >, } impl Vtable for GoApiVtable {} @@ -53,7 +61,7 @@ pub struct GoApi { unsafe impl Send for GoApi {} impl BackendApi for GoApi { - fn canonical_address(&self, human: &str) -> BackendResult> { + fn addr_canonicalize(&self, human: &str) -> BackendResult> { let mut output = UnmanagedVector::default(); let mut error_msg = UnmanagedVector::default(); let mut used_gas = 0_u64; @@ -86,7 +94,7 @@ impl BackendApi for GoApi { (result, gas_info) } - fn human_address(&self, canonical: &[u8]) -> BackendResult { + fn addr_humanize(&self, canonical: &[u8]) -> BackendResult { let mut output = UnmanagedVector::default(); let mut error_msg = UnmanagedVector::default(); let mut used_gas = 0_u64; @@ -125,4 +133,27 @@ impl BackendApi for GoApi { .and_then(|human_data| String::from_utf8(human_data).map_err(BackendError::from)); (result, gas_info) } + + fn addr_validate(&self, input: &str) -> BackendResult<()> { + let mut error_msg = UnmanagedVector::default(); + let mut used_gas = 0_u64; + let validate_address = self + .vtable + .validate_address + .expect("vtable function 'validate_address' not set"); + let go_error: GoError = validate_address( + self.state, + U8SliceView::new(Some(input.as_bytes())), + &mut error_msg as *mut UnmanagedVector, + &mut used_gas as *mut u64, + ) + .into(); + + let gas_info = GasInfo::with_cost(used_gas); + + // return complete error message (reading from buffer for GoError::Other) + let default = || format!("Failed to validate the address: {input}"); + let result = unsafe { go_error.into_result(error_msg, default) }; + (result, gas_info) + } } diff --git a/types/api.go b/types/api.go index 9f506160f..9fd1f7a26 100644 --- a/types/api.go +++ b/types/api.go @@ -7,9 +7,12 @@ type ( // CanonicalizeAddressFunc is a type for functions that convert a human readable address (typically bech32) // to a canonical address (bytes). CanonicalizeAddressFunc func(string) ([]byte, uint64, error) + // ValidateAddressFunc is a type for functions that validate a human readable address (typically bech32). + ValidateAddressFunc func(string) (uint64, error) ) type GoAPI struct { HumanizeAddress HumanizeAddressFunc CanonicalizeAddress CanonicalizeAddressFunc + ValidateAddress ValidateAddressFunc } From c953d44bd4e24965dfa35008e2220feb7932d5c6 Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Thu, 25 Jan 2024 18:03:11 +0100 Subject: [PATCH 2/8] Add GoAPI change to migration doc --- docs/MIGRATING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/MIGRATING.md b/docs/MIGRATING.md index cd85c293f..d0851fc66 100644 --- a/docs/MIGRATING.md +++ b/docs/MIGRATING.md @@ -29,6 +29,10 @@ - `VM.StoreCode` now returns a `uint64` containing the gas cost in CosmWasm gas and takes a gas limit as argument. This was previously calculated in wasmd. The change brings consistency with the other functions that cause gas usage. +- `GoAPI` now requires an additional `ValidateAddress` function that validates + whether the given string is a valid address. This was previously done + internally using separate calls to `CanonicalizeAddress` and `HumanizeAddress` + but can be done more efficiently using a single call. ## Renamings From c7236da00ef2f497f606030f49445acc6408612e Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Fri, 26 Jan 2024 11:49:29 +0100 Subject: [PATCH 3/8] Add entrypoints to AnalysisReport --- internal/api/lib.go | 2 ++ types/types.go | 1 + 2 files changed, 3 insertions(+) diff --git a/internal/api/lib.go b/internal/api/lib.go index dd72358f2..72df827c1 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -160,10 +160,12 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) { return nil, errorWithMessage(err, errmsg) } requiredCapabilities := string(copyAndDestroyUnmanagedVector(report.required_capabilities)) + entrypoints := string(copyAndDestroyUnmanagedVector(report.entrypoints)) res := types.AnalysisReport{ HasIBCEntryPoints: bool(report.has_ibc_entry_points), RequiredFeatures: requiredCapabilities, RequiredCapabilities: requiredCapabilities, + Entrypoints: entrypoints, } return &res, nil } diff --git a/types/types.go b/types/types.go index df275bddc..0a7f12efe 100644 --- a/types/types.go +++ b/types/types.go @@ -196,6 +196,7 @@ type AnalysisReport struct { // Deprecated, use RequiredCapabilities. For now both fields contain the same value. RequiredFeatures string RequiredCapabilities string + Entrypoints string } type Metrics struct { From 4b2c7eed851b2642e08409fdd949c38930b20c0f Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Fri, 26 Jan 2024 11:50:44 +0100 Subject: [PATCH 4/8] Split entrypoints --- internal/api/lib.go | 2 +- types/types.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/api/lib.go b/internal/api/lib.go index 72df827c1..a85a6cf33 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -165,7 +165,7 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) { HasIBCEntryPoints: bool(report.has_ibc_entry_points), RequiredFeatures: requiredCapabilities, RequiredCapabilities: requiredCapabilities, - Entrypoints: entrypoints, + Entrypoints: strings.Split(entrypoints, ","), } return &res, nil } diff --git a/types/types.go b/types/types.go index 0a7f12efe..386e53e0c 100644 --- a/types/types.go +++ b/types/types.go @@ -196,7 +196,7 @@ type AnalysisReport struct { // Deprecated, use RequiredCapabilities. For now both fields contain the same value. RequiredFeatures string RequiredCapabilities string - Entrypoints string + Entrypoints []string } type Metrics struct { From 8be985b1833f81a704e573695e60b8073de114ae Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Fri, 26 Jan 2024 12:07:43 +0100 Subject: [PATCH 5/8] Remove deprecated RequiredFeatures --- ibc_test.go | 2 -- internal/api/lib.go | 1 - types/types.go | 4 +--- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/ibc_test.go b/ibc_test.go index 6bfdf49b3..fb8a76a5b 100644 --- a/ibc_test.go +++ b/ibc_test.go @@ -301,7 +301,6 @@ func TestAnalyzeCode(t *testing.T) { report, err := vm.AnalyzeCode(checksum) require.NoError(t, err) require.False(t, report.HasIBCEntryPoints) - require.Equal(t, "", report.RequiredFeatures) require.Equal(t, "", report.RequiredCapabilities) // Store IBC contract @@ -313,7 +312,6 @@ func TestAnalyzeCode(t *testing.T) { report2, err := vm.AnalyzeCode(checksum2) require.NoError(t, err) require.True(t, report2.HasIBCEntryPoints) - require.Equal(t, "iterator,stargate", report2.RequiredFeatures) require.Equal(t, "iterator,stargate", report2.RequiredCapabilities) } diff --git a/internal/api/lib.go b/internal/api/lib.go index a85a6cf33..45acfff04 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -163,7 +163,6 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) { entrypoints := string(copyAndDestroyUnmanagedVector(report.entrypoints)) res := types.AnalysisReport{ HasIBCEntryPoints: bool(report.has_ibc_entry_points), - RequiredFeatures: requiredCapabilities, RequiredCapabilities: requiredCapabilities, Entrypoints: strings.Split(entrypoints, ","), } diff --git a/types/types.go b/types/types.go index 386e53e0c..b98765b21 100644 --- a/types/types.go +++ b/types/types.go @@ -192,9 +192,7 @@ func EmptyGasReport(limit uint64) GasReport { // Contains static analysis info of the contract (the Wasm code to be precise). // This type is returned by VM.AnalyzeCode(). type AnalysisReport struct { - HasIBCEntryPoints bool - // Deprecated, use RequiredCapabilities. For now both fields contain the same value. - RequiredFeatures string + HasIBCEntryPoints bool RequiredCapabilities string Entrypoints []string } From fc13618a0aeeaf52d6cdf339025038a4593101cb Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Fri, 26 Jan 2024 12:39:44 +0100 Subject: [PATCH 6/8] Add migration docs --- docs/MIGRATING.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/MIGRATING.md b/docs/MIGRATING.md index d0851fc66..7c6a6be34 100644 --- a/docs/MIGRATING.md +++ b/docs/MIGRATING.md @@ -40,18 +40,19 @@ This section contains renamed symbols that do not require any further explanation. Some of the new names may be available in 1.x already in cases where the old name was deprecated. -| Old name | New name | Note | -| ------------------------ | --------------------------- | ----------------------------------------------------------- | -| `VM.Create` | `VM.StoreCode` | StoreCode brings consistency with wasmd naming | -| `SubcallResult` | `SubMsgResult` | Contracts do not "call" each other but send messages around | -| `SubcallResponse` | `SubMsgResponse` | Contracts do not "call" each other but send messages around | -| `HumanizeAddress` | `HumanizeAddressFunc` | Follow [best practice for naming function types][ft] | -| `CanonicalizeAddress` | `CanonicalizeAddressFunc` | Follow [best practice for naming function types][ft] | -| `GoAPI.HumanAddress` | `GoAPI.HumanizeAddress` | Perfer verbs for converters | -| `GoAPI.CanonicalAddress` | `GoAPI.CanonicalizeAddress` | Perfer verbs for converters | -| `CosmosMsg.Stargate` | `CosmosMsg.Any` | The message has nothing to do with Stargate | -| `StargateMsg` | `AnyMsg` | The message has nothing to do with Stargate | -| `QueryResponse` | `QueryResult` | Brings consistency with the naming of the other results | -| `VoteMsg.Vote` | `VoteMsg.Option` | Brings consistency with Cosmos SDK naming | +| Old name | New name | Note | +| --------------------------------- | ------------------------------------- | ------------------------------------------------------------ | +| `VM.Create` | `VM.StoreCode` | StoreCode brings consistency with wasmd naming | +| `AnalysisReport.RequiredFeatures` | `AnalysisReport.RequiredCapabilities` | Renamed for a long time, but now the old version was removed | +| `SubcallResult` | `SubMsgResult` | Contracts do not "call" each other but send messages around | +| `SubcallResponse` | `SubMsgResponse` | Contracts do not "call" each other but send messages around | +| `HumanizeAddress` | `HumanizeAddressFunc` | Follow [best practice for naming function types][ft] | +| `CanonicalizeAddress` | `CanonicalizeAddressFunc` | Follow [best practice for naming function types][ft] | +| `GoAPI.HumanAddress` | `GoAPI.HumanizeAddress` | Perfer verbs for converters | +| `GoAPI.CanonicalAddress` | `GoAPI.CanonicalizeAddress` | Perfer verbs for converters | +| `CosmosMsg.Stargate` | `CosmosMsg.Any` | The message has nothing to do with Stargate | +| `StargateMsg` | `AnyMsg` | The message has nothing to do with Stargate | +| `QueryResponse` | `QueryResult` | Brings consistency with the naming of the other results | +| `VoteMsg.Vote` | `VoteMsg.Option` | Brings consistency with Cosmos SDK naming | [ft]: https://stackoverflow.com/a/60073310 From 6967510d57e951976a9e5f6736df5b5dd88defc0 Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Wed, 31 Jan 2024 16:16:03 +0100 Subject: [PATCH 7/8] Check that provided API has ValidateAddress --- internal/api/lib.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/internal/api/lib.go b/internal/api/lib.go index 45acfff04..99a5add35 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -726,17 +726,22 @@ func errorWithMessage(err error, b C.UnmanagedVector) error { // to be caused by user data. func checkAndPinAPI(api *types.GoAPI, pinner runtime.Pinner) { if api == nil { - panic("API must not be nil. If you don't want to provide API functionality, please create an instance that returns an error on every call to HumanizeAddress() and CanonicalizeAddress().") + panic("API must not be nil. If you don't want to provide API functionality, please create an instance that returns an error on every call to HumanizeAddress(), CanonicalizeAddress() and ValidateAddress().") } // func cHumanizeAddress assumes this is set if api.HumanizeAddress == nil { - panic("HumanizeAddress in API must not be nil. If you don't want to provide API functionality, please create an instance that returns an error on every call to HumanizeAddress() and CanonicalizeAddress().") + panic("HumanizeAddress in API must not be nil. If you don't want to provide API functionality, please create an instance that returns an error on every call to HumanizeAddress(), CanonicalizeAddress() and ValidateAddress().") } // func cCanonicalizeAddress assumes this is set if api.CanonicalizeAddress == nil { - panic("CanonicalizeAddress in API must not be nil. If you don't want to provide API functionality, please create an instance that returns an error on every call to HumanizeAddress() and CanonicalizeAddress().") + panic("CanonicalizeAddress in API must not be nil. If you don't want to provide API functionality, please create an instance that returns an error on every call to HumanizeAddress(), CanonicalizeAddress() and ValidateAddress().") + } + + // func cValidateAddress assumes this is set + if api.ValidateAddress == nil { + panic("ValidateAddress in API must not be nil. If you don't want to provide API functionality, please create an instance that returns an error on every call to HumanizeAddress(), CanonicalizeAddress() and ValidateAddress().") } pinner.Pin(api) // this pointer is used in Rust (`state` in `C.GoApi`) and must not change From 0009ee3211dcdb13dc723743c08d018b67347c74 Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Wed, 31 Jan 2024 16:16:45 +0100 Subject: [PATCH 8/8] Add failing ValidateAddress for NewMockFailureAPI --- internal/api/mock_failure.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/api/mock_failure.go b/internal/api/mock_failure.go index 14b14369c..acc80f626 100644 --- a/internal/api/mock_failure.go +++ b/internal/api/mock_failure.go @@ -16,9 +16,14 @@ func MockFailureHumanizeAddress(canon []byte) (string, uint64, error) { return "", 0, fmt.Errorf("mock failure - human_address") } +func MockFailureValidateAddress(human string) (uint64, error) { + return 0, fmt.Errorf("mock failure - validate_address") +} + func NewMockFailureAPI() *types.GoAPI { return &types.GoAPI{ HumanizeAddress: MockFailureHumanizeAddress, CanonicalizeAddress: MockFailureCanonicalizeAddress, + ValidateAddress: MockFailureValidateAddress, } }