From 1c812a6c4d07617c2bd61fa0674c1e592abe7de3 Mon Sep 17 00:00:00 2001 From: pwang200 <354723+pwang200@users.noreply.github.com> Date: Mon, 12 Jan 2026 22:04:33 -0500 Subject: [PATCH] disable Wasm features added in Wasmi 1.0, and fix unit test fuel cost due to Wasmi 1.0 fuel changes (#6173) * disable 4 more wasm features * unit tests for disabled Wasmi 1.0 features * fix unit tests failed due to fuel changes * rearrange wasm feature unit tests * fix gas costs * Update src/test/app/wasm_fixtures/wat/custom_page_sizes.wat --------- Co-authored-by: Mayukha Vadari --- src/test/app/Wasm_test.cpp | 42 +++++++++++-------- src/test/app/wasm_fixtures/fixtures.cpp | 16 +++++++ src/test/app/wasm_fixtures/fixtures.h | 4 ++ .../wasm_fixtures/wat/custom_page_sizes.wat | 13 ++++++ src/test/app/wasm_fixtures/wat/memory64.wat | 21 ++++++++++ .../app/wasm_fixtures/wat/multi_memory.wat | 16 +++++++ .../app/wasm_fixtures/wat/wide_arithmetic.wat | 22 ++++++++++ src/xrpld/app/wasm/detail/WasmiVM.cpp | 4 ++ 8 files changed, 121 insertions(+), 17 deletions(-) create mode 100644 src/test/app/wasm_fixtures/wat/custom_page_sizes.wat create mode 100644 src/test/app/wasm_fixtures/wat/memory64.wat create mode 100644 src/test/app/wasm_fixtures/wat/multi_memory.wat create mode 100644 src/test/app/wasm_fixtures/wat/wide_arithmetic.wat diff --git a/src/test/app/Wasm_test.cpp b/src/test/app/Wasm_test.cpp index 95986f5a76..543f57cccd 100644 --- a/src/test/app/Wasm_test.cpp +++ b/src/test/app/Wasm_test.cpp @@ -95,7 +95,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == 6'912, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 3, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 59, std::to_string(re->cost)); } } @@ -183,7 +183,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == 0, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 38, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 151, std::to_string(re->cost)); } env.close(); @@ -196,7 +196,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == 5, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 76, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 190, std::to_string(re->cost)); } } @@ -214,7 +214,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == 55, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 696, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 1'137, std::to_string(re->cost)); } } @@ -233,7 +233,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == 34'432, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 145'573, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 151'155, std::to_string(re->cost)); } } @@ -258,7 +258,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == 700, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 2'701'528, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 2'886'069, std::to_string(re->cost)); } } @@ -294,7 +294,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == 1, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 842, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 25'503, std::to_string(re->cost)); } env.close(); @@ -328,7 +328,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == 1, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 40'102, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 64'763, std::to_string(re->cost)); } env.close(); @@ -377,7 +377,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == 1, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 40'102, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 64'763, std::to_string(re->cost)); } } @@ -388,7 +388,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == 1, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 40'102, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 64'763, std::to_string(re->cost)); } } @@ -410,7 +410,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == -201, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 5'012, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 28'148, std::to_string(re->cost)); } } @@ -432,7 +432,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == -201, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 5'012, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 28'148, std::to_string(re->cost)); } } @@ -570,11 +570,11 @@ struct Wasm_test : public beast::unit_test::suite std::vector const wasm(wasmStr.begin(), wasmStr.end()); TestHostFunctions hf(env, 0); - auto re = runEscrowWasm(wasm, hf, funcName, {}, 100'000); + auto re = runEscrowWasm(wasm, hf, funcName, {}, 200'000); if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == 1, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 97'356, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 110'699, std::to_string(re->cost)); } env.close(); } @@ -589,7 +589,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re.has_value())) { BEAST_EXPECTS(re->result == 1, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 2'054, std::to_string(re->cost)); + BEAST_EXPECTS(re->cost == 4'259, std::to_string(re->cost)); } env.close(); } @@ -703,7 +703,7 @@ struct Wasm_test : public beast::unit_test::suite Bytes const wasm(wasmStr.begin(), wasmStr.end()); TestHostFunctions hfs(env, 0); - auto const allowance = 154'545; + auto const allowance = 189'508; auto re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, allowance); if (BEAST_EXPECT(re.has_value())) @@ -804,6 +804,14 @@ struct Wasm_test : public beast::unit_test::suite runFinishFunction(proposalTailCallHex).has_value() == false); BEAST_EXPECT( runFinishFunction(proposalExtendedConstHex).has_value() == false); + BEAST_EXPECT( + runFinishFunction(proposalMultiMemoryHex).has_value() == false); + BEAST_EXPECT( + runFinishFunction(proposalCustomPageSizesHex).has_value() == false); + BEAST_EXPECT( + runFinishFunction(proposalMemory64Hex).has_value() == false); + BEAST_EXPECT( + runFinishFunction(proposalWideArithmeticHex).has_value() == false); } void @@ -909,7 +917,7 @@ struct Wasm_test : public beast::unit_test::suite if (BEAST_EXPECT(re)) { BEAST_EXPECTS(re->result == 7, std::to_string(re->result)); - BEAST_EXPECTS(re->cost == 10, std::to_string(re->result)); + BEAST_EXPECTS(re->cost == 430, std::to_string(re->cost)); } } diff --git a/src/test/app/wasm_fixtures/fixtures.cpp b/src/test/app/wasm_fixtures/fixtures.cpp index 97143f1f61..493d5aca8a 100644 --- a/src/test/app/wasm_fixtures/fixtures.cpp +++ b/src/test/app/wasm_fixtures/fixtures.cpp @@ -1176,6 +1176,22 @@ extern std::string const proposalExtendedConstHex = "0061736d010000000105016000017f030201000609017f00410a41206a0b070a010666696e" "69736800000a090107002300412a460b"; +extern std::string const proposalMultiMemoryHex = + "0061736d010000000105016000017f0302010005050200000001070a010666696e69736800" + "000a060104003f010b"; + +extern std::string const proposalCustomPageSizesHex = + "0061736d010000000105016000017f0302010005040108010a070a010666696e6973680000" + "0a0601040041010b0010046e616d65010901000666696e697368"; + +extern std::string const proposalMemory64Hex = + "0061736d010000000105016000017f030201000503010401070a010666696e69736800000a" + "10010e004200412a3a00003f004201510b0010046e616d65010901000666696e697368"; + +extern std::string const proposalWideArithmeticHex = + "0061736d010000000105016000017f03020100070a010666696e69736800000a0e010c0042" + "014202fc161a1a41010b0010046e616d65010901000666696e697368"; + extern std::string const trapDivideBy0Hex = "0061736d010000000105016000017f03020100070a010666696e69736800000a0c010a0041" "2a41006d1a41010b"; diff --git a/src/test/app/wasm_fixtures/fixtures.h b/src/test/app/wasm_fixtures/fixtures.h index 32f71883f8..bb7a80f791 100644 --- a/src/test/app/wasm_fixtures/fixtures.h +++ b/src/test/app/wasm_fixtures/fixtures.h @@ -55,6 +55,10 @@ extern std::string const proposalBulkMemoryHex; extern std::string const proposalRefTypesHex; extern std::string const proposalTailCallHex; extern std::string const proposalExtendedConstHex; +extern std::string const proposalMultiMemoryHex; +extern std::string const proposalCustomPageSizesHex; +extern std::string const proposalMemory64Hex; +extern std::string const proposalWideArithmeticHex; extern std::string const trapDivideBy0Hex; extern std::string const trapIntOverflowHex; diff --git a/src/test/app/wasm_fixtures/wat/custom_page_sizes.wat b/src/test/app/wasm_fixtures/wat/custom_page_sizes.wat new file mode 100644 index 0000000000..a9d404fadc --- /dev/null +++ b/src/test/app/wasm_fixtures/wat/custom_page_sizes.wat @@ -0,0 +1,13 @@ +(module + ;; Define a memory with 1 initial page. + ;; CRITICAL: We explicitly set the page size to 1 kilobyte. + ;; Standard Wasm implies (pagesize 65536). + (memory 1 (pagesize 1024)) + + (func $finish (result i32) + ;; If this module instantiates, the runtime accepted the custom page size. + i32.const 1 + ) + + (export "finish" (func $finish)) +) diff --git a/src/test/app/wasm_fixtures/wat/memory64.wat b/src/test/app/wasm_fixtures/wat/memory64.wat new file mode 100644 index 0000000000..02c8f4f590 --- /dev/null +++ b/src/test/app/wasm_fixtures/wat/memory64.wat @@ -0,0 +1,21 @@ +(module + ;; Define a 64-bit memory (index type i64) + ;; Start with 1 page. + (memory i64 1) + + (func $finish (result i32) + ;; 1. Perform a store using a 64-bit address. + ;; Even if the value is small (0), the type MUST be i64. + i64.const 0 ;; Address (64-bit) + i32.const 42 ;; Value (32-bit) + i32.store8 ;; Opcode doesn't change, but validation rules do. + + ;; 2. check memory size + ;; memory.size now returns an i64. + memory.size + i64.const 1 + i64.eq ;; Returns i32 (1 if true) + ) + + (export "finish" (func $finish)) +) diff --git a/src/test/app/wasm_fixtures/wat/multi_memory.wat b/src/test/app/wasm_fixtures/wat/multi_memory.wat new file mode 100644 index 0000000000..c2f36e253f --- /dev/null +++ b/src/test/app/wasm_fixtures/wat/multi_memory.wat @@ -0,0 +1,16 @@ +(module + ;; Memory 0: Index 0 (Empty) + (memory 0) + + ;; Memory 1: Index 1 (Size 1 page) + ;; If multi-memory is disabled, this line causes a validation error (max 1 memory). + (memory 1) + + (func $finish (result i32) + ;; Query size of Memory Index 1. + ;; Should return 1 (success). + memory.size 1 + ) + + (export "finish" (func $finish)) +) diff --git a/src/test/app/wasm_fixtures/wat/wide_arithmetic.wat b/src/test/app/wasm_fixtures/wat/wide_arithmetic.wat new file mode 100644 index 0000000000..cd796162ae --- /dev/null +++ b/src/test/app/wasm_fixtures/wat/wide_arithmetic.wat @@ -0,0 +1,22 @@ +(module + (func $finish (result i32) + ;; 1. Push operands + i64.const 1 + i64.const 2 + + ;; 2. Execute Wide Multiplication + ;; If the feature is DISABLED, the parser/validator will trap here + ;; with "unknown instruction" or "invalid opcode". + ;; Input: [i64, i64] -> Output: [i64, i64] + i64.mul_wide_u + + ;; 3. Clean up the stack (drop the two i64 results) + drop + drop + + ;; 4. Return 1 to signal that validation passed + i32.const 1 + ) + + (export "finish" (func $finish)) +) diff --git a/src/xrpld/app/wasm/detail/WasmiVM.cpp b/src/xrpld/app/wasm/detail/WasmiVM.cpp index 9d3dded78b..fa61ec2679 100644 --- a/src/xrpld/app/wasm/detail/WasmiVM.cpp +++ b/src/xrpld/app/wasm/detail/WasmiVM.cpp @@ -510,6 +510,10 @@ WasmiEngine::init() wasmi_config_wasm_tail_call_set(config, false); wasmi_config_wasm_extended_const_set(config, false); wasmi_config_floats_set(config, false); + wasmi_config_wasm_multi_memory_set(config, false); + wasmi_config_wasm_custom_page_sizes_set(config, false); + wasmi_config_wasm_memory64_set(config, false); + wasmi_config_wasm_wide_arithmetic_set(config, false); return std::unique_ptr( wasm_engine_new_with_config(config), &wasm_engine_delete);