diff --git a/.gitignore b/.gitignore index 5f55306f4f..1f58acf128 100644 --- a/.gitignore +++ b/.gitignore @@ -121,3 +121,5 @@ CMakeUserPresets.json bld.rippled/ generated +guard_checker +guard_checker.dSYM diff --git a/src/ripple/app/hook/Guard.h b/src/ripple/app/hook/Guard.h index f395af4481..1d0fd573cb 100644 --- a/src/ripple/app/hook/Guard.h +++ b/src/ripple/app/hook/Guard.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -282,7 +283,8 @@ check_guard( * might have unforeseen consequences, without also rolling back further * changes that are fine. */ - uint64_t rulesVersion = 0 + uint64_t rulesVersion = 0, + std::set* out_callees = nullptr ) { @@ -492,17 +494,27 @@ check_guard( { REQUIRE(1); uint64_t callee_idx = LEB(); - // disallow calling of user defined functions inside a hook + + // record user-defined function calls if tracking is enabled if (callee_idx > last_import_idx) { - GUARDLOG(hook::log::CALL_ILLEGAL) - << "GuardCheck " - << "Hook calls a function outside of the whitelisted " - "imports " - << "codesec: " << codesec << " hook byte offset: " << i - << "\n"; + if (out_callees != nullptr) + { + // record the callee for call graph analysis + out_callees->insert(callee_idx); + } + else + { + // if not tracking, maintain original behavior: reject + GUARDLOG(hook::log::CALL_ILLEGAL) + << "GuardCheck " + << "Hook calls a function outside of the whitelisted " + "imports " + << "codesec: " << codesec << " hook byte offset: " << i + << "\n"; - return {}; + return {}; + } } // enforce guard call limit @@ -837,6 +849,42 @@ validateGuards( */ uint64_t rulesVersion = 0) { + // Structure to track function call graph information + struct FunctionInfo + { + int func_idx; + std::set callees; // functions this function calls + std::set callers; // functions that call this function + bool has_loops; // whether this function contains loops + uint64_t local_wce; // local worst-case execution count + uint64_t total_wce; // total WCE including callees + bool wce_calculated; // whether total_wce has been computed + bool in_calculation; // for cycle detection in WCE calculation + + FunctionInfo() + : func_idx(-1) + , has_loops(false) + , local_wce(0) + , total_wce(0) + , wce_calculated(false) + , in_calculation(false) + { + } + + FunctionInfo(int idx, uint64_t local_wce_val, bool has_loops_val) + : func_idx(idx) + , has_loops(has_loops_val) + , local_wce(local_wce_val) + , total_wce(0) + , wce_calculated(false) + , in_calculation(false) + { + } + }; + + // Call graph: maps function index to its information + std::map call_graph; + uint64_t byteCount = wasm.size(); // 63 bytes is the smallest possible valid hook wasm @@ -1176,6 +1224,12 @@ validateGuards( if (DEBUG_GUARD) printf("Function map: func %d -> type %d\n", j, type_idx); func_type_map[j] = type_idx; + + // Step 4: Initialize FunctionInfo for each user-defined + // function func_idx starts from last_import_number + 1 + int actual_func_idx = last_import_number + 1 + j; + call_graph[actual_func_idx] = FunctionInfo(); + call_graph[actual_func_idx].func_idx = actual_func_idx; } } @@ -1217,9 +1271,6 @@ validateGuards( return {}; } - int64_t maxInstrCountHook = 0; - int64_t maxInstrCountCbak = 0; - // second pass... where we check all the guard function calls follow the // guard rules minimal other validation in this pass because first pass // caught most of it @@ -1253,6 +1304,7 @@ validateGuards( std::optional< std::reference_wrapper const>> first_signature; + bool helper_function = false; if (auto const& usage = import_type_map.find(j); usage != import_type_map.end()) { @@ -1288,7 +1340,7 @@ validateGuards( } } } - else if (j == hook_type_idx) + else if (j == hook_type_idx) // hook() or cbak() function type { // pass } @@ -1301,7 +1353,8 @@ validateGuards( << "Codesec: " << section_type << " " << "Local: " << j << " " << "Offset: " << i << "\n"; - return {}; + // return {}; + helper_function = true; } int param_count = parseLeb128(wasm, i, &i); @@ -1318,12 +1371,19 @@ validateGuards( return {}; } } + else if (helper_function) + { + // pass + } else if (param_count != (*first_signature).get().size() - 1) { GUARDLOG(hook::log::FUNC_TYPE_INVALID) << "Malformed transaction. " << "Hook API: " << *first_name - << " has the wrong number of parameters.\n"; + << " has the wrong number of parameters.\n" + << "param_count: " << param_count << " " + << "first_signature: " + << (*first_signature).get().size() - 1 << "\n"; return {}; } @@ -1370,6 +1430,10 @@ validateGuards( return {}; } } + else if (helper_function) + { + // pass + } else if ((*first_signature).get()[k + 1] != param_type) { GUARDLOG(hook::log::FUNC_PARAM_INVALID) @@ -1446,6 +1510,10 @@ validateGuards( return {}; } } + else if (helper_function) + { + // pass + } else if ((*first_signature).get()[0] != result_type) { GUARDLOG(hook::log::FUNC_RETURN_INVALID) @@ -1497,6 +1565,17 @@ validateGuards( // execution to here means we are up to the actual expr for the // codesec/function + // Step 5: Calculate actual function index and prepare callees + // tracking + int actual_func_idx = last_import_number + 1 + j; + std::set* out_callees_ptr = nullptr; + + // Only track callees if this function is in the call_graph + if (call_graph.find(actual_func_idx) != call_graph.end()) + { + out_callees_ptr = &call_graph[actual_func_idx].callees; + } + auto valid = check_guard( wasm, j, @@ -1506,33 +1585,188 @@ validateGuards( last_import_number, guardLog, guardLogAccStr, - rulesVersion); + rulesVersion, + out_callees_ptr); if (!valid) return {}; - if (hook_func_idx && *hook_func_idx == j) - maxInstrCountHook = *valid; - else if (cbak_func_idx && *cbak_func_idx == j) - maxInstrCountCbak = *valid; - else + // Step 5: Store local WCE and build bidirectional call + // relationships + if (call_graph.find(actual_func_idx) != call_graph.end()) { - if (DEBUG_GUARD) - printf( - "code section: %d not hook_func_idx: %d or " - "cbak_func_idx: %d\n", - j, - *hook_func_idx, - (cbak_func_idx ? *cbak_func_idx : -1)); - // assert(false); + call_graph[actual_func_idx].local_wce = *valid; + + // Build bidirectional relationships: for each callee, add + // this function as a caller + for (int callee_idx : call_graph[actual_func_idx].callees) + { + if (call_graph.find(callee_idx) != call_graph.end()) + { + call_graph[callee_idx].callers.insert( + actual_func_idx); + } + } } + + // Note: We will calculate total WCE later after processing all + // functions i = code_end; } } i = next_section; } - // execution to here means guards are installed correctly + // Step 6: Cycle detection using DFS + // Lambda function for DFS-based cycle detection + std::set visited; + std::set rec_stack; + std::function detect_cycles_dfs = [&](int func_idx) -> bool { + if (rec_stack.find(func_idx) != rec_stack.end()) + { + // Found a cycle: func_idx is already in the recursion stack + return true; + } + + if (visited.find(func_idx) != visited.end()) + { + // Already visited and no cycle found from this node + return false; + } + + visited.insert(func_idx); + rec_stack.insert(func_idx); + + // Check all callees + if (call_graph.find(func_idx) != call_graph.end()) + { + for (int callee_idx : call_graph[func_idx].callees) + { + if (detect_cycles_dfs(callee_idx)) + { + return true; + } + } + } + + rec_stack.erase(func_idx); + return false; + }; + + // Run cycle detection on all user-defined functions + for (const auto& [func_idx, func_info] : call_graph) + { + if (detect_cycles_dfs(func_idx)) + { + GUARDLOG(hook::log::CALL_ILLEGAL) + << "GuardCheck: Recursive function calls detected. " + << "Hooks cannot contain recursive or mutually recursive " + "functions.\n"; + return {}; + } + } + + // Step 7: Calculate total WCE for each function using bottom-up approach + // Lambda function for recursive WCE calculation with memoization + std::function calculate_function_wce = + [&](int func_idx) -> uint64_t { + // Check if function exists in call graph + if (call_graph.find(func_idx) == call_graph.end()) + { + // This is an imported function, WCE = 0 (already accounted for) + return 0; + } + + FunctionInfo& func_info = call_graph[func_idx]; + + // If already calculated, return cached result + if (func_info.wce_calculated) + { + return func_info.total_wce; + } + + // Detect circular dependency in WCE calculation (should not happen + // after cycle detection) + if (func_info.in_calculation) + { + GUARDLOG(hook::log::CALL_ILLEGAL) + << "GuardCheck: Internal error - circular dependency detected " + "during WCE calculation.\n"; + return 0xFFFFFFFFU; // Return large value to trigger overflow error + } + + func_info.in_calculation = true; + + // Start with local WCE + uint64_t total = func_info.local_wce; + + // Add WCE of all callees + for (int callee_idx : func_info.callees) + { + uint64_t callee_wce = calculate_function_wce(callee_idx); + + // Check for overflow + if (total > 0xFFFFU || callee_wce > 0xFFFFU || + (total + callee_wce) > 0xFFFFU) + { + func_info.in_calculation = false; + return 0xFFFFFFFFU; // Signal overflow + } + + total += callee_wce; + } + + func_info.total_wce = total; + func_info.wce_calculated = true; + func_info.in_calculation = false; + + return total; + }; + + // Calculate WCE for hook and cbak functions + int64_t hook_wce_actual = 0; + int64_t cbak_wce_actual = 0; + + if (hook_func_idx) + { + int actual_hook_idx = last_import_number + 1 + *hook_func_idx; + hook_wce_actual = calculate_function_wce(actual_hook_idx); + + if (hook_wce_actual >= 0xFFFFU) + { + GUARDLOG(hook::log::INSTRUCTION_EXCESS) + << "GuardCheck: hook() function exceeds maximum instruction " + "count (65535). " + << "Total WCE including called functions: " << hook_wce_actual + << "\n"; + return {}; + } + + if (DEBUG_GUARD) + printf("hook() total WCE: %ld\n", hook_wce_actual); + } + + if (cbak_func_idx) + { + int actual_cbak_idx = last_import_number + 1 + *cbak_func_idx; + cbak_wce_actual = calculate_function_wce(actual_cbak_idx); + + if (cbak_wce_actual >= 0xFFFFU) + { + GUARDLOG(hook::log::INSTRUCTION_EXCESS) + << "GuardCheck: cbak() function exceeds maximum instruction " + "count (65535). " + << "Total WCE including called functions: " << cbak_wce_actual + << "\n"; + return {}; + } + + if (DEBUG_GUARD) + printf("cbak() total WCE: %ld\n", cbak_wce_actual); + } + + // execution to here means guards are installed correctly and WCE is within + // limits - return std::pair{maxInstrCountHook, maxInstrCountCbak}; + return std::pair{hook_wce_actual, cbak_wce_actual}; } diff --git a/src/test/app/SetHook_test.cpp b/src/test/app/SetHook_test.cpp index 0c7be29e81..b4016d7c18 100644 --- a/src/test/app/SetHook_test.cpp +++ b/src/test/app/SetHook_test.cpp @@ -75,6 +75,16 @@ using JSSMap = [[maybe_unused]] std::string const x##_hash_str = to_string(x##_hash); \ [[maybe_unused]] Keylet const x##_keylet = keylet::hookDefinition(x##_hash); +#define EXPECT_HOOK_FEE(x, fee) \ + do \ + { \ + auto const hookSLE = env.le(x##_keylet); \ + BEAST_EXPECTS( \ + hookSLE->getFieldAmount(sfFee) == XRPAmount{fee}, \ + "Hook fee mismatch: expected " #fee " got " + \ + to_string(hookSLE->getFieldAmount(sfFee))); \ + } while (false) + class SetHook0_test : public beast::unit_test::suite { private: @@ -2330,6 +2340,7 @@ class SetHook0_test : public beast::unit_test::suite M("Install Accept Hook"), HSFEE); env.close(); + EXPECT_HOOK_FEE(accept, 9); env(pay(bob, alice, XRP(1)), M("Test Accept Hook"), fee(XRP(1))); env.close(); @@ -2351,6 +2362,7 @@ class SetHook0_test : public beast::unit_test::suite M("Install Rollback Hook"), HSFEE); env.close(); + EXPECT_HOOK_FEE(rollback, 9); env(pay(bob, alice, XRP(1)), M("Test Rollback Hook"), @@ -2413,7 +2425,7 @@ class SetHook0_test : public beast::unit_test::suite // same loop again but with a guard call { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( (module (type (;0;) (func (param i32 i32) (result i64))) (type (;1;) (func (param i32 i32) (result i32))) @@ -2448,15 +2460,17 @@ class SetHook0_test : public beast::unit_test::suite (export "hook" (func 2))) )[test.hook]"]; - env(ripple::test::jtx::hook(alice, {{hso(hook)}}, 0), + HASH_WASM(hook); + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm)}}, 0), M("Loop 1 with guards"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 14); } // simple looping, c { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -2472,11 +2486,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,2); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("Loop 2 in C"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 100); env(pay(bob, alice, XRP(1)), M("Test Loop 2"), fee(XRP(1))); env.close(); @@ -2484,7 +2501,7 @@ class SetHook0_test : public beast::unit_test::suite // complex looping, c { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -2516,11 +2533,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,2); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("Loop 3 in C"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 1944); env(pay(bob, alice, XRP(1)), M("Test Loop 3"), fee(XRP(1))); env.close(); @@ -2528,7 +2548,7 @@ class SetHook0_test : public beast::unit_test::suite // complex looping missing a guard { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -2562,7 +2582,8 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("Loop 4 in C"), HSFEE, ter(temMALFORMED)); @@ -2570,6 +2591,809 @@ class SetHook0_test : public beast::unit_test::suite } } + void + testHelperFunctions(FeatureBitset features) + { + testcase("Test helper functions and recursion detection"); + using namespace jtx; + Env env{*this, features}; + + auto const alice = Account{"alice"}; + auto const bob = Account{"bob"}; + env.fund(XRP(10000), alice, bob); + env.close(); + + // Test 1: Valid helper function without loops - should pass + { + /* + #include + extern int32_t _g(uint32_t id, uint32_t maxiter); + extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t + error_code); + extern int64_t hook_pos(void); + + int64_t helper(int64_t n) { return n + hook_pos(); } + + int64_t cbak(uint32_t reserved) { + _g(1, 1); + int64_t result = helper(34); + return accept(0, 0, result); + } + + int64_t hook(uint32_t reserved) { + _g(1, 1); + int64_t result = helper(5); + return accept(0, 0, result); + } + */ + TestHook hook_wasm = wasm[R"[test.hook]( + (module + (type (;0;) (func (param i32) (result i64))) + (type (;1;) (func (result i64))) + (type (;2;) (func (param i32 i32) (result i32))) + (type (;3;) (func (param i32 i32 i64) (result i64))) + (type (;4;) (func (param i64) (result i64))) + (import "env" "hook_pos" (func (;0;) (type 1))) + (import "env" "_g" (func (;1;) (type 2))) + (import "env" "accept" (func (;2;) (type 3))) + (func (;3;) (type 4) (param i64) (result i64) + call 0 + local.get 0 + i64.add) + (func (;4;) (type 0) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 1 + drop + i32.const 0 + i32.const 0 + i64.const 34 + call 3 + call 2) + (func (;5;) (type 0) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 1 + drop + i32.const 0 + i32.const 0 + i64.const 5 + call 3 + call 2) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "cbak" (func 4)) + (export "hook" (func 5))) + )[test.hook]"]; + HASH_WASM(hook); + + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), + M("Valid helper function without loops"), + HSFEE, + ter(tesSUCCESS)); + env.close(); + EXPECT_HOOK_FEE(hook, 14); + + env(pay(bob, alice, XRP(1)), M("Test helper 1"), fee(XRP(1))); + env.close(); + } + + // Test 2: Helper function with guarded loop - should pass + { + /* + #include + extern int32_t _g(uint32_t id, uint32_t maxiter); + extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t + error_code); extern int64_t hook_pos(void); + + int64_t helper(int64_t n) { + int64_t sum = 0; + for (int i = 0; i < 3; ++i) { + _g(2, 4); + sum += i * n; + } + return sum; + } + + int64_t cbak(uint32_t reserved) { + _g(1, 1); + int64_t result = helper(2); + return accept(0, 0, result); + } + + int64_t hook(uint32_t reserved) { + _g(1, 1); + int64_t result = helper(3); + return accept(0, 0, result); + } + */ + TestHook hook_wasm = wasm[R"[test.hook]( + (module + (type (;0;) (func (param i32) (result i64))) + (type (;1;) (func (param i32 i32) (result i32))) + (type (;2;) (func (param i32 i32 i64) (result i64))) + (type (;3;) (func (param i64) (result i64))) + (import "env" "_g" (func (;0;) (type 1))) + (import "env" "accept" (func (;1;) (type 2))) + (func (;2;) (type 0) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 0 + i32.const 0 + i64.const 3 + call 3 + call 1) + (func (;3;) (type 3) (param i64) (result i64) + i32.const 2 + i32.const 4 + call 0 + drop + i32.const 2 + i32.const 4 + call 0 + drop + i32.const 2 + i32.const 4 + call 0 + drop + local.get 0 + i64.const 3 + i64.mul) + (func (;4;) (type 0) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 0 + i32.const 0 + i64.const 2 + call 3 + call 1) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "hook" (func 2)) + (export "cbak" (func 4))) + )[test.hook]"]; + HASH_WASM(hook); + + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), + M("Helper function with guarded loop"), + HSFEE, + ter(tesSUCCESS)); + env.close(); + EXPECT_HOOK_FEE(hook, 26); + + env(pay(bob, alice, XRP(1)), M("Test helper 2"), fee(XRP(1))); + env.close(); + } + + // Test 3: Direct recursion - should fail + { + /* + #include + extern int32_t _g(uint32_t id, uint32_t maxiter); + extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t + error_code); + extern int64_t hook_pos(void); + + int64_t recursive_func(int64_t n) { + if (n <= 0) + return 0; + return n + recursive_func(n - hook_pos()); + } + int64_t cbak(uint32_t reserved) { + _g(1, 1); + int64_t result = recursive_func(5); + return accept(0, 0, result); + } + + int64_t hook(uint32_t reserved) { + _g(1, 1); + int64_t result = recursive_func(10); + return accept(0, 0, result); + } + + */ + TestHook hook = wasm[R"[test.hook]( + (module + (type (;0;) (func (param i32) (result i64))) + (type (;1;) (func (param i32 i32) (result i32))) + (type (;2;) (func (param i32 i32 i64) (result i64))) + (type (;3;) (func (result i64))) + (type (;4;) (func (param i64) (result i64))) + (import "env" "_g" (func $g (type 1))) + (import "env" "accept" (func $accept (type 2))) + (import "env" "hook_pos" (func $hook_pos (type 3))) + (func $recursive_func (type 4) (param $n i64) (result i64) + (if (result i64) + (i64.le_s (local.get $n) (i64.const 0)) + (then + (i64.const 0) + ) + (else + (i64.add + (local.get $n) + (call $recursive_func + (i64.sub (local.get $n) (call $hook_pos)) + ) + ) + ) + ) + ) + (func (;3;) (type 0) (param i32) (result i64) ;; cbak + i32.const 1 + i32.const 1 + call $g + drop + i32.const 0 + i32.const 0 + i64.const 5 + call $recursive_func + call $accept + ) + (func (;5;) (type 0) (param i32) (result i64) ;; hook + i32.const 1 + i32.const 1 + call $g + drop + i32.const 0 + i32.const 0 + i64.const 10 + call $recursive_func + call $accept + ) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "cbak" (func 3)) + (export "hook" (func 5))) + )[test.hook]"]; + + env(ripple::test::jtx::hook(alice, {{hso(hook)}}, 0), + M("Direct recursion should fail"), + HSFEE, + ter(temMALFORMED)); + env.close(); + } + + // Test 4: Indirect recursion (A -> B -> A) - should fail + { + /* + #include + extern int32_t _g(uint32_t id, uint32_t maxiter); + extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t + error_code); + + int64_t func_b(int64_t n); + + int64_t func_a(int64_t n) { + if (n <= 0) + return 0; + return n + func_b(n - 1); + } + + int64_t func_b(int64_t n) { + if (n <= 0) + return 0; + return n + func_a(n - 1); + } + + int64_t cbak(uint32_t reserved) { + _g(1, 1); + int64_t result = func_a(5); + return accept(0, 0, result); + } + + int64_t hook(uint32_t reserved) { + _g(1, 1); + int64_t result = func_a(10); + return accept(0, 0, result); + } + + */ + TestHook hook = wasm[R"[test.hook]( + (module + (import "env" "_g" (func $_g (param i32 i32) (result i32))) + (import "env" "accept" (func $accept (param i32 i32 i64) (result i64))) + (type $func_type (func (param i64) (result i64))) + (func $func_b (param $n i64) (result i64) + (if (result i64) + (i64.le_s (local.get $n) (i64.const 0)) + (then + (i64.const 0) + ) + (else + (i64.add + (local.get $n) + (call $func_a + (i64.sub (local.get $n) (i64.const 1)) + ) + ) + ) + ) + ) + (func $func_a (param $n i64) (result i64) + (if (result i64) + (i64.le_s (local.get $n) (i64.const 0)) + (then + (i64.const 0) + ) + (else + (i64.add + (local.get $n) + (call $func_b + (i64.sub (local.get $n) (i64.const 1)) + ) + ) + ) + ) + ) + (func $cbak (param $reserved i32) (result i64) + (local $result i64) + (drop (call $_g (i32.const 1) (i32.const 1))) + (local.set $result (call $func_a (i64.const 5))) + (call $accept (i32.const 0) (i32.const 0) (local.get $result)) + ) + (func $hook (param $reserved i32) (result i64) + (local $result i64) + (drop (call $_g (i32.const 1) (i32.const 1))) + (local.set $result (call $func_a (i64.const 10))) + (call $accept (i32.const 0) (i32.const 0) (local.get $result)) + ) + (export "cbak" (func $cbak)) + (export "hook" (func $hook))) + )[test.hook]"]; + + env(ripple::test::jtx::hook(alice, {{hso(hook)}}, 0), + M("Indirect recursion should fail"), + HSFEE, + ter(temMALFORMED)); + env.close(); + } + + // Test 5: Deep call chain (A -> B -> C -> D) - should pass if WCE is OK + { + /* + #include + extern int32_t _g(uint32_t id, uint32_t maxiter); + extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t + error_code); + extern int64_t hook_pos(void); + + int64_t helper(int64_t n) { return n + hook_pos(); } + + int64_t cbak(uint32_t reserved) { + _g(1, 1); + int64_t result = helper(34); + return accept(0, 0, result); + } + + int64_t hook(uint32_t reserved) { + _g(1, 1); + int64_t result = helper(5); + return accept(0, 0, result); + } + */ + TestHook hook_wasm = wasm[R"[test.hook]( + (module + (type (;0;) (func (param i32) (result i64))) + (type (;1;) (func (result i64))) + (type (;2;) (func (param i32 i32) (result i32))) + (type (;3;) (func (param i32 i32 i64) (result i64))) + (type (;4;) (func (param i64) (result i64))) + (import "env" "hook_pos" (func (;0;) (type 1))) + (import "env" "_g" (func (;1;) (type 2))) + (import "env" "accept" (func (;2;) (type 3))) + (func (;3;) (type 4) (param i64) (result i64) + call 0 + local.get 0 + i64.add) + (func (;4;) (type 0) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 1 + drop + i32.const 0 + i32.const 0 + i64.const 34 + call 3 + call 2) + (func (;5;) (type 0) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 1 + drop + i32.const 0 + i32.const 0 + i64.const 5 + call 3 + call 2) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "cbak" (func 4)) + (export "hook" (func 5))) + )[test.hook]"]; + HASH_WASM(hook); + + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), + M("Deep call chain without recursion"), + HSFEE, + ter(tesSUCCESS)); + env.close(); + EXPECT_HOOK_FEE(hook, 14); + + env(pay(bob, alice, XRP(1)), M("Test helper 5"), fee(XRP(1))); + env.close(); + } + + // Test 6: Helper called multiple times - WCE should accumulate + { + /* + #include + extern int32_t _g(uint32_t id, uint32_t maxiter); + extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t + error_code); + + int64_t expensive_helper() { + int64_t sum = 0; + for (int i = 0; i < 100; ++i) { + _g(2, 301); + sum += i; + } + return sum; + } + + int64_t hook(uint32_t reserved) { + _g(1, 1); + int64_t result = 0; + result += expensive_helper(); + result += expensive_helper(); + result += expensive_helper(); + return accept(0, 0, result); + } + */ + + TestHook hook_wasm = wasm[R"[test.hook]( + (module + (type (;0;) (func (param i32 i32) (result i32))) + (type (;1;) (func (param i32 i32 i64) (result i64))) + (type (;2;) (func (result i64))) + (type (;3;) (func (param i32) (result i64))) + (import "env" "_g" (func (;0;) (type 0))) + (import "env" "accept" (func (;1;) (type 1))) + (func (;2;) (type 2) (result i64) + (local i64) + i64.const 100 + local.set 0 + loop ;; label = @1 + i32.const 2 + i32.const 301 + call 0 + drop + local.get 0 + i64.const 1 + i64.sub + local.tee 0 + i64.eqz + i32.eqz + br_if 0 (;@1;) + end + i64.const 4950) + (func (;3;) (type 3) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 0 + i32.const 0 + call 2 + call 2 + i64.add + call 2 + i64.add + call 1) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "hook" (func 3))) + )[test.hook]"]; + HASH_WASM(hook); + + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), + M("Helper called multiple times"), + HSFEE, + ter(tesSUCCESS)); + env.close(); + EXPECT_HOOK_FEE(hook, 2727); + + env(pay(bob, alice, XRP(1)), M("Test helper 6"), fee(XRP(1))); + env.close(); + } + + // Test 7: WCE overflow through many helpers - should fail + { + /* + #include + extern int32_t _g(uint32_t id, uint32_t maxiter); + extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t + error_code); + + int64_t large_helper(int64_t n) { + int64_t sum = n; + for (int i = 0; i < 10000; ++i) { + _g(2, 10001); + sum += i; + } + return sum; + } + + int64_t cbak(uint32_t reserved) { + _g(1, 1); + int64_t result = 10; + for (int i = 0; i < 10; ++i) { + _g(3, 11); + result += large_helper(10); + } + return accept(0, 0, result); + } + + int64_t hook(uint32_t reserved) { + _g(1, 1); + int64_t result = 0; + for (int i = 0; i < 10; ++i) { + _g(3, 11); + result += large_helper(0); + } + return accept(0, 0, result); + } + + */ + TestHook hook = wasm[R"[test.hook]( + (module + (type (;0;) (func (param i32) (result i64))) + (type (;1;) (func (param i32 i32) (result i32))) + (type (;2;) (func (param i32 i32 i64) (result i64))) + (type (;3;) (func (param i64) (result i64))) + (import "env" "_g" (func (;0;) (type 1))) + (import "env" "accept" (func (;1;) (type 2))) + (func (;2;) (type 0) (param i32) (result i64) + (local i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 10 + local.set 0 + i64.const 10 + local.set 1 + loop ;; label = @1 + i32.const 3 + i32.const 11 + call 0 + drop + i64.const 10 + call 3 + local.get 1 + i64.add + local.set 1 + local.get 0 + i32.const 1 + i32.sub + local.tee 0 + br_if 0 (;@1;) + end + i32.const 0 + i32.const 0 + local.get 1 + call 1) + (func (;3;) (type 3) (param i64) (result i64) + (local i64) + i64.const 10000 + local.set 1 + loop ;; label = @1 + i32.const 2 + i32.const 10001 + call 0 + drop + local.get 1 + i64.const 1 + i64.sub + local.tee 1 + i64.eqz + i32.eqz + br_if 0 (;@1;) + end + local.get 0 + i64.const 49995000 + i64.add) + (func (;4;) (type 0) (param i32) (result i64) + (local i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 10 + local.set 0 + loop ;; label = @1 + i32.const 3 + i32.const 11 + call 0 + drop + i64.const 0 + call 3 + local.get 1 + i64.add + local.set 1 + local.get 0 + i32.const 1 + i32.sub + local.tee 0 + br_if 0 (;@1;) + end + i32.const 0 + i32.const 0 + local.get 1 + call 1) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "cbak" (func 2)) + (export "hook" (func 4))) + )[test.hook]"]; + + env(ripple::test::jtx::hook(alice, {{hso(hook)}}, 0), + M("WCE overflow through helpers"), + HSFEE, + ter(temMALFORMED)); + env.close(); + } + + // Test 8: guard inside guard + { + /* + #include + extern int32_t _g(uint32_t id, uint32_t maxiter); + extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t + error_code); + + int64_t helper(int64_t n) { + int64_t sum = n; + for (int i = 0; i < 100; ++i) { + _g(2, 1000); + sum += i; + } + return sum; + } + + int64_t cbak(uint32_t reserved) { + _g(1, 1); + int64_t result = 10; + for (int i = 0; i < 10; ++i) { + _g(3, 11); + result += helper(10); + } + return accept(0, 0, result); + } + + int64_t hook(uint32_t reserved) { + _g(1, 1); + int64_t result = 0; + for (int i = 0; i < 10; ++i) { + _g(3, 11); + result += helper(0); + } + return accept(0, 0, result); + } + */ + + TestHook hook_wasm = wasm[R"[test.hook]( + (module + (type (;0;) (func (param i32) (result i64))) + (type (;1;) (func (param i32 i32) (result i32))) + (type (;2;) (func (param i32 i32 i64) (result i64))) + (type (;3;) (func (param i64) (result i64))) + (import "env" "_g" (func (;0;) (type 1))) + (import "env" "accept" (func (;1;) (type 2))) + (func (;2;) (type 3) (param i64) (result i64) + (local i64) + i64.const 100 + local.set 1 + loop ;; label = @1 + i32.const 2 + i32.const 1000 + call 0 + drop + local.get 1 + i64.const 1 + i64.sub + local.tee 1 + i64.eqz + i32.eqz + br_if 0 (;@1;) + end + local.get 0 + i64.const 4950 + i64.add) + (func (;3;) (type 0) (param i32) (result i64) + (local i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 10 + local.set 0 + i64.const 10 + local.set 1 + loop ;; label = @1 + i32.const 3 + i32.const 11 + call 0 + drop + i64.const 10 + call 2 + local.get 1 + i64.add + local.set 1 + local.get 0 + i32.const 1 + i32.sub + local.tee 0 + br_if 0 (;@1;) + end + i32.const 0 + i32.const 0 + local.get 1 + call 1) + (func (;4;) (type 0) (param i32) (result i64) + (local i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 10 + local.set 0 + loop ;; label = @1 + i32.const 3 + i32.const 11 + call 0 + drop + i64.const 0 + call 2 + local.get 1 + i64.add + local.set 1 + local.get 0 + i32.const 1 + i32.sub + local.tee 0 + br_if 0 (;@1;) + end + i32.const 0 + i32.const 0 + local.get 1 + call 1) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "cbak" (func 3)) + (export "hook" (func 4))) + )[test.hook]"]; + HASH_WASM(hook); + + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), + M("guard inside guard"), + HSFEE, + ter(tesSUCCESS)); + EXPECT_HOOK_FEE(hook, 9151); + + env(pay(bob, alice, XRP(1)), M("Test helper 8"), fee(XRP(1))); + env.close(); + } + } + void test_emit(FeatureBitset features) { @@ -2582,7 +3406,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -2903,10 +3727,12 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + HASH_WASM(hook); + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set emit"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 342); Json::Value invoke; invoke[jss::TransactionType] = "Invoke"; @@ -3086,7 +3912,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -3119,12 +3945,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set etxn_details"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 88); // invoke the hook env(pay(bob, alice, XRP(1)), M("test etxn_details"), fee(XRP(1))); @@ -3140,7 +3968,7 @@ class SetHook0_test : public beast::unit_test::suite auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -3201,8 +4029,9 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); + HASH_WASM(hook); // install the hook on alice - auto hsobj = hso(hook, overrideFlag); + auto hsobj = hso(hook_wasm, overrideFlag); hsobj[jss::HookOn] = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFF" "FE"; // payment high @@ -3210,6 +4039,7 @@ class SetHook0_test : public beast::unit_test::suite M("set etxn_fee_base"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 77); // invoke the hook env(pay(bob, alice, XRP(1)), M("test etxn_fee_base"), fee(XRP(1))); @@ -3245,7 +4075,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -3284,12 +4114,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set etxn_nonce"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 11644); // invoke the hook env(pay(bob, alice, XRP(1)), M("test etxn_nonce"), fee(XRP(1))); @@ -3309,7 +4141,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -3334,12 +4166,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set etxn_reserve"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 69); // invoke the hook env(pay(bob, alice, XRP(1)), M("test etxn_reserve"), fee(XRP(1))); @@ -3358,7 +4192,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -3375,12 +4209,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set fee_base"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 20); // invoke the hook env(pay(bob, alice, XRP(1)), M("test fee_base"), fee(XRP(1))); @@ -3399,7 +4235,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -3508,11 +4344,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_compare"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 583); env(pay(bob, alice, XRP(1)), M("test float_compare"), fee(XRP(1))); env.close(); @@ -3532,7 +4371,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -3707,11 +4546,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_divide"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 1799); env(pay(bob, alice, XRP(1)), M("test float_divide"), fee(XRP(1))); env.close(); @@ -3731,7 +4573,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -3836,11 +4678,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_int"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 1178); env(pay(bob, alice, XRP(1)), M("test float_int"), fee(XRP(1))); env.close(); @@ -3860,7 +4705,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -3924,11 +4769,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_invert"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 329); env(pay(bob, alice, XRP(1)), M("test float_invert"), fee(XRP(1))); env.close(); @@ -3948,7 +4796,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -4007,11 +4855,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_log"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 388); env(pay(bob, alice, XRP(1)), M("test float_log"), fee(XRP(1))); env.close(); @@ -4031,7 +4882,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -4136,11 +4987,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_mantissa"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 309); env(pay(bob, alice, XRP(1)), M("test float_mantissa"), fee(XRP(1))); env.close(); @@ -4160,7 +5014,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -4291,11 +5145,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_mulratio"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 1683); env(pay(bob, alice, XRP(1)), M("test float_mulratio"), fee(XRP(1))); env.close(); @@ -4315,7 +5172,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -4590,12 +5447,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_multiply"), HSFEE); env.close(); - + EXPECT_HOOK_FEE(hook, 3180); env(pay(bob, alice, XRP(1)), M("test float_multiply"), fee(XRP(1))); env.close(); } @@ -4614,7 +5473,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -4661,11 +5520,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_negate"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 105); env(pay(bob, alice, XRP(1)), M("test float_negate"), fee(XRP(1))); env.close(); @@ -4685,7 +5547,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -4702,11 +5564,14 @@ class SetHook0_test : public beast::unit_test::suite : rollback(0,0,1); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_one"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 20); env(pay(bob, alice, XRP(1)), M("test float_one"), fee(XRP(1))); env.close(); @@ -4726,7 +5591,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -4780,11 +5645,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_root"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 257); env(pay(bob, alice, XRP(1)), M("test float_root"), fee(XRP(1))); env.close(); @@ -4804,7 +5672,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -4853,11 +5721,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_set"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 343); env(pay(bob, alice, XRP(1)), M("test float_set"), fee(XRP(1))); env.close(); @@ -4877,7 +5748,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -4966,11 +5837,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_sign"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 296); env(pay(bob, alice, XRP(1)), M("test float_sign"), fee(XRP(1))); env.close(); @@ -4990,7 +5864,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -5171,11 +6045,14 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_sto"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 920); env(pay(bob, alice, XRP(1)), M("test float_sto"), fee(XRP(1))); env.close(); @@ -5195,7 +6072,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -5313,11 +6190,14 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_sto_set"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 187); env(pay(bob, alice, XRP(1)), M("test float_sto_set"), fee(XRP(1))); env.close(); @@ -5337,7 +6217,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -5493,11 +6373,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set float_sum"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 1735); env(pay(bob, alice, XRP(1)), M("test float_sum"), fee(XRP(1))); env.close(); @@ -5517,7 +6400,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -5544,12 +6427,15 @@ class SetHook0_test : public beast::unit_test::suite accept((uint32_t)acc, 20, 0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set hook_account"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 72); // invoke the hook env(pay(bob, alice, XRP(1)), M("test hook_account"), fee(XRP(1))); @@ -5577,7 +6463,8 @@ class SetHook0_test : public beast::unit_test::suite } // install the same hook bob - env(ripple::test::jtx::hook(bob, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + bob, {{hso(hook_wasm, overrideFlag)}}, 0), M("set hook_account 2"), HSFEE); env.close(); @@ -5639,7 +6526,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -5668,12 +6555,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set hook_again"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 54); env(pay(bob, alice, XRP(1)), M("test hook_again"), fee(XRP(1))); env.close(); @@ -5716,7 +6605,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -5742,12 +6631,15 @@ class SetHook0_test : public beast::unit_test::suite accept((uint32_t)hash, 32, 0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set hook_hash"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 62); // invoke the hook env(pay(bob, alice, XRP(1)), M("test hook_hash"), fee(XRP(1))); @@ -5775,7 +6667,7 @@ class SetHook0_test : public beast::unit_test::suite BEAST_EXPECT(memcmp(hash.data(), retStr.data(), 32) == 0); } - TestHook hook2 = wasm[R"[test.hook]( + TestHook hook2_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -5801,12 +6693,15 @@ class SetHook0_test : public beast::unit_test::suite accept((uint32_t)hash, 32, 0); } )[test.hook]"]; + HASH_WASM(hook2); // install a slightly different hook on bob - env(ripple::test::jtx::hook(bob, {{hso(hook2, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + bob, {{hso(hook2_wasm, overrideFlag)}}, 0), M("set hook_hash 2"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook2, 62); // invoke the hook env(pay(bob, alice, XRP(1)), M("test hook_hash 2"), fee(XRP(1))); @@ -5849,11 +6744,8 @@ class SetHook0_test : public beast::unit_test::suite BEAST_EXPECT(memcmp(hash1.data(), hash2.data(), 32) != 0); // compute the hashes - auto computedHash2 = ripple::sha512Half_s( - ripple::Slice(hook.data(), hook.size())); - - auto computedHash1 = ripple::sha512Half_s( - ripple::Slice(hook2.data(), hook2.size())); + auto computedHash2 = hook_hash; + auto computedHash1 = hook2_hash; // ensure the computed hashes match BEAST_EXPECT(computedHash1 == hash1); @@ -5876,7 +6768,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -5958,6 +6850,7 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; + HASH_WASM(hook); Json::Value jv; jv[jss::Account] = alice.human(); @@ -5966,7 +6859,7 @@ class SetHook0_test : public beast::unit_test::suite jv[jss::Hooks] = Json::Value{Json::arrayValue}; Json::Value iv; - iv[jss::CreateCode] = strHex(hook); + iv[jss::CreateCode] = strHex(hook_wasm); iv[jss::HookOn] = "0000000000000000000000000000000000000000000000000000000000000000"; iv[jss::HookApiVersion] = 0U; @@ -5985,6 +6878,7 @@ class SetHook0_test : public beast::unit_test::suite jv[jss::Hooks][0U][jss::Hook] = iv; env(jv, M("set hook_param"), HSFEE, ter(tesSUCCESS)); env.close(); + EXPECT_HOOK_FEE(hook, 2412); // invoke env(pay(bob, alice, XRP(1)), M("test hook_param"), fee(XRP(1))); @@ -6145,6 +7039,7 @@ class SetHook0_test : public beast::unit_test::suite )[test.hook]"]; HASH_WASM(checker); + HASH_WASM(setter); Json::Value jv; jv[jss::Account] = alice.human(); @@ -6194,6 +7089,8 @@ class SetHook0_test : public beast::unit_test::suite env(jv, M("set hook_param_set"), HSFEE, ter(tesSUCCESS)); env.close(); + EXPECT_HOOK_FEE(checker, 475); + EXPECT_HOOK_FEE(setter, 759); // invoke env(pay(bob, alice, XRP(1)), M("test hook_param_set"), fee(XRP(1))); @@ -6212,7 +7109,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -6224,14 +7121,21 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,hook_pos()); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice in all four spots env(ripple::test::jtx::hook( - alice, {{hso(hook), hso(hook), hso(hook), hso(hook)}}, 0), + alice, + {{hso(hook_wasm), + hso(hook_wasm), + hso(hook_wasm), + hso(hook_wasm)}}, + 0), M("set hook_pos"), HSFEE, ter(tesSUCCESS)); env.close(); + EXPECT_HOOK_FEE(hook, 11); // invoke the hooks env(pay(bob, alice, XRP(1)), M("test hook_pos"), fee(XRP(1))); @@ -6338,6 +7242,7 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; + HASH_WASM(skip); HASH_WASM(pos); // install the hook on alice in one places @@ -6352,6 +7257,8 @@ class SetHook0_test : public beast::unit_test::suite HSFEE, ter(tesSUCCESS)); env.close(); + EXPECT_HOOK_FEE(skip, 263); + EXPECT_HOOK_FEE(pos, 11); // invoke the hooks { @@ -6388,7 +7295,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -6466,12 +7373,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set ledger_keylet"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 415); env(pay(bob, alice, XRP(1)), M("test ledger_keylet"), fee(XRP(1))); env.close(); @@ -6490,7 +7399,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -6515,12 +7424,14 @@ class SetHook0_test : public beast::unit_test::suite accept((uint32_t)hash, 32, 0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set ledger_last_hash"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 59); for (uint32_t i = 0; i < 3; ++i) { @@ -6564,7 +7475,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -6576,12 +7487,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,ledger_last_time()); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set ledger_last_time"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 11); // invoke the hook a few times for (uint32_t i = 0; i < 3; ++i) @@ -6632,7 +7545,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -6659,12 +7572,14 @@ class SetHook0_test : public beast::unit_test::suite accept((uint32_t)nonce, 64, 0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set ledger_nonce"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 74); // invoke the hook auto const seq = @@ -6730,7 +7645,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -6742,12 +7657,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,ledger_seq()); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set ledger_seq"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 11); // invoke the hook a few times for (uint32_t i = 0; i < 3; ++i) @@ -6789,7 +7706,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -6839,12 +7756,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set meta_slot"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 139); env(pay(bob, alice, XRP(1)), M("test meta_slot"), fee(XRP(1))); env.close(); @@ -6883,7 +7802,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -6949,12 +7868,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,2); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set xpop_slot"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 3245); auto checkResult = [this](auto const& meta, uint64_t expectedCode) -> void { @@ -6994,7 +7915,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -7041,12 +7962,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set otxn_field"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 732); // invoke the hook env(pay(alice, bob, XRP(1)), M("test otxn_field"), fee(XRP(1))); @@ -7064,7 +7987,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -7124,12 +8047,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set otxn_id"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 1077); // invoke the hook env(pay(bob, alice, XRP(1)), M("test otxn_id"), fee(XRP(1))); @@ -7147,7 +8072,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -7206,12 +8131,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set otxn_slot"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 6442); // invoke the hook env(pay(bob, alice, XRP(1)), M("test otxn_slot"), fee(XRP(1))); @@ -7229,7 +8156,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -7266,12 +8193,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set otxn_type"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 51); // invoke the hook env(pay(bob, alice, XRP(1)), M("test otxn_type"), fee(XRP(1))); @@ -7300,7 +8229,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -7382,12 +8311,14 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set otxn_param"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 2412); // invoke Json::Value invoke; @@ -7423,7 +8354,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -7513,12 +8444,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set slot"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 232); // invoke the hook env(pay(bob, alice, XRP(1)), M("test slot"), fee(XRP(1))); @@ -7536,7 +8469,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -7571,12 +8504,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set slot_clear"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 83); // invoke the hook env(pay(bob, alice, XRP(1)), M("test slot_clear"), fee(XRP(1))); @@ -7594,7 +8529,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -7636,12 +8571,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set slot_count"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 97); // invoke the hook env(pay(bob, alice, XRP(1)), M("test slot_count"), fee(XRP(1))); @@ -7659,7 +8596,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -7711,12 +8648,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set slot_float"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 112); // invoke the hook env(pay(bob, alice, XRP(1)), M("test slot_float"), fee(XRP(1))); @@ -7734,7 +8673,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -7821,12 +8760,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set slot_set"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 11653); // invoke the hook env(pay(bob, alice, XRP(1)), M("test slot_set"), fee(XRP(1))); @@ -7844,7 +8785,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -7900,12 +8841,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set slot_size"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 114); // invoke the hook env(pay(bob, alice, XRP(1)), M("test slot_size"), fee(XRP(1))); @@ -7924,7 +8867,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -8021,12 +8964,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set slot_subarray"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 6212); // generate an array of memos to attach Json::Value jv; @@ -8064,7 +9009,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -8141,12 +9086,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set slot_subfield"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 6109); // invoke the hook env(pay(bob, alice, XRP(1)), M("test slot_subfield"), fee(XRP(1))); @@ -8167,7 +9114,7 @@ class SetHook0_test : public beast::unit_test::suite // set up a trustline which we can retrieve later env(trust(alice, bob["USD"](600))); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -8280,12 +9227,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set slot_subfield"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 284); // invoke the hook env(pay(bob, alice, XRP(1)), M("test slot_type"), fee(XRP(1))); @@ -8305,7 +9254,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -8364,12 +9313,15 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set state"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 2254); // invoke the hook env(pay(bob, alice, XRP(1)), M("test state"), fee(XRP(1))); @@ -8379,7 +9331,7 @@ class SetHook0_test : public beast::unit_test::suite // override hook with a second version that just reads those state // objects { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -8420,12 +9372,15 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set state 2"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 2134); // invoke the hook env(pay(bob, alice, XRP(1)), M("test state 2"), fee(XRP(1))); @@ -8446,7 +9401,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), bob); { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -8486,12 +9441,15 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set state_foreign"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 72); // invoke the hook env(pay(bob, alice, XRP(1)), M("test state_foreign"), fee(XRP(1))); @@ -8499,7 +9457,7 @@ class SetHook0_test : public beast::unit_test::suite // set a second hook on bob that will read the state objects from alice { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -8576,12 +9534,15 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on bob - env(ripple::test::jtx::hook(bob, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + bob, {{hso(hook_wasm, overrideFlag)}}, 0), M("set state_foreign 2"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 2408); // invoke the hook @@ -8597,7 +9558,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test state_foreign_set max"); using namespace jtx; - static const std::vector ns_maxHook = { + static const std::vector ns_maxHook_wasm = { 0x00U, 0x61U, 0x73U, 0x6dU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x36U, 0x07U, 0x60U, 0x02U, 0x7fU, 0x7fU, 0x01U, 0x7fU, 0x60U, 0x02U, 0x7fU, 0x7fU, 0x01U, 0x7eU, 0x60U, 0x03U, 0x7fU, 0x7fU, @@ -8657,6 +9618,7 @@ class SetHook0_test : public beast::unit_test::suite 0x52U, 0x65U, 0x61U, 0x63U, 0x68U, 0x65U, 0x64U, 0x00U, 0x6bU, 0x65U, 0x79U, 0x32U, 0x00U, 0x63U, 0x6fU, 0x6eU, 0x74U, 0x65U, 0x6eU, 0x74U, 0x32U}; + HASH_WASM(ns_maxHook); Env env{*this, features}; @@ -8667,10 +9629,11 @@ class SetHook0_test : public beast::unit_test::suite // install the hook on alice env(ripple::test::jtx::hook( - alice, {{hso(ns_maxHook, overrideFlag)}}, 0), + alice, {{hso(ns_maxHook_wasm, overrideFlag)}}, 0), M("set state_foreign_set_max"), HSFEE); env.close(); + EXPECT_HOOK_FEE(ns_maxHook, 103); // invoke the hook for (uint32_t i = 0; i < 255; ++i) @@ -8848,6 +9811,7 @@ class SetHook0_test : public beast::unit_test::suite env(json, M("set state_foreign_set"), HSFEE); env.close(); + EXPECT_HOOK_FEE(grantor, 103); } // install the grantee hook on bob @@ -8857,6 +9821,7 @@ class SetHook0_test : public beast::unit_test::suite bob, {{hso(grantee_wasm, overrideFlag)}}, 0); env(json, M("set state_foreign_set 2"), HSFEE); env.close(); + EXPECT_HOOK_FEE(grantee, 234); } auto const aliceid = Account("alice").id(); @@ -9118,6 +10083,7 @@ class SetHook0_test : public beast::unit_test::suite bob, {{hso(exhaustion_wasm, overrideFlag)}}, 0); env(json, M("set state_foreign_set 12"), HSFEE); env.close(); + EXPECT_HOOK_FEE(exhaustion, 10582); } // now invoke repeatedly until exhaustion is reached @@ -9218,7 +10184,7 @@ class SetHook0_test : public beast::unit_test::suite // bounds and buffer size checks { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -9261,12 +10227,15 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set state_set 1"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 143); BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1); @@ -9314,7 +10283,7 @@ class SetHook0_test : public beast::unit_test::suite // first hook will set two state objects with different keys and data on // alice { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -9385,12 +10354,15 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set state_set 1"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 85); BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1); @@ -9476,7 +10448,7 @@ class SetHook0_test : public beast::unit_test::suite // make amother hook to override an existing state and delete an // existing state { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -9531,8 +10503,9 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; + HASH_WASM(hook); - TestHook hook2 = wasm[R"[test.hook]( + TestHook hook2_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -9576,14 +10549,21 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; + HASH_WASM(hook2); + // install the hook on alice env(ripple::test::jtx::hook( alice, - {{{hso(hook, overrideFlag)}, {}, {}, {hso(hook2, 0)}}}, + {{{hso(hook_wasm, overrideFlag)}, + {}, + {}, + {hso(hook2_wasm, 0)}}}, 0), M("set state_set 2"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 82); + EXPECT_HOOK_FEE(hook2, 525); // two hooks + two state objects = 4 BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 4); @@ -9592,7 +10572,7 @@ class SetHook0_test : public beast::unit_test::suite // updated state is also available on his side. caution must be // taken because bob's hooks will execute first if bob's is the // otxn. therefore we will flip to a payment from alice to bob here - TestHook hook3 = wasm[R"[test.hook]( + TestHook hook3_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -9652,12 +10632,15 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; + HASH_WASM(hook3); // install the hook on bob - env(ripple::test::jtx::hook(bob, {{hso(hook3, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + bob, {{hso(hook3_wasm, overrideFlag)}}, 0), M("set state_set 3"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook3, 560); // invoke the hook with cho (rollback after alice's hooks have // executed) @@ -9710,7 +10693,7 @@ class SetHook0_test : public beast::unit_test::suite // create a hook state inside the weak side of an execution, while the // strong side is rolled back { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -9754,15 +10737,17 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice, deleting the other hook env(ripple::test::jtx::hook( alice, - {{{hso(hook, overrideFlag)}, {}, {}, {hso_delete()}}}, + {{{hso(hook_wasm, overrideFlag)}, {}, {}, {hso_delete()}}}, 0), M("set state_set 4"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 52); // invoke from alice to cho, this will cause a rollback, however the // hook state should still be updated because the hook specified @@ -9875,6 +10860,7 @@ class SetHook0_test : public beast::unit_test::suite env(json, M("set state_set 6"), HSFEE); env.close(); + EXPECT_HOOK_FEE(exhaustion, 54114); } // now invoke repeatedly until exhaustion is reached @@ -10027,6 +11013,7 @@ class SetHook0_test : public beast::unit_test::suite to_string(UINT256_BIT[ttACCOUNT_SET]); env(jv, M("Create scaled state hook"), HSFEE, ter(tesSUCCESS)); env.close(); + EXPECT_HOOK_FEE(scaled_state, 227); BEAST_EXPECT((*env.le(gary))[sfOwnerCount] == 1); BEAST_EXPECT(!env.le(gary)->isFieldPresent(sfHookStateCount)); @@ -10077,7 +11064,7 @@ class SetHook0_test : public beast::unit_test::suite // tests for set_state_cache if (extHookStateEnabled) { - TestHook extended_state_reserve_hook = wasm[R"[test.hook]( + TestHook extended_state_reserve_hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -10122,14 +11109,17 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(extended_state_reserve_hook); // install the hook on gary - Json::Value jv = hso(extended_state_reserve_hook, overrideFlag); + Json::Value jv = + hso(extended_state_reserve_hook_wasm, overrideFlag); jv[jss::HookOn] = "fffffffffffffffffffffffffffffffffffffff7ffffffffffffffffff" "bfffff"; // only invoke high env(ripple::test::jtx::hook(hank, {{jv}}, 0), HSFEE); env.close(); + EXPECT_HOOK_FEE(extended_state_reserve_hook, 95); Json::Value jv1 = noop(hank); jv1[sfHookStateScale.fieldName] = 8; @@ -10172,7 +11162,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -10342,19 +11332,22 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set sto_emplace"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 15024); // invoke the hook env(pay(bob, alice, XRP(1)), M("test sto_emplace"), fee(XRP(1))); } { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -10391,6 +11384,7 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,result); } )[test.hook]"]; + HASH_WASM(hook); for (auto f : {features, features - fixHookAPI20251128}) { @@ -10403,10 +11397,11 @@ class SetHook0_test : public beast::unit_test::suite // install the hook on alice env(ripple::test::jtx::hook( - alice, {{hso(hook, overrideFlag)}}, 0), + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set sto_emplace"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 36); // invoke the hook env(pay(bob, alice, XRP(1)), @@ -10444,7 +11439,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -10557,12 +11552,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set sto_erase"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 10021); // invoke the hook env(pay(bob, alice, XRP(1)), M("test sto_erase"), fee(XRP(1))); @@ -10582,7 +11579,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -10632,19 +11629,22 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set sto_subarray"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 95); // invoke the hook env(pay(bob, alice, XRP(1)), M("test sto_subarray"), fee(XRP(1))); } { - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -10675,6 +11675,7 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,result1+result2); } )[test.hook]"]; + HASH_WASM(hook); for (auto isfixHookAPI20251128 : {true, false}) { @@ -10687,10 +11688,11 @@ class SetHook0_test : public beast::unit_test::suite // install the hook on alice env(ripple::test::jtx::hook( - alice, {{hso(hook, overrideFlag)}}, 0), + alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set sto_subarray"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 19); // invoke the hook env(pay(bob, alice, XRP(1)), @@ -10744,7 +11746,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -10804,12 +11806,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set sto_subfield"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 123); // invoke the hook env(pay(bob, alice, XRP(1)), M("test sto_subfield"), fee(XRP(1))); @@ -10828,7 +11832,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -10887,12 +11891,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set sto_validate"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 130); // invoke the hook env(pay(bob, alice, XRP(1)), M("test sto_validate"), fee(XRP(1))); @@ -10911,7 +11917,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -10937,12 +11943,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set trace"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 103); // invoke the hook env(pay(bob, alice, XRP(1)), M("test trace"), fee(XRP(1))); @@ -10961,7 +11969,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -10981,12 +11989,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set trace_float"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 37); // invoke the hook env(pay(bob, alice, XRP(1)), M("test trace_float"), fee(XRP(1))); @@ -11005,7 +12015,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -11025,12 +12035,14 @@ class SetHook0_test : public beast::unit_test::suite return accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set trace_num"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 37); // invoke the hook env(pay(bob, alice, XRP(1)), M("test trace_num"), fee(XRP(1))); @@ -11047,7 +12059,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -11293,12 +12305,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set util_accid"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 3101); // invoke the hook env(pay(bob, alice, XRP(1)), M("test util_accid"), fee(XRP(1))); @@ -11317,7 +12331,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -11881,12 +12895,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set util_keylet"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 1546); // invoke the hook env(pay(bob, alice, XRP(1)), M("test util_keylet"), fee(XRP(1))); @@ -11904,7 +12920,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -12334,12 +13350,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set util_raddr"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 4279); // invoke the hook env(pay(bob, alice, XRP(1)), M("test util_raddr"), fee(XRP(1))); @@ -12357,7 +13375,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -12707,12 +13725,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set util_sha512h"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 2875); // invoke the hook env(pay(bob, alice, XRP(1)), M("test util_sha512h"), fee(XRP(1))); @@ -12730,7 +13750,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) @@ -12821,12 +13841,14 @@ class SetHook0_test : public beast::unit_test::suite accept(0,0,0); } )[test.hook]"]; + HASH_WASM(hook); // install the hook on alice - env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + env(ripple::test::jtx::hook(alice, {{hso(hook_wasm, overrideFlag)}}, 0), M("set util_verify"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 230); // invoke the hook env(pay(bob, alice, XRP(1)), M("test util_verify"), fee(XRP(1))); @@ -12851,7 +13873,7 @@ class SetHook0_test : public beast::unit_test::suite env.fund(XRP(10000), hookacc); env.close(); - TestHook hook = wasm[R"[test.hook]( + TestHook hook_wasm = wasm[R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); @@ -13180,6 +14202,7 @@ class SetHook0_test : public beast::unit_test::suite } } )[test.hook]"]; + HASH_WASM(hook); bool const hasFeature = env.current()->rules().enabled(featureHookCanEmit); @@ -13215,15 +14238,16 @@ class SetHook0_test : public beast::unit_test::suite if (i == 1) { - Json::Value h = hso(hook, overrideFlag); + Json::Value h = hso(hook_wasm, overrideFlag); env(ripple::test::jtx::hook(hookacc, {{h}}, 0), M("set hookcanemit"), HSFEE); env.close(); + EXPECT_HOOK_FEE(hook, 755); } else if (i == 2) { - Json::Value h = hso(hook, overrideFlag); + Json::Value h = hso(hook_wasm, overrideFlag); env(ripple::test::jtx::hook(acc, {{h}}, 0), M("set hookcanemit"), HSFEE); @@ -13231,7 +14255,7 @@ class SetHook0_test : public beast::unit_test::suite } { - Json::Value h = hso(hook, overrideFlag); + Json::Value h = hso(hook_wasm, overrideFlag); env(ripple::test::jtx::hook(acc, {{h}}, 0), M("set hookcanemit"), HSFEE); @@ -13263,7 +14287,7 @@ class SetHook0_test : public beast::unit_test::suite { // same result with no-HookCanEmit - Json::Value h = hso(hook, overrideFlag); + Json::Value h = hso(hook_wasm, overrideFlag); h[jss::HookCanEmit] = "0000000000000000000000000000000000000000000000000000000000" "400000"; @@ -13302,7 +14326,7 @@ class SetHook0_test : public beast::unit_test::suite { // install the hook on acc - Json::Value hookCanEmitHook = hso(hook, overrideFlag); + Json::Value hookCanEmitHook = hso(hook_wasm, overrideFlag); hookCanEmitHook[jss::HookCanEmit] = "00000000000000000000000000000000000000000000000000" "00000000000000"; @@ -13341,7 +14365,7 @@ class SetHook0_test : public beast::unit_test::suite { // install the hook on acc - Json::Value hookCanEmitHook = hso(hook, overrideFlag); + Json::Value hookCanEmitHook = hso(hook_wasm, overrideFlag); hookCanEmitHook[jss::HookCanEmit] = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFF"; @@ -13407,6 +14431,7 @@ class SetHook0_test : public beast::unit_test::suite test_rollback(features); testGuards(features); + testHelperFunctions(features); test_emit(features); // // test_etxn_burden(features); // tested above diff --git a/src/test/app/SetHook_wasm.h b/src/test/app/SetHook_wasm.h index 73294c9fb0..9c0561f01c 100644 --- a/src/test/app/SetHook_wasm.h +++ b/src/test/app/SetHook_wasm.h @@ -543,6 +543,649 @@ std::map> wasm = { }}, /* ==== WASM: 6 ==== */ + {R"[test.hook]( + (module + (type (;0;) (func (param i32) (result i64))) + (type (;1;) (func (result i64))) + (type (;2;) (func (param i32 i32) (result i32))) + (type (;3;) (func (param i32 i32 i64) (result i64))) + (type (;4;) (func (param i64) (result i64))) + (import "env" "hook_pos" (func (;0;) (type 1))) + (import "env" "_g" (func (;1;) (type 2))) + (import "env" "accept" (func (;2;) (type 3))) + (func (;3;) (type 4) (param i64) (result i64) + call 0 + local.get 0 + i64.add) + (func (;4;) (type 0) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 1 + drop + i32.const 0 + i32.const 0 + i64.const 34 + call 3 + call 2) + (func (;5;) (type 0) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 1 + drop + i32.const 0 + i32.const 0 + i64.const 5 + call 3 + call 2) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "cbak" (func 4)) + (export "hook" (func 5))) + )[test.hook]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x1CU, + 0x05U, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x00U, 0x01U, 0x7EU, + 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU, 0x7FU, + 0x7EU, 0x01U, 0x7EU, 0x60U, 0x01U, 0x7EU, 0x01U, 0x7EU, 0x02U, 0x26U, + 0x03U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x08U, 0x68U, 0x6FU, 0x6FU, 0x6BU, + 0x5FU, 0x70U, 0x6FU, 0x73U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, + 0x02U, 0x5FU, 0x67U, 0x00U, 0x02U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, + 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x03U, 0x03U, 0x04U, + 0x03U, 0x04U, 0x00U, 0x00U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x07U, + 0x18U, 0x03U, 0x06U, 0x6DU, 0x65U, 0x6DU, 0x6FU, 0x72U, 0x79U, 0x02U, + 0x00U, 0x04U, 0x63U, 0x62U, 0x61U, 0x6BU, 0x00U, 0x04U, 0x04U, 0x68U, + 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x05U, 0x0AU, 0x31U, 0x03U, 0x07U, 0x00U, + 0x10U, 0x00U, 0x20U, 0x00U, 0x7CU, 0x0BU, 0x13U, 0x00U, 0x41U, 0x01U, + 0x41U, 0x01U, 0x10U, 0x01U, 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, + 0x22U, 0x10U, 0x03U, 0x10U, 0x02U, 0x0BU, 0x13U, 0x00U, 0x41U, 0x01U, + 0x41U, 0x01U, 0x10U, 0x01U, 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, + 0x05U, 0x10U, 0x03U, 0x10U, 0x02U, 0x0BU, + }}, + + /* ==== WASM: 7 ==== */ + {R"[test.hook]( + (module + (type (;0;) (func (param i32) (result i64))) + (type (;1;) (func (param i32 i32) (result i32))) + (type (;2;) (func (param i32 i32 i64) (result i64))) + (type (;3;) (func (param i64) (result i64))) + (import "env" "_g" (func (;0;) (type 1))) + (import "env" "accept" (func (;1;) (type 2))) + (func (;2;) (type 0) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 0 + i32.const 0 + i64.const 3 + call 3 + call 1) + (func (;3;) (type 3) (param i64) (result i64) + i32.const 2 + i32.const 4 + call 0 + drop + i32.const 2 + i32.const 4 + call 0 + drop + i32.const 2 + i32.const 4 + call 0 + drop + local.get 0 + i64.const 3 + i64.mul) + (func (;4;) (type 0) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 0 + i32.const 0 + i64.const 2 + call 3 + call 1) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "hook" (func 2)) + (export "cbak" (func 4))) + )[test.hook]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x18U, + 0x04U, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x02U, 0x7FU, 0x7FU, + 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, + 0x01U, 0x7EU, 0x01U, 0x7EU, 0x02U, 0x17U, 0x02U, 0x03U, 0x65U, 0x6EU, + 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, + 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U, 0x03U, + 0x04U, 0x03U, 0x00U, 0x03U, 0x00U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, + 0x07U, 0x18U, 0x03U, 0x06U, 0x6DU, 0x65U, 0x6DU, 0x6FU, 0x72U, 0x79U, + 0x02U, 0x00U, 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x02U, 0x04U, + 0x63U, 0x62U, 0x61U, 0x6BU, 0x00U, 0x04U, 0x0AU, 0x46U, 0x03U, 0x13U, + 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x00U, 0x1AU, 0x41U, 0x00U, + 0x41U, 0x00U, 0x42U, 0x03U, 0x10U, 0x03U, 0x10U, 0x01U, 0x0BU, 0x1CU, + 0x00U, 0x41U, 0x02U, 0x41U, 0x04U, 0x10U, 0x00U, 0x1AU, 0x41U, 0x02U, + 0x41U, 0x04U, 0x10U, 0x00U, 0x1AU, 0x41U, 0x02U, 0x41U, 0x04U, 0x10U, + 0x00U, 0x1AU, 0x20U, 0x00U, 0x42U, 0x03U, 0x7EU, 0x0BU, 0x13U, 0x00U, + 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x00U, 0x1AU, 0x41U, 0x00U, 0x41U, + 0x00U, 0x42U, 0x02U, 0x10U, 0x03U, 0x10U, 0x01U, 0x0BU, + }}, + + /* ==== WASM: 8 ==== */ + {R"[test.hook]( + (module + (type (;0;) (func (param i32) (result i64))) + (type (;1;) (func (param i32 i32) (result i32))) + (type (;2;) (func (param i32 i32 i64) (result i64))) + (type (;3;) (func (result i64))) + (type (;4;) (func (param i64) (result i64))) + (import "env" "_g" (func $g (type 1))) + (import "env" "accept" (func $accept (type 2))) + (import "env" "hook_pos" (func $hook_pos (type 3))) + (func $recursive_func (type 4) (param $n i64) (result i64) + (if (result i64) + (i64.le_s (local.get $n) (i64.const 0)) + (then + (i64.const 0) + ) + (else + (i64.add + (local.get $n) + (call $recursive_func + (i64.sub (local.get $n) (call $hook_pos)) + ) + ) + ) + ) + ) + (func (;3;) (type 0) (param i32) (result i64) ;; cbak + i32.const 1 + i32.const 1 + call $g + drop + i32.const 0 + i32.const 0 + i64.const 5 + call $recursive_func + call $accept + ) + (func (;5;) (type 0) (param i32) (result i64) ;; hook + i32.const 1 + i32.const 1 + call $g + drop + i32.const 0 + i32.const 0 + i64.const 10 + call $recursive_func + call $accept + ) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "cbak" (func 3)) + (export "hook" (func 5))) + )[test.hook]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x1CU, + 0x05U, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x02U, 0x7FU, 0x7FU, + 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, + 0x00U, 0x01U, 0x7EU, 0x60U, 0x01U, 0x7EU, 0x01U, 0x7EU, 0x02U, 0x26U, + 0x03U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x01U, + 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, + 0x74U, 0x00U, 0x02U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x08U, 0x68U, 0x6FU, + 0x6FU, 0x6BU, 0x5FU, 0x70U, 0x6FU, 0x73U, 0x00U, 0x03U, 0x03U, 0x04U, + 0x03U, 0x04U, 0x00U, 0x00U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x07U, + 0x18U, 0x03U, 0x06U, 0x6DU, 0x65U, 0x6DU, 0x6FU, 0x72U, 0x79U, 0x02U, + 0x00U, 0x04U, 0x63U, 0x62U, 0x61U, 0x6BU, 0x00U, 0x03U, 0x04U, 0x68U, + 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x05U, 0x0AU, 0x41U, 0x03U, 0x17U, 0x00U, + 0x20U, 0x00U, 0x42U, 0x00U, 0x57U, 0x04U, 0x7EU, 0x42U, 0x00U, 0x05U, + 0x20U, 0x00U, 0x20U, 0x00U, 0x10U, 0x02U, 0x7DU, 0x10U, 0x03U, 0x7CU, + 0x0BU, 0x0BU, 0x13U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x00U, + 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x05U, 0x10U, 0x03U, 0x10U, + 0x01U, 0x0BU, 0x13U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x00U, + 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x0AU, 0x10U, 0x03U, 0x10U, + 0x01U, 0x0BU, + }}, + + /* ==== WASM: 9 ==== */ + {R"[test.hook]( + (module + (import "env" "_g" (func $_g (param i32 i32) (result i32))) + (import "env" "accept" (func $accept (param i32 i32 i64) (result i64))) + (type $func_type (func (param i64) (result i64))) + (func $func_b (param $n i64) (result i64) + (if (result i64) + (i64.le_s (local.get $n) (i64.const 0)) + (then + (i64.const 0) + ) + (else + (i64.add + (local.get $n) + (call $func_a + (i64.sub (local.get $n) (i64.const 1)) + ) + ) + ) + ) + ) + (func $func_a (param $n i64) (result i64) + (if (result i64) + (i64.le_s (local.get $n) (i64.const 0)) + (then + (i64.const 0) + ) + (else + (i64.add + (local.get $n) + (call $func_b + (i64.sub (local.get $n) (i64.const 1)) + ) + ) + ) + ) + ) + (func $cbak (param $reserved i32) (result i64) + (local $result i64) + (drop (call $_g (i32.const 1) (i32.const 1))) + (local.set $result (call $func_a (i64.const 5))) + (call $accept (i32.const 0) (i32.const 0) (local.get $result)) + ) + (func $hook (param $reserved i32) (result i64) + (local $result i64) + (drop (call $_g (i32.const 1) (i32.const 1))) + (local.set $result (call $func_a (i64.const 10))) + (call $accept (i32.const 0) (i32.const 0) (local.get $result)) + ) + (export "cbak" (func $cbak)) + (export "hook" (func $hook))) + )[test.hook]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x18U, + 0x04U, 0x60U, 0x01U, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x02U, 0x7FU, 0x7FU, + 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, + 0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, 0x17U, 0x02U, 0x03U, 0x65U, 0x6EU, + 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, + 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U, 0x03U, + 0x05U, 0x04U, 0x00U, 0x00U, 0x03U, 0x03U, 0x07U, 0x0FU, 0x02U, 0x04U, + 0x63U, 0x62U, 0x61U, 0x6BU, 0x00U, 0x04U, 0x04U, 0x68U, 0x6FU, 0x6FU, + 0x6BU, 0x00U, 0x05U, 0x0AU, 0x65U, 0x04U, 0x17U, 0x00U, 0x20U, 0x00U, + 0x42U, 0x00U, 0x57U, 0x04U, 0x7EU, 0x42U, 0x00U, 0x05U, 0x20U, 0x00U, + 0x20U, 0x00U, 0x42U, 0x01U, 0x7DU, 0x10U, 0x03U, 0x7CU, 0x0BU, 0x0BU, + 0x17U, 0x00U, 0x20U, 0x00U, 0x42U, 0x00U, 0x57U, 0x04U, 0x7EU, 0x42U, + 0x00U, 0x05U, 0x20U, 0x00U, 0x20U, 0x00U, 0x42U, 0x01U, 0x7DU, 0x10U, + 0x02U, 0x7CU, 0x0BU, 0x0BU, 0x19U, 0x01U, 0x01U, 0x7EU, 0x41U, 0x01U, + 0x41U, 0x01U, 0x10U, 0x00U, 0x1AU, 0x42U, 0x05U, 0x10U, 0x03U, 0x21U, + 0x01U, 0x41U, 0x00U, 0x41U, 0x00U, 0x20U, 0x01U, 0x10U, 0x01U, 0x0BU, + 0x19U, 0x01U, 0x01U, 0x7EU, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x00U, + 0x1AU, 0x42U, 0x0AU, 0x10U, 0x03U, 0x21U, 0x01U, 0x41U, 0x00U, 0x41U, + 0x00U, 0x20U, 0x01U, 0x10U, 0x01U, 0x0BU, + }}, + + /* ==== WASM: 10 ==== */ + {R"[test.hook]( + (module + (type (;0;) (func (param i32) (result i64))) + (type (;1;) (func (result i64))) + (type (;2;) (func (param i32 i32) (result i32))) + (type (;3;) (func (param i32 i32 i64) (result i64))) + (type (;4;) (func (param i64) (result i64))) + (import "env" "hook_pos" (func (;0;) (type 1))) + (import "env" "_g" (func (;1;) (type 2))) + (import "env" "accept" (func (;2;) (type 3))) + (func (;3;) (type 4) (param i64) (result i64) + call 0 + local.get 0 + i64.add) + (func (;4;) (type 0) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 1 + drop + i32.const 0 + i32.const 0 + i64.const 34 + call 3 + call 2) + (func (;5;) (type 0) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 1 + drop + i32.const 0 + i32.const 0 + i64.const 5 + call 3 + call 2) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "cbak" (func 4)) + (export "hook" (func 5))) + )[test.hook]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x1CU, + 0x05U, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x00U, 0x01U, 0x7EU, + 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU, 0x7FU, + 0x7EU, 0x01U, 0x7EU, 0x60U, 0x01U, 0x7EU, 0x01U, 0x7EU, 0x02U, 0x26U, + 0x03U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x08U, 0x68U, 0x6FU, 0x6FU, 0x6BU, + 0x5FU, 0x70U, 0x6FU, 0x73U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, + 0x02U, 0x5FU, 0x67U, 0x00U, 0x02U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, + 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x03U, 0x03U, 0x04U, + 0x03U, 0x04U, 0x00U, 0x00U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x07U, + 0x18U, 0x03U, 0x06U, 0x6DU, 0x65U, 0x6DU, 0x6FU, 0x72U, 0x79U, 0x02U, + 0x00U, 0x04U, 0x63U, 0x62U, 0x61U, 0x6BU, 0x00U, 0x04U, 0x04U, 0x68U, + 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x05U, 0x0AU, 0x31U, 0x03U, 0x07U, 0x00U, + 0x10U, 0x00U, 0x20U, 0x00U, 0x7CU, 0x0BU, 0x13U, 0x00U, 0x41U, 0x01U, + 0x41U, 0x01U, 0x10U, 0x01U, 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, + 0x22U, 0x10U, 0x03U, 0x10U, 0x02U, 0x0BU, 0x13U, 0x00U, 0x41U, 0x01U, + 0x41U, 0x01U, 0x10U, 0x01U, 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, + 0x05U, 0x10U, 0x03U, 0x10U, 0x02U, 0x0BU, + }}, + + /* ==== WASM: 11 ==== */ + {R"[test.hook]( + (module + (type (;0;) (func (param i32 i32) (result i32))) + (type (;1;) (func (param i32 i32 i64) (result i64))) + (type (;2;) (func (result i64))) + (type (;3;) (func (param i32) (result i64))) + (import "env" "_g" (func (;0;) (type 0))) + (import "env" "accept" (func (;1;) (type 1))) + (func (;2;) (type 2) (result i64) + (local i64) + i64.const 100 + local.set 0 + loop ;; label = @1 + i32.const 2 + i32.const 301 + call 0 + drop + local.get 0 + i64.const 1 + i64.sub + local.tee 0 + i64.eqz + i32.eqz + br_if 0 (;@1;) + end + i64.const 4950) + (func (;3;) (type 3) (param i32) (result i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 0 + i32.const 0 + call 2 + call 2 + i64.add + call 2 + i64.add + call 1) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "hook" (func 3))) + )[test.hook]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x17U, + 0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU, + 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x00U, 0x01U, 0x7EU, 0x60U, 0x01U, + 0x7FU, 0x01U, 0x7EU, 0x02U, 0x17U, 0x02U, 0x03U, 0x65U, 0x6EU, 0x76U, + 0x02U, 0x5FU, 0x67U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, + 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x01U, 0x03U, 0x03U, + 0x02U, 0x02U, 0x03U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x07U, 0x11U, + 0x02U, 0x06U, 0x6DU, 0x65U, 0x6DU, 0x6FU, 0x72U, 0x79U, 0x02U, 0x00U, + 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x03U, 0x0AU, 0x3CU, 0x02U, + 0x22U, 0x01U, 0x01U, 0x7EU, 0x42U, 0xE4U, 0x00U, 0x21U, 0x00U, 0x03U, + 0x40U, 0x41U, 0x02U, 0x41U, 0xADU, 0x02U, 0x10U, 0x00U, 0x1AU, 0x20U, + 0x00U, 0x42U, 0x01U, 0x7DU, 0x22U, 0x00U, 0x50U, 0x45U, 0x0DU, 0x00U, + 0x0BU, 0x42U, 0xD6U, 0x26U, 0x0BU, 0x17U, 0x00U, 0x41U, 0x01U, 0x41U, + 0x01U, 0x10U, 0x00U, 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x10U, 0x02U, + 0x10U, 0x02U, 0x7CU, 0x10U, 0x02U, 0x7CU, 0x10U, 0x01U, 0x0BU, + }}, + + /* ==== WASM: 12 ==== */ + {R"[test.hook]( + (module + (type (;0;) (func (param i32) (result i64))) + (type (;1;) (func (param i32 i32) (result i32))) + (type (;2;) (func (param i32 i32 i64) (result i64))) + (type (;3;) (func (param i64) (result i64))) + (import "env" "_g" (func (;0;) (type 1))) + (import "env" "accept" (func (;1;) (type 2))) + (func (;2;) (type 0) (param i32) (result i64) + (local i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 10 + local.set 0 + i64.const 10 + local.set 1 + loop ;; label = @1 + i32.const 3 + i32.const 11 + call 0 + drop + i64.const 10 + call 3 + local.get 1 + i64.add + local.set 1 + local.get 0 + i32.const 1 + i32.sub + local.tee 0 + br_if 0 (;@1;) + end + i32.const 0 + i32.const 0 + local.get 1 + call 1) + (func (;3;) (type 3) (param i64) (result i64) + (local i64) + i64.const 10000 + local.set 1 + loop ;; label = @1 + i32.const 2 + i32.const 10001 + call 0 + drop + local.get 1 + i64.const 1 + i64.sub + local.tee 1 + i64.eqz + i32.eqz + br_if 0 (;@1;) + end + local.get 0 + i64.const 49995000 + i64.add) + (func (;4;) (type 0) (param i32) (result i64) + (local i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 10 + local.set 0 + loop ;; label = @1 + i32.const 3 + i32.const 11 + call 0 + drop + i64.const 0 + call 3 + local.get 1 + i64.add + local.set 1 + local.get 0 + i32.const 1 + i32.sub + local.tee 0 + br_if 0 (;@1;) + end + i32.const 0 + i32.const 0 + local.get 1 + call 1) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "cbak" (func 2)) + (export "hook" (func 4))) + )[test.hook]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x18U, + 0x04U, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x02U, 0x7FU, 0x7FU, + 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, + 0x01U, 0x7EU, 0x01U, 0x7EU, 0x02U, 0x17U, 0x02U, 0x03U, 0x65U, 0x6EU, + 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, + 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U, 0x03U, + 0x04U, 0x03U, 0x00U, 0x03U, 0x00U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, + 0x07U, 0x18U, 0x03U, 0x06U, 0x6DU, 0x65U, 0x6DU, 0x6FU, 0x72U, 0x79U, + 0x02U, 0x00U, 0x04U, 0x63U, 0x62U, 0x61U, 0x6BU, 0x00U, 0x02U, 0x04U, + 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x04U, 0x0AU, 0x97U, 0x01U, 0x03U, + 0x37U, 0x01U, 0x01U, 0x7EU, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x00U, + 0x1AU, 0x41U, 0x0AU, 0x21U, 0x00U, 0x42U, 0x0AU, 0x21U, 0x01U, 0x03U, + 0x40U, 0x41U, 0x03U, 0x41U, 0x0BU, 0x10U, 0x00U, 0x1AU, 0x42U, 0x0AU, + 0x10U, 0x03U, 0x20U, 0x01U, 0x7CU, 0x21U, 0x01U, 0x20U, 0x00U, 0x41U, + 0x01U, 0x6BU, 0x22U, 0x00U, 0x0DU, 0x00U, 0x0BU, 0x41U, 0x00U, 0x41U, + 0x00U, 0x20U, 0x01U, 0x10U, 0x01U, 0x0BU, 0x29U, 0x01U, 0x01U, 0x7EU, + 0x42U, 0x90U, 0xCEU, 0x00U, 0x21U, 0x01U, 0x03U, 0x40U, 0x41U, 0x02U, + 0x41U, 0x91U, 0xCEU, 0x00U, 0x10U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x42U, + 0x01U, 0x7DU, 0x22U, 0x01U, 0x50U, 0x45U, 0x0DU, 0x00U, 0x0BU, 0x20U, + 0x00U, 0x42U, 0xF8U, 0xB9U, 0xEBU, 0x17U, 0x7CU, 0x0BU, 0x33U, 0x01U, + 0x01U, 0x7EU, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x00U, 0x1AU, 0x41U, + 0x0AU, 0x21U, 0x00U, 0x03U, 0x40U, 0x41U, 0x03U, 0x41U, 0x0BU, 0x10U, + 0x00U, 0x1AU, 0x42U, 0x00U, 0x10U, 0x03U, 0x20U, 0x01U, 0x7CU, 0x21U, + 0x01U, 0x20U, 0x00U, 0x41U, 0x01U, 0x6BU, 0x22U, 0x00U, 0x0DU, 0x00U, + 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x20U, 0x01U, 0x10U, 0x01U, 0x0BU, + }}, + + /* ==== WASM: 13 ==== */ + {R"[test.hook]( + (module + (type (;0;) (func (param i32) (result i64))) + (type (;1;) (func (param i32 i32) (result i32))) + (type (;2;) (func (param i32 i32 i64) (result i64))) + (type (;3;) (func (param i64) (result i64))) + (import "env" "_g" (func (;0;) (type 1))) + (import "env" "accept" (func (;1;) (type 2))) + (func (;2;) (type 3) (param i64) (result i64) + (local i64) + i64.const 100 + local.set 1 + loop ;; label = @1 + i32.const 2 + i32.const 1000 + call 0 + drop + local.get 1 + i64.const 1 + i64.sub + local.tee 1 + i64.eqz + i32.eqz + br_if 0 (;@1;) + end + local.get 0 + i64.const 4950 + i64.add) + (func (;3;) (type 0) (param i32) (result i64) + (local i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 10 + local.set 0 + i64.const 10 + local.set 1 + loop ;; label = @1 + i32.const 3 + i32.const 11 + call 0 + drop + i64.const 10 + call 2 + local.get 1 + i64.add + local.set 1 + local.get 0 + i32.const 1 + i32.sub + local.tee 0 + br_if 0 (;@1;) + end + i32.const 0 + i32.const 0 + local.get 1 + call 1) + (func (;4;) (type 0) (param i32) (result i64) + (local i64) + i32.const 1 + i32.const 1 + call 0 + drop + i32.const 10 + local.set 0 + loop ;; label = @1 + i32.const 3 + i32.const 11 + call 0 + drop + i64.const 0 + call 2 + local.get 1 + i64.add + local.set 1 + local.get 0 + i32.const 1 + i32.sub + local.tee 0 + br_if 0 (;@1;) + end + i32.const 0 + i32.const 0 + local.get 1 + call 1) + (memory (;0;) 2) + (export "memory" (memory 0)) + (export "cbak" (func 3)) + (export "hook" (func 4))) + )[test.hook]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x18U, + 0x04U, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x02U, 0x7FU, 0x7FU, + 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, + 0x01U, 0x7EU, 0x01U, 0x7EU, 0x02U, 0x17U, 0x02U, 0x03U, 0x65U, 0x6EU, + 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, + 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U, 0x03U, + 0x04U, 0x03U, 0x03U, 0x00U, 0x00U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, + 0x07U, 0x18U, 0x03U, 0x06U, 0x6DU, 0x65U, 0x6DU, 0x6FU, 0x72U, 0x79U, + 0x02U, 0x00U, 0x04U, 0x63U, 0x62U, 0x61U, 0x6BU, 0x00U, 0x03U, 0x04U, + 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x04U, 0x0AU, 0x93U, 0x01U, 0x03U, + 0x25U, 0x01U, 0x01U, 0x7EU, 0x42U, 0xE4U, 0x00U, 0x21U, 0x01U, 0x03U, + 0x40U, 0x41U, 0x02U, 0x41U, 0xE8U, 0x07U, 0x10U, 0x00U, 0x1AU, 0x20U, + 0x01U, 0x42U, 0x01U, 0x7DU, 0x22U, 0x01U, 0x50U, 0x45U, 0x0DU, 0x00U, + 0x0BU, 0x20U, 0x00U, 0x42U, 0xD6U, 0x26U, 0x7CU, 0x0BU, 0x37U, 0x01U, + 0x01U, 0x7EU, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x00U, 0x1AU, 0x41U, + 0x0AU, 0x21U, 0x00U, 0x42U, 0x0AU, 0x21U, 0x01U, 0x03U, 0x40U, 0x41U, + 0x03U, 0x41U, 0x0BU, 0x10U, 0x00U, 0x1AU, 0x42U, 0x0AU, 0x10U, 0x02U, + 0x20U, 0x01U, 0x7CU, 0x21U, 0x01U, 0x20U, 0x00U, 0x41U, 0x01U, 0x6BU, + 0x22U, 0x00U, 0x0DU, 0x00U, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x20U, + 0x01U, 0x10U, 0x01U, 0x0BU, 0x33U, 0x01U, 0x01U, 0x7EU, 0x41U, 0x01U, + 0x41U, 0x01U, 0x10U, 0x00U, 0x1AU, 0x41U, 0x0AU, 0x21U, 0x00U, 0x03U, + 0x40U, 0x41U, 0x03U, 0x41U, 0x0BU, 0x10U, 0x00U, 0x1AU, 0x42U, 0x00U, + 0x10U, 0x02U, 0x20U, 0x01U, 0x7CU, 0x21U, 0x01U, 0x20U, 0x00U, 0x41U, + 0x01U, 0x6BU, 0x22U, 0x00U, 0x0DU, 0x00U, 0x0BU, 0x41U, 0x00U, 0x41U, + 0x00U, 0x20U, 0x01U, 0x10U, 0x01U, 0x0BU, + }}, + + /* ==== WASM: 14 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); @@ -1159,7 +1802,7 @@ std::map> wasm = { 0x78U, 0x29U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 7 ==== */ + /* ==== WASM: 15 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -1264,7 +1907,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 8 ==== */ + /* ==== WASM: 16 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -1386,7 +2029,7 @@ std::map> wasm = { 0x58U, 0x4EU, 0x00U, }}, - /* ==== WASM: 9 ==== */ + /* ==== WASM: 17 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -1509,7 +2152,7 @@ std::map> wasm = { 0x4EU, 0x59U, 0x5FU, 0x4EU, 0x4FU, 0x4EU, 0x43U, 0x45U, 0x53U, 0x00U, }}, - /* ==== WASM: 10 ==== */ + /* ==== WASM: 18 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -1589,7 +2232,7 @@ std::map> wasm = { 0x54U, 0x00U, }}, - /* ==== WASM: 11 ==== */ + /* ==== WASM: 19 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -1634,7 +2277,7 @@ std::map> wasm = { 0x30U, 0x00U, }}, - /* ==== WASM: 12 ==== */ + /* ==== WASM: 20 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -1953,7 +2596,7 @@ std::map> wasm = { 0x80U, 0x80U, 0x80U, 0x00U, 0x0BU, }}, - /* ==== WASM: 13 ==== */ + /* ==== WASM: 21 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -2739,7 +3382,7 @@ std::map> wasm = { 0x37U, 0x36U, 0x33U, 0x4CU, 0x4CU, 0x20U, 0x29U, 0x00U, }}, - /* ==== WASM: 14 ==== */ + /* ==== WASM: 22 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -3129,7 +3772,7 @@ std::map> wasm = { 0x80U, 0x80U, 0x80U, 0x00U, 0x0BU, }}, - /* ==== WASM: 15 ==== */ + /* ==== WASM: 23 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -3310,7 +3953,7 @@ std::map> wasm = { 0x38U, 0x4CU, 0x4CU, 0x29U, 0x00U, }}, - /* ==== WASM: 16 ==== */ + /* ==== WASM: 24 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -3499,7 +4142,7 @@ std::map> wasm = { 0x29U, 0x00U, }}, - /* ==== WASM: 17 ==== */ + /* ==== WASM: 25 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -3738,7 +4381,7 @@ std::map> wasm = { 0x00U, 0x42U, 0x00U, 0x10U, 0x85U, 0x80U, 0x80U, 0x80U, 0x00U, 0x0BU, }}, - /* ==== WASM: 18 ==== */ + /* ==== WASM: 26 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -4440,7 +5083,7 @@ std::map> wasm = { 0x38U, 0x35U, 0x35U, 0x32U, 0x55U, 0x29U, 0x00U, }}, - /* ==== WASM: 19 ==== */ + /* ==== WASM: 27 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -5785,7 +6428,7 @@ std::map> wasm = { 0x20U, 0x29U, 0x00U, }}, - /* ==== WASM: 20 ==== */ + /* ==== WASM: 28 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -5887,7 +6530,7 @@ std::map> wasm = { 0x84U, 0x80U, 0x80U, 0x80U, 0x00U, 0x0BU, }}, - /* ==== WASM: 21 ==== */ + /* ==== WASM: 29 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -5930,7 +6573,7 @@ std::map> wasm = { 0x00U, 0x0BU, }}, - /* ==== WASM: 22 ==== */ + /* ==== WASM: 30 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -6078,7 +6721,7 @@ std::map> wasm = { 0x34U, 0x34U, 0x4CU, 0x4CU, 0x2CU, 0x20U, 0x33U, 0x29U, 0x00U, }}, - /* ==== WASM: 23 ==== */ + /* ==== WASM: 31 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -6406,7 +7049,7 @@ std::map> wasm = { 0x38U, 0x34U, 0x39U, 0x30U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 24 ==== */ + /* ==== WASM: 32 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -6611,7 +7254,7 @@ std::map> wasm = { 0x10U, 0x85U, 0x80U, 0x80U, 0x80U, 0x00U, 0x0BU, }}, - /* ==== WASM: 25 ==== */ + /* ==== WASM: 33 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -7295,7 +7938,7 @@ std::map> wasm = { 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 26 ==== */ + /* ==== WASM: 34 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -7590,7 +8233,7 @@ std::map> wasm = { 0x32U, 0x34U, 0x31U, 0x36U, 0x55U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 27 ==== */ + /* ==== WASM: 35 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8303,7 +8946,7 @@ std::map> wasm = { 0x31U, 0x33U, 0x33U, 0x38U, 0x20U, 0x29U, 0x00U, }}, - /* ==== WASM: 28 ==== */ + /* ==== WASM: 36 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8388,7 +9031,7 @@ std::map> wasm = { 0x30U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x32U, 0x30U, 0x00U, }}, - /* ==== WASM: 29 ==== */ + /* ==== WASM: 37 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8450,7 +9093,7 @@ std::map> wasm = { 0x80U, 0x80U, 0x00U, 0x0BU, }}, - /* ==== WASM: 30 ==== */ + /* ==== WASM: 38 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8527,7 +9170,7 @@ std::map> wasm = { 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 31 ==== */ + /* ==== WASM: 39 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8604,7 +9247,7 @@ std::map> wasm = { 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 32 ==== */ + /* ==== WASM: 40 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8861,7 +9504,7 @@ std::map> wasm = { 0x00U, 0x00U, }}, - /* ==== WASM: 33 ==== */ + /* ==== WASM: 41 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -9019,7 +9662,7 @@ std::map> wasm = { 0x04U, 0x00U, 0x00U, }}, - /* ==== WASM: 34 ==== */ + /* ==== WASM: 42 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -9372,7 +10015,7 @@ std::map> wasm = { 0x00U, 0x2AU, 0x04U, 0x00U, 0x00U, 0x31U, 0x04U, 0x00U, 0x00U, }}, - /* ==== WASM: 35 ==== */ + /* ==== WASM: 43 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -9405,7 +10048,7 @@ std::map> wasm = { 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x0BU, }}, - /* ==== WASM: 36 ==== */ + /* ==== WASM: 44 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -9632,7 +10275,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 37 ==== */ + /* ==== WASM: 45 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -9663,7 +10306,7 @@ std::map> wasm = { 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x0BU, }}, - /* ==== WASM: 38 ==== */ + /* ==== WASM: 46 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -9974,7 +10617,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 39 ==== */ + /* ==== WASM: 47 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10051,7 +10694,7 @@ std::map> wasm = { 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 40 ==== */ + /* ==== WASM: 48 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10085,7 +10728,7 @@ std::map> wasm = { 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x0BU, }}, - /* ==== WASM: 41 ==== */ + /* ==== WASM: 49 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10172,7 +10815,7 @@ std::map> wasm = { 0x32U, 0x00U, }}, - /* ==== WASM: 42 ==== */ + /* ==== WASM: 50 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10206,7 +10849,7 @@ std::map> wasm = { 0x0BU, }}, - /* ==== WASM: 43 ==== */ + /* ==== WASM: 51 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10346,7 +10989,7 @@ std::map> wasm = { 0x54U, 0x5FU, 0x4DU, 0x45U, 0x54U, 0x00U, }}, - /* ==== WASM: 44 ==== */ + /* ==== WASM: 52 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10536,7 +11179,7 @@ std::map> wasm = { 0x31U, 0x34U, 0x00U, }}, - /* ==== WASM: 45 ==== */ + /* ==== WASM: 53 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10690,7 +11333,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 46 ==== */ + /* ==== WASM: 54 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10851,7 +11494,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 47 ==== */ + /* ==== WASM: 55 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11008,7 +11651,7 @@ std::map> wasm = { 0x53U, 0x4CU, 0x4FU, 0x54U, 0x53U, 0x00U, }}, - /* ==== WASM: 48 ==== */ + /* ==== WASM: 56 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11093,7 +11736,7 @@ std::map> wasm = { 0x74U, 0x79U, 0x70U, 0x65U, 0x28U, 0x29U, 0x00U, }}, - /* ==== WASM: 49 ==== */ + /* ==== WASM: 57 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11350,7 +11993,7 @@ std::map> wasm = { 0x00U, 0x00U, }}, - /* ==== WASM: 50 ==== */ + /* ==== WASM: 58 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11588,7 +12231,7 @@ std::map> wasm = { 0x3EU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 51 ==== */ + /* ==== WASM: 59 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11684,7 +12327,7 @@ std::map> wasm = { 0x53U, 0x54U, 0x00U, }}, - /* ==== WASM: 52 ==== */ + /* ==== WASM: 60 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11794,7 +12437,7 @@ std::map> wasm = { 0x20U, 0x31U, 0x00U, }}, - /* ==== WASM: 53 ==== */ + /* ==== WASM: 61 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11924,7 +12567,7 @@ std::map> wasm = { 0x30U, 0x30U, 0x30U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 54 ==== */ + /* ==== WASM: 62 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -12198,7 +12841,7 @@ std::map> wasm = { 0x30U, 0x00U, }}, - /* ==== WASM: 55 ==== */ + /* ==== WASM: 63 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -12335,7 +12978,7 @@ std::map> wasm = { 0x2CU, 0x20U, 0x73U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x31U, 0x00U, }}, - /* ==== WASM: 56 ==== */ + /* ==== WASM: 64 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -12629,7 +13272,7 @@ std::map> wasm = { 0x5FU, 0x53U, 0x4CU, 0x4FU, 0x54U, 0x53U, 0x00U, }}, - /* ==== WASM: 57 ==== */ + /* ==== WASM: 65 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -12863,7 +13506,7 @@ std::map> wasm = { 0x5FU, 0x53U, 0x4CU, 0x4FU, 0x54U, 0x53U, 0x00U, }}, - /* ==== WASM: 58 ==== */ + /* ==== WASM: 66 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -13159,7 +13802,7 @@ std::map> wasm = { 0x2CU, 0x20U, 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 59 ==== */ + /* ==== WASM: 67 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -13363,7 +14006,7 @@ std::map> wasm = { 0x6EU, 0x74U, 0x32U, 0x22U, 0x20U, 0x2BU, 0x20U, 0x69U, 0x29U, 0x00U, }}, - /* ==== WASM: 60 ==== */ + /* ==== WASM: 68 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -13480,7 +14123,7 @@ std::map> wasm = { 0x69U, 0x29U, 0x00U, }}, - /* ==== WASM: 61 ==== */ + /* ==== WASM: 69 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -13589,7 +14232,7 @@ std::map> wasm = { 0x6EU, 0x74U, 0x65U, 0x6EU, 0x74U, 0x32U, 0x22U, 0x29U, 0x00U, }}, - /* ==== WASM: 62 ==== */ + /* ==== WASM: 70 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -13862,7 +14505,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 63 ==== */ + /* ==== WASM: 71 ==== */ {R"[test.hook]( #include #define sfInvoiceID ((5U << 16U) + 17U) @@ -14081,7 +14724,7 @@ std::map> wasm = { 0x30U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 64 ==== */ + /* ==== WASM: 72 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -14193,7 +14836,7 @@ std::map> wasm = { 0x58U, 0x49U, 0x53U, 0x54U, 0x00U, }}, - /* ==== WASM: 65 ==== */ + /* ==== WASM: 73 ==== */ {R"[test.hook]( #include #define sfInvoiceID ((5U << 16U) + 17U) @@ -14329,7 +14972,7 @@ std::map> wasm = { 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 66 ==== */ + /* ==== WASM: 74 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -14465,7 +15108,7 @@ std::map> wasm = { 0x49U, 0x47U, 0x00U, }}, - /* ==== WASM: 67 ==== */ + /* ==== WASM: 75 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -14604,7 +15247,7 @@ std::map> wasm = { 0x66U, 0x28U, 0x64U, 0x61U, 0x74U, 0x61U, 0x32U, 0x29U, 0x00U, }}, - /* ==== WASM: 68 ==== */ + /* ==== WASM: 76 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -14716,7 +15359,7 @@ std::map> wasm = { 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 69 ==== */ + /* ==== WASM: 77 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -14810,7 +15453,7 @@ std::map> wasm = { 0x61U, 0x64U, 0x5BU, 0x69U, 0x5DU, 0x00U, }}, - /* ==== WASM: 70 ==== */ + /* ==== WASM: 78 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -14943,7 +15586,7 @@ std::map> wasm = { 0x64U, 0x5BU, 0x69U, 0x5DU, 0x00U, }}, - /* ==== WASM: 71 ==== */ + /* ==== WASM: 79 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -15031,7 +15674,7 @@ std::map> wasm = { 0x61U, 0x74U, 0x61U, 0x29U, 0x00U, }}, - /* ==== WASM: 72 ==== */ + /* ==== WASM: 80 ==== */ {R"[test.hook]( #include #define sfInvoiceID ((5U << 16U) + 17U) @@ -15142,7 +15785,7 @@ std::map> wasm = { 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 73 ==== */ + /* ==== WASM: 81 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -15353,7 +15996,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 74 ==== */ + /* ==== WASM: 82 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -15461,7 +16104,7 @@ std::map> wasm = { 0x20U, 0x22U, 0x32U, 0x22U, 0x2CU, 0x20U, 0x31U, 0x29U, 0x00U, }}, - /* ==== WASM: 75 ==== */ + /* ==== WASM: 83 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16073,7 +16716,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 76 ==== */ + /* ==== WASM: 84 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16260,7 +16903,7 @@ std::map> wasm = { 0x63U, 0x65U, 0x29U, 0x20U, 0x3EU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 77 ==== */ + /* ==== WASM: 85 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16610,7 +17253,7 @@ std::map> wasm = { 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 78 ==== */ + /* ==== WASM: 86 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16746,7 +17389,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 79 ==== */ + /* ==== WASM: 87 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16805,7 +17448,7 @@ std::map> wasm = { 0x64U, 0xE1U, 0xF1U, }}, - /* ==== WASM: 79 ==== */ + /* ==== WASM: 88 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16978,7 +17621,7 @@ std::map> wasm = { 0x54U, 0x5FU, 0x45U, 0x58U, 0x49U, 0x53U, 0x54U, 0x00U, }}, - /* ==== WASM: 80 ==== */ + /* ==== WASM: 89 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17126,7 +17769,7 @@ std::map> wasm = { 0x30U, 0x00U, 0x22U, 0x00U, 0x00U, 0x00U, 0x00U, }}, - /* ==== WASM: 81 ==== */ + /* ==== WASM: 90 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17223,7 +17866,7 @@ std::map> wasm = { 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 82 ==== */ + /* ==== WASM: 91 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17282,7 +17925,7 @@ std::map> wasm = { 0x4FU, 0x46U, 0x5FU, 0x42U, 0x4FU, 0x55U, 0x4EU, 0x44U, 0x53U, 0x00U, }}, - /* ==== WASM: 83 ==== */ + /* ==== WASM: 92 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17341,7 +17984,7 @@ std::map> wasm = { 0x4EU, 0x44U, 0x53U, 0x00U, }}, - /* ==== WASM: 84 ==== */ + /* ==== WASM: 93 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -19170,7 +19813,7 @@ std::map> wasm = { 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 85 ==== */ + /* ==== WASM: 94 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -20512,7 +21155,7 @@ std::map> wasm = { 0x20U, 0x30U, 0x2CU, 0x20U, 0x30U, 0x29U, 0x29U, 0x00U, }}, - /* ==== WASM: 86 ==== */ + /* ==== WASM: 95 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -23445,7 +24088,7 @@ std::map> wasm = { 0x4FU, 0x4FU, 0x5FU, 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 87 ==== */ + /* ==== WASM: 96 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -25410,7 +26053,7 @@ std::map> wasm = { 0x54U, 0x4FU, 0x4FU, 0x5FU, 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 88 ==== */ + /* ==== WASM: 97 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -25695,7 +26338,7 @@ std::map> wasm = { 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 89 ==== */ + /* ==== WASM: 98 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); @@ -26282,7 +26925,7 @@ std::map> wasm = { 0x4EU, 0x5FU, 0x46U, 0x41U, 0x49U, 0x4CU, 0x55U, 0x52U, 0x45U, 0x00U, }}, - /* ==== WASM: 90 ==== */ + /* ==== WASM: 99 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -26311,7 +26954,7 @@ std::map> wasm = { 0x0BU, }}, - /* ==== WASM: 91 ==== */ + /* ==== WASM: 100 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -26343,7 +26986,7 @@ std::map> wasm = { 0x20U, 0x52U, 0x65U, 0x6AU, 0x65U, 0x63U, 0x74U, 0x65U, 0x64U, 0x00U, }}, - /* ==== WASM: 92 ==== */ + /* ==== WASM: 101 ==== */ {R"[test.hook]( (module (type (;0;) (func (param i32 i32 i64) (result i64))) @@ -26370,7 +27013,7 @@ std::map> wasm = { 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x00U, 0x0BU, }}, - /* ==== WASM: 93 ==== */ + /* ==== WASM: 102 ==== */ {R"[test.hook]( (module (type (;0;) (func (param i32 i32) (result i32))) @@ -26423,7 +27066,7 @@ std::map> wasm = { 0x00U, 0x1AU, 0x0BU, }}, - /* ==== WASM: 94 ==== */ + /* ==== WASM: 103 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -33066,7 +33709,7 @@ std::map> wasm = { 0x39U, 0x30U, 0x31U, 0x32U, 0x33U, 0x00U, }}, - /* ==== WASM: 95 ==== */ + /* ==== WASM: 104 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -33112,7 +33755,7 @@ std::map> wasm = { 0x0BU, 0x06U, 0x76U, 0x61U, 0x6CU, 0x75U, 0x65U, 0x00U, }}, - /* ==== WASM: 96 ==== */ + /* ==== WASM: 105 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); diff --git a/src/test/app/build_test_hooks.sh b/src/test/app/build_test_hooks.sh index 4e57701a88..2110d4b139 100755 --- a/src/test/app/build_test_hooks.sh +++ b/src/test/app/build_test_hooks.sh @@ -58,8 +58,21 @@ cat $INPUT_FILE | tr '\n' '\f' | then echo '#include "api.h"' > "$WASM_DIR/test-$COUNTER-gen.c" tr '\f' '\n' <<< $line >> "$WASM_DIR/test-$COUNTER-gen.c" - DECLARED="`tr '\f' '\n' <<< $line | grep -E '(extern|define) ' | grep -Eo '[a-z\-\_]+ *\(' | grep -v 'sizeof' | sed -E 's/[^a-z\-\_]//g' | sort | uniq`" - USED="`tr '\f' '\n' <<< $line | grep -vE '(extern|define) ' | grep -Eo '[a-z\-\_]+\(' | grep -v 'sizeof' | sed -E 's/[^a-z\-\_]//g' | grep -vE '^(hook|cbak)' | sort | uniq`" + DECLARED="`tr '\f' '\n' <<< $line \ + | grep -E '(extern|static|define) ' \ + | grep -Eo '[a-z\-\_]+ *\(' \ + | grep -v 'sizeof' \ + | sed -E 's/[^a-z\-\_]//g' \ + | grep -vE '^__attribute__$' \ + | sort | uniq`" + + USED="`tr '\f' '\n' <<< $line \ + | grep -vE '(extern|static|define) ' \ + | grep -Eo '[a-z\-\_]+\(' \ + | grep -v 'sizeof' \ + | sed -E 's/[^a-z\-\_]//g' \ + | grep -vE '^(__attribute__|hook|cbak)$' \ + | sort | uniq`" ONCE="`echo $DECLARED $USED | tr ' ' '\n' | sort | uniq -c | grep '1 ' | sed -E 's/^ *1 //g'`" FILTER="`echo $DECLARED | tr ' ' '|' | sed -E 's/\|$//g'`" UNDECL="`echo $ONCE | grep -v -E $FILTER 2>/dev/null || echo ''`" @@ -69,7 +82,7 @@ cat $INPUT_FILE | tr '\n' '\f' | echo "$line" exit 1 fi - wasmcc -x c /dev/stdin -o /dev/stdout -O2 -Wl,--allow-undefined <<< "`tr '\f' '\n' <<< $line`" | + wasmcc -x c /dev/stdin -o /dev/stdout -O2 -Wl,--allow-undefined,--export=hook,--export=cbak <<< "`tr '\f' '\n' <<< $line`" | hook-cleaner - - 2>/dev/null | xxd -p -u -c 10 | sed -E 's/../0x&U,/g' | sed -E 's/^/ /g' >> $OUTPUT_FILE