diff --git a/src/ripple/app/tx/applyHook.h b/src/ripple/app/tx/applyHook.h index 6e59ec107..abb028574 100644 --- a/src/ripple/app/tx/applyHook.h +++ b/src/ripple/app/tx/applyHook.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace hook { struct HookContext; @@ -194,7 +194,7 @@ namespace hook_api { DECLARE_HOOK_FUNCTION(int64_t, hook_param_set, uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t hread_ptr, uint32_t hread_len); - + DECLARE_HOOK_FUNCTION(int64_t, hook_param, uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); @@ -247,26 +247,26 @@ namespace hook { struct HookResult; - HookResult apply( - ripple::uint256 const&, - ripple::uint256 const&, - ripple::uint256 const&, - ripple::Blob const&, + hook::apply( + ripple::uint256 const& hookSetTxnID, /* this is the txid of the sethook, used for caching (one day) */ + ripple::uint256 const& hookHash, /* hash of the actual hook byte code, used for metadata */ + ripple::uint256 const& hookNamespace, + ripple::Blob const& wasm, + std::map< + std::vector, /* param name */ + std::vector /* param value */ + > const& hookParams, + std::map< + ripple::uint256, /* hook hash */ std::map< - std::vector, /* param name */ - std::vector /* param value */ - > const& parameters, - std::map< - ripple::uint256, - std::map< - std::vector, /* param name */ - std::vector /* param value */ - >> const& parameterOverrides, - ripple::ApplyContext&, - ripple::AccountID const&, - bool callback, - uint32_t wasmParam = 0, - int32_t hookChainPosition = -1); + std::vector, + std::vector + >> const& hookParamOverrides, + ripple::ApplyContext& applyCtx, + ripple::AccountID const& account, /* the account the hook is INSTALLED ON not always the otxn account */ + bool callback = false, + uint32_t wasmParam = 0, + int32_t hookChainPosition = -1); struct HookContext; @@ -376,12 +376,15 @@ namespace hook { // create these once at boot and keep them WasmEdge_String exportName = WasmEdge_StringCreateByCString("env"); WasmEdge_String tableName = WasmEdge_StringCreateByCString("table"); - WasmEdge_TableTypeContext* tableType = + WasmEdge_TableTypeContext* tableType = WasmEdge_TableTypeCreate(WasmEdge_RefType_FuncRef, {.HasMax = true, .Min = 10, .Max = 20}); WasmEdge_MemoryTypeContext* memType = WasmEdge_MemoryTypeCreate({.HasMax = true, .Min = 1, .Max = 1}); WasmEdge_String memName = WasmEdge_StringCreateByCString("memory"); + WasmEdge_String cbakFunctionName = WasmEdge_StringCreateByCString("cbak"); + WasmEdge_String hookFunctionName = WasmEdge_StringCreateByCString("hook"); + // RH TODO: call destruct for these on rippled shutdown #define ADD_HOOK_FUNCTION(F, ctx)\ @@ -391,19 +394,102 @@ namespace hook { WasmEdge_ImportObjectAddFunction(importObj, WasmFunctionName##F, hf);\ } - class HookModule - { - //RH TODO UPTO put the hook-api functions here! - //then wrap/proxy them with the appropriate DECLARE_HOOK classes - //and add those below. HookModule::otxn_id() ... - public: - HookContext hookCtx; + #define HR_ACC() hookResult.account << "-" << hookResult.otxnAccount + #define HC_ACC() hookCtx.result.account << "-" << hookCtx.result.otxnAccount - HookModule(HookContext& ctx) : hookCtx(ctx) + + /** + * HookExecutor is effectively a two-part function: + * The first part sets up the Hook Api inside the wasm import, ready for use + * (this is done during object construction.) + * The second part is actually executing webassembly instructions + * this is done during execteWasm function. + * The instance is single use. + */ + class HookExecutor + { + + private: + bool spent = false; // a HookExecutor can only be used once + + public: + HookContext hookCtx; + WasmEdge_ImportObjectContext* importObj; + + + /** + * Execute web assembly byte code against the constructed Hook Context + * Once execution has occured the exector is spent and cannot be used again and should be destructed + * Information about the execution is populated into hookCtx + */ + void executeWasm(void* wasm, size_t len, bool callback, WasmEdge_Value wasmParam, beast::Journal const& j) + { + + // HookExecutor can only execute once + assert(!spent); + + spent = true; + + JLOG(j.trace()) + << "HookInfo[" << HC_ACC() << "]: creating wasm instance"; + + WasmEdge_ConfigureContext* confCtx = WasmEdge_ConfigureCreate(); + WasmEdge_ConfigureStatisticsSetInstructionCounting(confCtx, true); + WasmEdge_VMContext vmCtx = WasmEdge_VMCreate(confCtx, NULL); + + + WasmEdge_Result res = WasmEdge_VMRegisterModuleFromImport(vmCtx, this->importObj); + if (!WasmEdge_ResultOK(res)) + { + hookCtx.result.exitType = hook_api::ExitType::WASM_ERROR; + JLOG(j.trace()) + << "HookError[" << HC_ACC() << "]: Import phase failed " + << WasmEdge_ResultGetMessage(res); + } + else + { + + WasmEdge_Value params[1] = {wasmParam}; + WasmEdge_Value results[1]; + + res = + WasmEdge_VMRunWasmFromBuffer(vmCtx, wasm, len, + callback ? cbakFunctionName : hookFunctionName, + params, 1, returns, 1); + + if (!WasmEdge_ResultOK(res)) + { + JLOG(j.warn()) + << "HookError[" << HC_ACC() << "]: WASM VM error " + << WasmEdge_ResultGetMessage(res); + hookCtx.result.exitType = hook_api::ExitType::WASM_ERROR; + } + else + { + + auto* statsCtx= WasmEdge_VMGetStatisticsContext(vmCtx); + hookCtx.result.instructionCount = WasmEdge_StatisticsGetInstrCount(statsCtx); + + JLOG(j.trace()) + << "HookInfo[" << HC_ACC() << "]: " + << (hookCtx.result.exitType == hook_api::ExitType::ROLLBACK ? "ROLLBACK" : "ACCEPT") + << " RS: '" << hookCtx.result.exitReason.c_str() + << "' RC: " << hookCtx.result.exitCode; + + //WasmEdge_ValueGetI64(returns[0])); + } + } + + WasmEdge_ConfigureDelete(confCtx); + WasmEdge_VMDelete(vmCtx); + } + + HookModule(HookContext& ctx) + : hookCtx(ctx) + , importObj(WasmEdge_ImportObjectCreate(exportName)) { ctx.module = this; - WasmEdge_ImportObjectContext* importObj = WasmEdge_ImportObjectCreate(exportName); ADD_HOOK_FUNCTION(_g, ctx); ADD_HOOK_FUNCTION(accept, ctx); ADD_HOOK_FUNCTION(rollback, ctx); @@ -447,8 +533,6 @@ namespace hook { ADD_HOOK_FUNCTION(float_sign_set, ctx); ADD_HOOK_FUNCTION(float_int, ctx); - - ADD_HOOK_FUNCTION(otxn_burden, ctx); ADD_HOOK_FUNCTION(otxn_generation, ctx); ADD_HOOK_FUNCTION(otxn_field_txt, ctx); @@ -494,7 +578,11 @@ namespace hook { WasmEdge_MemoryInstanceContext* hostMem = WasmEdge_MemoryInstanceCreate(memType); WasmEdge_ImportObjectAddMemory(importObj, memName, hostMem); } - virtual ~HookModule() = default; + + ~HookModule() + { + WasmEdge_ImportObjectDelete(importObj); + }; }; } diff --git a/src/ripple/app/tx/applyHookMacro.h b/src/ripple/app/tx/applyHookMacro.h index 5a3f59a87..ffde4d93c 100644 --- a/src/ripple/app/tx/applyHookMacro.h +++ b/src/ripple/app/tx/applyHookMacro.h @@ -31,16 +31,16 @@ #define DELIM_2 ; #define DELIM(S) DELIM_##S -#define FOR_VAR_1(T, D) SEP(T, D) -#define FOR_VAR_2(T, S, a, b) FOR_VAR_1(T, a) DELIM(S) FOR_VAR_1(T, b) -#define FOR_VAR_3(T, S, a, ...) FOR_VAR_1(T, a) DELIM(S) FOR_VAR_2(T, S, __VA_ARGS__) -#define FOR_VAR_4(T, S, a, ...) FOR_VAR_1(T, a) DELIM(S) FOR_VAR_3(T, S, __VA_ARGS__) -#define FOR_VAR_5(T, S, a, ...) FOR_VAR_1(T, a) DELIM(S) FOR_VAR_4(T, S, __VA_ARGS__) -#define FOR_VAR_6(T, S, a, ...) FOR_VAR_1(T, a) DELIM(S) FOR_VAR_5(T, S, __VA_ARGS__) -#define FOR_VAR_7(T, S, a, ...) FOR_VAR_1(T, a) DELIM(S) FOR_VAR_6(T, S, __VA_ARGS__) -#define FOR_VAR_8(T, S, a, ...) FOR_VAR_1(T, a) DELIM(S) FOR_VAR_7(T, S, __VA_ARGS__) -#define FOR_VAR_9(T, S, a, ...) FOR_VAR_1(T, a) DELIM(S) FOR_VAR_8(T, S, __VA_ARGS__) -#define FOR_VAR_10(T, S, a, ...) FOR_VAR_1(T, a) DELIM(S) FOR_VAR_9(T, S, __VA_ARGS__) +#define FOR_VAR_1(T, S, D) SEP(T, D) +#define FOR_VAR_2(T, S, a, b) FOR_VAR_1(T, S, a) DELIM(S) FOR_VAR_1(T, S, b) +#define FOR_VAR_3(T, S, a, ...) FOR_VAR_1(T, S, a) DELIM(S) FOR_VAR_2(T, S, __VA_ARGS__) +#define FOR_VAR_4(T, S, a, ...) FOR_VAR_1(T, S, a) DELIM(S) FOR_VAR_3(T, S, __VA_ARGS__) +#define FOR_VAR_5(T, S, a, ...) FOR_VAR_1(T, S, a) DELIM(S) FOR_VAR_4(T, S, __VA_ARGS__) +#define FOR_VAR_6(T, S, a, ...) FOR_VAR_1(T, S, a) DELIM(S) FOR_VAR_5(T, S, __VA_ARGS__) +#define FOR_VAR_7(T, S, a, ...) FOR_VAR_1(T, S, a) DELIM(S) FOR_VAR_6(T, S, __VA_ARGS__) +#define FOR_VAR_8(T, S, a, ...) FOR_VAR_1(T, S, a) DELIM(S) FOR_VAR_7(T, S, __VA_ARGS__) +#define FOR_VAR_9(T, S, a, ...) FOR_VAR_1(T, S, a) DELIM(S) FOR_VAR_8(T, S, __VA_ARGS__) +#define FOR_VAR_10(T, S, a, ...) FOR_VAR_1(T, S, a) DELIM(S) FOR_VAR_9(T, S, __VA_ARGS__) #define FOR_VARS(T, S, ...)\ DEFER(CAT(FOR_VAR_,VA_NARGS(NULL, __VA_ARGS__))CAT(LPAREN T COMMA S COMMA OBSTRUCT(__VA_ARGS__) RPAREN)) @@ -75,6 +75,7 @@ CAT2(TYP_,T) #define DECLARE_HOOK_FUNCTION(R, F, ...)\ + R F(hook::HookContext& hookCtx, WasmEdge_MemoryInstanceContext& memoryCtx, __VA_ARGS__);\ WasmEdge_Result WasmFunction##F(\ void *data_ptr, WasmEdge_MemoryInstanceContext *memCtx,\ const WasmEdge_Value *in, WasmEdge_Value *out)\ @@ -88,16 +89,16 @@ out[0] = RET_ASSIGN(R, return_code);\ return WasmEdge_Result_Success;\ };\ - WasmEdge_FunctionTypeContext* WasmFunctionType##F = NULL;\ - {\ - enum WasmEdge_ValType r = { WASM_VAL_TYPE(R, dummy) };\ - enum WasmEdge_ValType p = { FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__) };\ - WasmFunctionType##F = WasmEdge_FunctionTypeCreate(p, VA_NARGS(NULL, __VA_ARGS__), r, 1);\ - };\ + WasmEdge_ValType WasmFunctionParams##F[] = { FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__) };\ + WasmEdge_ValType WasmFunctionResult##F[1] = { WASM_VAL_TYPE(R, dummy) };\ + WasmEdge_FunctionTypeContext* WasmFunctionType##F = WasmEdge_FunctionTypeCreate(\ + WasmFunctionParams##F, VA_NARGS(NULL, __VA_ARGS__),\ + WasmFunctionResult##F, 1);\ WasmEdge_String WasmFunctionName##F = WasmEdge_StringCreateByCString(#F); #define DECLARE_HOOK_FUNCNARG(R, F)\ + R F(hook::HookContext& hookCtx, WasmEdge_MemoryInstanceContext& memoryCtx);\ WasmEdge_Result WasmFunction_##F(\ void *data_ptr, WasmEdge_MemoryInstanceContext *memCtx,\ const WasmEdge_Value *in, WasmEdge_Value *out)\ @@ -106,15 +107,12 @@ R return_code = hook_api::F(*hookCtx, *memCtx);\ if (return_code == RC_ROLLBACK || return_code == RC_ACCEPT)\ return WasmEdge_Result_Terminate;\ - Out[0] = CAT2(RET_,R(return_code));\ + out[0] = CAT2(RET_,R(return_code));\ return WasmEdge_Result_Success;\ };\ - WasmEdge_FunctionTypeContext* WasmFunctionType##F = NULL;\ - {\ - enum WasmEdge_ValType r = { WASM_VAL_TYPE(R, dummy) };\ - enum WasmEdge_ValType p = { };\ - WasmFunctionType##F = WasmEdge_FunctionTypeCreate(p, 0, r, 1);\ - }\ + WasmEdge_ValType WasmFunctionResult##F[1] = { WASM_VAL_TYPE(R, dummy) };\ + WasmEdge_FunctionTypeContext* WasmFunctionType##F = \ + WasmEdge_FunctionTypeCreate({}, 0, WasmFunctionResult##F, 1);\ WasmEdge_String WasmFunctionName##F = WasmEdge_StringCreateByCString(#F); #define DEFINE_HOOK_FUNCTION(R, F, ...)\ @@ -123,3 +121,107 @@ #define DEFINE_HOOK_FUNCNARG(R, F)\ R hook_api::F(hook::HookContext& hookCtx, WasmEdge_MemoryInstanceContext& memoryCtx) + + + + +#define COMPUTE_HOOK_DATA_OWNER_COUNT(state_count)\ + (std::ceil( (double)state_count/(double)5.0 )) + +#define HOOK_SETUP()\ + [[maybe_unused]] ApplyContext& applyCtx = hookCtx.applyCtx;\ + [[maybe_unused]] auto& view = applyCtx.view();\ + [[maybe_unused]] auto j = applyCtx.app.journal("View");\ + [[maybe_unused]] unsigned char* memory = WasmEdge_MemoryInstanceGetPointer(memoryCtx, 0, 0);\ + [[maybe_unused]] const uint64_t memory_length = WasmEdge_MemoryInstanceGetPageSize(memoryCtx); + +#define WRITE_WASM_MEMORY(bytes_written, guest_dst_ptr, guest_dst_len,\ + host_src_ptr, host_src_len, host_memory_ptr, guest_memory_length)\ +{\ + int64_t bytes_to_write = std::min(static_cast(host_src_len), static_cast(guest_dst_len));\ + if (guest_dst_ptr + bytes_to_write > guest_memory_length)\ + {\ + JLOG(j.warn())\ + << "HookError[" << HC_ACC() << "]: "\ + << __func__ << " tried to retreive blob of " << host_src_len\ + << " bytes past end of wasm memory";\ + return OUT_OF_BOUNDS;\ + }\ + WasmEdge_MemoryInstanceGetPointer(memoryCtx, host_src_ptr, guest_dst_ptr, bytes_to_write);\ + bytes_written += bytes_to_write;\ +} + +#define WRITE_WASM_MEMORY_AND_RETURN(guest_dst_ptr, guest_dst_len,\ + host_src_ptr, host_src_len, host_memory_ptr, guest_memory_length)\ +{\ + int64_t bytes_written = 0;\ + WRITE_WASM_MEMORY(bytes_written, guest_dst_ptr, guest_dst_len, host_src_ptr,\ + host_src_len, host_memory_ptr, guest_memory_length);\ + return bytes_written;\ +} + +#define RETURN_HOOK_TRACE(read_ptr, read_len, t)\ +{\ + int rl = read_len;\ + if (rl > 1024)\ + rl = 1024;\ + if (NOT_IN_BOUNDS(read_ptr, read_len, memory_length))\ + {\ + return OUT_OF_BOUNDS;\ + }\ + else if (read_ptr == 0 && read_len == 0)\ + {\ + JLOG(j.trace()) \ + << "HookTrace[" << HC_ACC() << "]: " << t;\ + }\ + else if (is_UTF16LE(memory + read_ptr, rl))\ + {\ + uint8_t output[1024];\ + int len = rl / 2;\ + for (int i = 0; i < len && i < 512; ++i)\ + output[i] = memory[read_ptr + i * 2];\ + JLOG(j.trace()) \ + << "HookTrace[" << HC_ACC() << "]: "\ + << std::string_view((const char*)output, (size_t)(len)) << " "\ + << t;\ + }\ + else\ + {\ + JLOG(j.trace()) \ + << "HookTrace[" << HC_ACC() << "]: "\ + << std::string_view((const char*)(memory + read_ptr), (size_t)rl) << " "\ + << t;\ + }\ + return 0;\ +} +// ptr = pointer inside the wasm memory space +#define NOT_IN_BOUNDS(ptr, len, memory_length)\ + (ptr > memory_length || \ + static_cast(ptr) + static_cast(len) > static_cast(memory_length)) + +#define HOOK_EXIT(read_ptr, read_len, error_code, exit_type)\ +{\ + if (read_len > 256) read_len = 256;\ + if (read_ptr) {\ + if (NOT_IN_BOUNDS(read_ptr, read_len, memory_length)) {\ + JLOG(j.warn())\ + << "HookError[" << HC_ACC() << "]: "\ + << "Tried to accept/rollback but specified memory outside of the wasm instance " <<\ + "limit when specifying a reason string";\ + return OUT_OF_BOUNDS;\ + }\ + /* assembly script and some other languages use utf16 for strings */\ + if (is_UTF16LE(read_ptr + memory, read_len))\ + {\ + uint8_t output[128];\ + int len = read_len / 2; /* is_UTF16LE will only return true if read_len is even */\ + for (int i = 0; i < len; ++i)\ + output[i] = memory[read_ptr + i * 2];\ + hookCtx.result.exitReason = std::string((const char*)(output), (size_t)len);\ + } else\ + hookCtx.result.exitReason = std::string((const char*)(memory + read_ptr), (size_t)read_len);\ + }\ + hookCtx.result.exitType = exit_type;\ + hookCtx.result.exitCode = error_code;\ + return (exit_type == hook_api::ExitType::ACCEPT ? RC_ACCEPT : RC_ROLLBACK);\ +} diff --git a/src/ripple/app/tx/impl/applyHook.cpp b/src/ripple/app/tx/impl/applyHook.cpp index 1316deec4..841760b65 100644 --- a/src/ripple/app/tx/impl/applyHook.cpp +++ b/src/ripple/app/tx/impl/applyHook.cpp @@ -19,110 +19,7 @@ using namespace ripple; -#define HR_ACC() hookResult.account << "-" << hookResult.otxnAccount -#define HC_ACC() hookCtx.result.account << "-" << hookCtx.result.otxnAccount -#define COMPUTE_HOOK_DATA_OWNER_COUNT(state_count)\ - (std::ceil( (double)state_count/(double)5.0 )) - -#define HOOK_SETUP()\ - [[maybe_unused]] ApplyContext& applyCtx = hookCtx.applyCtx;\ - [[maybe_unused]] auto& view = applyCtx.view();\ - [[maybe_unused]] auto j = applyCtx.app.journal("View");\ - [[maybe_unused]] unsigned char* memory = memoryCtx.getPointer(0);\ - [[maybe_unused]] const uint64_t memory_length = memoryCtx.getDataPageSize() * memoryCtx.kPageSize; - -#define WRITE_WASM_MEMORY(bytes_written, guest_dst_ptr, guest_dst_len,\ - host_src_ptr, host_src_len, host_memory_ptr, guest_memory_length)\ -{\ - int64_t bytes_to_write = std::min(static_cast(host_src_len), static_cast(guest_dst_len));\ - if (guest_dst_ptr + bytes_to_write > guest_memory_length)\ - {\ - JLOG(j.warn())\ - << "HookError[" << HC_ACC() << "]: "\ - << __func__ << " tried to retreive blob of " << host_src_len\ - << " bytes past end of wasm memory";\ - return OUT_OF_BOUNDS;\ - }\ - memoryCtx.setBytes(SSVM::Span((const uint8_t*)host_src_ptr, host_src_len), \ - guest_dst_ptr, 0, bytes_to_write);\ - bytes_written += bytes_to_write;\ -} - -#define WRITE_WASM_MEMORY_AND_RETURN(guest_dst_ptr, guest_dst_len,\ - host_src_ptr, host_src_len, host_memory_ptr, guest_memory_length)\ -{\ - int64_t bytes_written = 0;\ - WRITE_WASM_MEMORY(bytes_written, guest_dst_ptr, guest_dst_len, host_src_ptr,\ - host_src_len, host_memory_ptr, guest_memory_length);\ - return bytes_written;\ -} - -#define RETURN_HOOK_TRACE(read_ptr, read_len, t)\ -{\ - int rl = read_len;\ - if (rl > 1024)\ - rl = 1024;\ - if (NOT_IN_BOUNDS(read_ptr, read_len, memory_length))\ - {\ - return OUT_OF_BOUNDS;\ - }\ - else if (read_ptr == 0 && read_len == 0)\ - {\ - JLOG(j.trace()) \ - << "HookTrace[" << HC_ACC() << "]: " << t;\ - }\ - else if (is_UTF16LE(memory + read_ptr, rl))\ - {\ - uint8_t output[1024];\ - int len = rl / 2;\ - for (int i = 0; i < len && i < 512; ++i)\ - output[i] = memory[read_ptr + i * 2];\ - JLOG(j.trace()) \ - << "HookTrace[" << HC_ACC() << "]: "\ - << std::string_view((const char*)output, (size_t)(len)) << " "\ - << t;\ - }\ - else\ - {\ - JLOG(j.trace()) \ - << "HookTrace[" << HC_ACC() << "]: "\ - << std::string_view((const char*)(memory + read_ptr), (size_t)rl) << " "\ - << t;\ - }\ - return 0;\ -} -// ptr = pointer inside the wasm memory space -#define NOT_IN_BOUNDS(ptr, len, memory_length)\ - (ptr > memory_length || \ - static_cast(ptr) + static_cast(len) > static_cast(memory_length)) - -#define HOOK_EXIT(read_ptr, read_len, error_code, exit_type)\ -{\ - if (read_len > 256) read_len = 256;\ - if (read_ptr) {\ - if (NOT_IN_BOUNDS(read_ptr, read_len, memory_length)) {\ - JLOG(j.warn())\ - << "HookError[" << HC_ACC() << "]: "\ - << "Tried to accept/rollback but specified memory outside of the wasm instance " <<\ - "limit when specifying a reason string";\ - return OUT_OF_BOUNDS;\ - }\ - /* assembly script and some other languages use utf16 for strings */\ - if (is_UTF16LE(read_ptr + memory, read_len))\ - {\ - uint8_t output[128];\ - int len = read_len / 2; /* is_UTF16LE will only return true if read_len is even */\ - for (int i = 0; i < len; ++i)\ - output[i] = memory[read_ptr + i * 2];\ - hookCtx.result.exitReason = std::string((const char*)(output), (size_t)len);\ - } else\ - hookCtx.result.exitReason = std::string((const char*)(memory + read_ptr), (size_t)read_len);\ - }\ - hookCtx.result.exitType = exit_type;\ - hookCtx.result.exitCode = error_code;\ - return (exit_type == hook_api::ExitType::ACCEPT ? RC_ACCEPT : RC_ROLLBACK);\ -} namespace hook_float { using namespace hook_api; @@ -551,12 +448,11 @@ hook::apply( >> const& hookParamOverrides, ApplyContext& applyCtx, ripple::AccountID const& account, /* the account the hook is INSTALLED ON not always the otxn account */ - bool callback = false, + bool callback, uint32_t wasmParam, int32_t hookChainPosition) { - HookContext hookCtx = { .applyCtx = applyCtx, @@ -594,39 +490,16 @@ hook::apply( ? std::optional( (*(applyCtx.view().peek( keylet::emitted(applyCtx.tx.getFieldH256(sfTransactionHash))) - )).downcast() - ) + )).downcast()) : std::optional() }; auto const& j = applyCtx.app.journal("View"); - SSVM::VM::Configure cfg; - SSVM::VM::VM vm(cfg); - HookModule env(hookCtx); - vm.registerModule(env); + HookExecutor executor { hookCtx } ; - std::vector params, results; - params.push_back(wasmParam); - - JLOG(j.trace()) - << "HookInfo[" << HC_ACC() << "]: creating wasm instance"; - if (auto result = - vm.runWasmFile( - SSVM::Span(wasm.data(), wasm.size()), (callback ? "cbak" : "hook"), params)) - hookCtx.result.instructionCount = vm.getStatistics().getInstrCount(); - else - { - uint32_t ssvm_error = static_cast(result.error()); - if (ssvm_error > 1) - { - JLOG(j.warn()) - << "HookError[" << HC_ACC() << "]: SSVM error " << ssvm_error; - hookCtx.result.exitType = hook_api::ExitType::WASM_ERROR; - return hookCtx.result; - } - } + executor.executeWasm(wasm.data(), wasm.dize(), callback, wasmParam); JLOG(j.trace()) << "HookInfo[" << HC_ACC() << "]: " <<