mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
further conversion to wasmedge, still not compiling
This commit is contained in:
@@ -13,7 +13,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <ripple/protocol/digest.h>
|
#include <ripple/protocol/digest.h>
|
||||||
#include <wasmedge.h>
|
#include <wasmedge.h>
|
||||||
#include <ripple/app/tx/impl/applyHookMacro.h>
|
#include <ripple/app/tx/applyHookMacro.h>
|
||||||
|
|
||||||
namespace hook {
|
namespace hook {
|
||||||
struct HookContext;
|
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,
|
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 kread_ptr, uint32_t kread_len,
|
||||||
uint32_t hread_ptr, uint32_t hread_len);
|
uint32_t hread_ptr, uint32_t hread_len);
|
||||||
|
|
||||||
DECLARE_HOOK_FUNCTION(int64_t, hook_param, uint32_t write_ptr, uint32_t write_len,
|
DECLARE_HOOK_FUNCTION(int64_t, hook_param, uint32_t write_ptr, uint32_t write_len,
|
||||||
uint32_t read_ptr, uint32_t read_len);
|
uint32_t read_ptr, uint32_t read_len);
|
||||||
|
|
||||||
@@ -247,26 +247,26 @@ namespace hook {
|
|||||||
|
|
||||||
struct HookResult;
|
struct HookResult;
|
||||||
|
|
||||||
HookResult apply(
|
hook::apply(
|
||||||
ripple::uint256 const&,
|
ripple::uint256 const& hookSetTxnID, /* this is the txid of the sethook, used for caching (one day) */
|
||||||
ripple::uint256 const&,
|
ripple::uint256 const& hookHash, /* hash of the actual hook byte code, used for metadata */
|
||||||
ripple::uint256 const&,
|
ripple::uint256 const& hookNamespace,
|
||||||
ripple::Blob const&,
|
ripple::Blob const& wasm,
|
||||||
|
std::map<
|
||||||
|
std::vector<uint8_t>, /* param name */
|
||||||
|
std::vector<uint8_t> /* param value */
|
||||||
|
> const& hookParams,
|
||||||
|
std::map<
|
||||||
|
ripple::uint256, /* hook hash */
|
||||||
std::map<
|
std::map<
|
||||||
std::vector<uint8_t>, /* param name */
|
std::vector<uint8_t>,
|
||||||
std::vector<uint8_t> /* param value */
|
std::vector<uint8_t>
|
||||||
> const& parameters,
|
>> const& hookParamOverrides,
|
||||||
std::map<
|
ripple::ApplyContext& applyCtx,
|
||||||
ripple::uint256,
|
ripple::AccountID const& account, /* the account the hook is INSTALLED ON not always the otxn account */
|
||||||
std::map<
|
bool callback = false,
|
||||||
std::vector<uint8_t>, /* param name */
|
uint32_t wasmParam = 0,
|
||||||
std::vector<uint8_t> /* param value */
|
int32_t hookChainPosition = -1);
|
||||||
>> const& parameterOverrides,
|
|
||||||
ripple::ApplyContext&,
|
|
||||||
ripple::AccountID const&,
|
|
||||||
bool callback,
|
|
||||||
uint32_t wasmParam = 0,
|
|
||||||
int32_t hookChainPosition = -1);
|
|
||||||
|
|
||||||
struct HookContext;
|
struct HookContext;
|
||||||
|
|
||||||
@@ -376,12 +376,15 @@ namespace hook {
|
|||||||
// create these once at boot and keep them
|
// create these once at boot and keep them
|
||||||
WasmEdge_String exportName = WasmEdge_StringCreateByCString("env");
|
WasmEdge_String exportName = WasmEdge_StringCreateByCString("env");
|
||||||
WasmEdge_String tableName = WasmEdge_StringCreateByCString("table");
|
WasmEdge_String tableName = WasmEdge_StringCreateByCString("table");
|
||||||
WasmEdge_TableTypeContext* tableType =
|
WasmEdge_TableTypeContext* tableType =
|
||||||
WasmEdge_TableTypeCreate(WasmEdge_RefType_FuncRef, {.HasMax = true, .Min = 10, .Max = 20});
|
WasmEdge_TableTypeCreate(WasmEdge_RefType_FuncRef, {.HasMax = true, .Min = 10, .Max = 20});
|
||||||
WasmEdge_MemoryTypeContext* memType =
|
WasmEdge_MemoryTypeContext* memType =
|
||||||
WasmEdge_MemoryTypeCreate({.HasMax = true, .Min = 1, .Max = 1});
|
WasmEdge_MemoryTypeCreate({.HasMax = true, .Min = 1, .Max = 1});
|
||||||
WasmEdge_String memName = WasmEdge_StringCreateByCString("memory");
|
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
|
// RH TODO: call destruct for these on rippled shutdown
|
||||||
|
|
||||||
#define ADD_HOOK_FUNCTION(F, ctx)\
|
#define ADD_HOOK_FUNCTION(F, ctx)\
|
||||||
@@ -391,19 +394,102 @@ namespace hook {
|
|||||||
WasmEdge_ImportObjectAddFunction(importObj, WasmFunctionName##F, hf);\
|
WasmEdge_ImportObjectAddFunction(importObj, WasmFunctionName##F, hf);\
|
||||||
}
|
}
|
||||||
|
|
||||||
class HookModule
|
#define HR_ACC() hookResult.account << "-" << hookResult.otxnAccount
|
||||||
{
|
#define HC_ACC() hookCtx.result.account << "-" << hookCtx.result.otxnAccount
|
||||||
//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;
|
|
||||||
|
|
||||||
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;
|
ctx.module = this;
|
||||||
|
|
||||||
WasmEdge_ImportObjectContext* importObj = WasmEdge_ImportObjectCreate(exportName);
|
|
||||||
ADD_HOOK_FUNCTION(_g, ctx);
|
ADD_HOOK_FUNCTION(_g, ctx);
|
||||||
ADD_HOOK_FUNCTION(accept, ctx);
|
ADD_HOOK_FUNCTION(accept, ctx);
|
||||||
ADD_HOOK_FUNCTION(rollback, ctx);
|
ADD_HOOK_FUNCTION(rollback, ctx);
|
||||||
@@ -447,8 +533,6 @@ namespace hook {
|
|||||||
ADD_HOOK_FUNCTION(float_sign_set, ctx);
|
ADD_HOOK_FUNCTION(float_sign_set, ctx);
|
||||||
ADD_HOOK_FUNCTION(float_int, ctx);
|
ADD_HOOK_FUNCTION(float_int, ctx);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ADD_HOOK_FUNCTION(otxn_burden, ctx);
|
ADD_HOOK_FUNCTION(otxn_burden, ctx);
|
||||||
ADD_HOOK_FUNCTION(otxn_generation, ctx);
|
ADD_HOOK_FUNCTION(otxn_generation, ctx);
|
||||||
ADD_HOOK_FUNCTION(otxn_field_txt, ctx);
|
ADD_HOOK_FUNCTION(otxn_field_txt, ctx);
|
||||||
@@ -494,7 +578,11 @@ namespace hook {
|
|||||||
WasmEdge_MemoryInstanceContext* hostMem = WasmEdge_MemoryInstanceCreate(memType);
|
WasmEdge_MemoryInstanceContext* hostMem = WasmEdge_MemoryInstanceCreate(memType);
|
||||||
WasmEdge_ImportObjectAddMemory(importObj, memName, hostMem);
|
WasmEdge_ImportObjectAddMemory(importObj, memName, hostMem);
|
||||||
}
|
}
|
||||||
virtual ~HookModule() = default;
|
|
||||||
|
~HookModule()
|
||||||
|
{
|
||||||
|
WasmEdge_ImportObjectDelete(importObj);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,16 +31,16 @@
|
|||||||
#define DELIM_2 ;
|
#define DELIM_2 ;
|
||||||
#define DELIM(S) DELIM_##S
|
#define DELIM(S) DELIM_##S
|
||||||
|
|
||||||
#define FOR_VAR_1(T, D) SEP(T, D)
|
#define FOR_VAR_1(T, S, 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_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, a) DELIM(S) FOR_VAR_2(T, S, __VA_ARGS__)
|
#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, a) DELIM(S) FOR_VAR_3(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, a) DELIM(S) FOR_VAR_4(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, a) DELIM(S) FOR_VAR_5(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, a) DELIM(S) FOR_VAR_6(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, a) DELIM(S) FOR_VAR_7(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, a) DELIM(S) FOR_VAR_8(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, a) DELIM(S) FOR_VAR_9(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, ...)\
|
#define FOR_VARS(T, S, ...)\
|
||||||
DEFER(CAT(FOR_VAR_,VA_NARGS(NULL, __VA_ARGS__))CAT(LPAREN T COMMA S COMMA OBSTRUCT(__VA_ARGS__) RPAREN))
|
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)
|
CAT2(TYP_,T)
|
||||||
|
|
||||||
#define DECLARE_HOOK_FUNCTION(R, F, ...)\
|
#define DECLARE_HOOK_FUNCTION(R, F, ...)\
|
||||||
|
R F(hook::HookContext& hookCtx, WasmEdge_MemoryInstanceContext& memoryCtx, __VA_ARGS__);\
|
||||||
WasmEdge_Result WasmFunction##F(\
|
WasmEdge_Result WasmFunction##F(\
|
||||||
void *data_ptr, WasmEdge_MemoryInstanceContext *memCtx,\
|
void *data_ptr, WasmEdge_MemoryInstanceContext *memCtx,\
|
||||||
const WasmEdge_Value *in, WasmEdge_Value *out)\
|
const WasmEdge_Value *in, WasmEdge_Value *out)\
|
||||||
@@ -88,16 +89,16 @@
|
|||||||
out[0] = RET_ASSIGN(R, return_code);\
|
out[0] = RET_ASSIGN(R, return_code);\
|
||||||
return WasmEdge_Result_Success;\
|
return WasmEdge_Result_Success;\
|
||||||
};\
|
};\
|
||||||
WasmEdge_FunctionTypeContext* WasmFunctionType##F = NULL;\
|
WasmEdge_ValType WasmFunctionParams##F[] = { FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__) };\
|
||||||
{\
|
WasmEdge_ValType WasmFunctionResult##F[1] = { WASM_VAL_TYPE(R, dummy) };\
|
||||||
enum WasmEdge_ValType r = { WASM_VAL_TYPE(R, dummy) };\
|
WasmEdge_FunctionTypeContext* WasmFunctionType##F = WasmEdge_FunctionTypeCreate(\
|
||||||
enum WasmEdge_ValType p = { FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__) };\
|
WasmFunctionParams##F, VA_NARGS(NULL, __VA_ARGS__),\
|
||||||
WasmFunctionType##F = WasmEdge_FunctionTypeCreate(p, VA_NARGS(NULL, __VA_ARGS__), r, 1);\
|
WasmFunctionResult##F, 1);\
|
||||||
};\
|
|
||||||
WasmEdge_String WasmFunctionName##F = WasmEdge_StringCreateByCString(#F);
|
WasmEdge_String WasmFunctionName##F = WasmEdge_StringCreateByCString(#F);
|
||||||
|
|
||||||
|
|
||||||
#define DECLARE_HOOK_FUNCNARG(R, F)\
|
#define DECLARE_HOOK_FUNCNARG(R, F)\
|
||||||
|
R F(hook::HookContext& hookCtx, WasmEdge_MemoryInstanceContext& memoryCtx);\
|
||||||
WasmEdge_Result WasmFunction_##F(\
|
WasmEdge_Result WasmFunction_##F(\
|
||||||
void *data_ptr, WasmEdge_MemoryInstanceContext *memCtx,\
|
void *data_ptr, WasmEdge_MemoryInstanceContext *memCtx,\
|
||||||
const WasmEdge_Value *in, WasmEdge_Value *out)\
|
const WasmEdge_Value *in, WasmEdge_Value *out)\
|
||||||
@@ -106,15 +107,12 @@
|
|||||||
R return_code = hook_api::F(*hookCtx, *memCtx);\
|
R return_code = hook_api::F(*hookCtx, *memCtx);\
|
||||||
if (return_code == RC_ROLLBACK || return_code == RC_ACCEPT)\
|
if (return_code == RC_ROLLBACK || return_code == RC_ACCEPT)\
|
||||||
return WasmEdge_Result_Terminate;\
|
return WasmEdge_Result_Terminate;\
|
||||||
Out[0] = CAT2(RET_,R(return_code));\
|
out[0] = CAT2(RET_,R(return_code));\
|
||||||
return WasmEdge_Result_Success;\
|
return WasmEdge_Result_Success;\
|
||||||
};\
|
};\
|
||||||
WasmEdge_FunctionTypeContext* WasmFunctionType##F = NULL;\
|
WasmEdge_ValType WasmFunctionResult##F[1] = { WASM_VAL_TYPE(R, dummy) };\
|
||||||
{\
|
WasmEdge_FunctionTypeContext* WasmFunctionType##F = \
|
||||||
enum WasmEdge_ValType r = { WASM_VAL_TYPE(R, dummy) };\
|
WasmEdge_FunctionTypeCreate({}, 0, WasmFunctionResult##F, 1);\
|
||||||
enum WasmEdge_ValType p = { };\
|
|
||||||
WasmFunctionType##F = WasmEdge_FunctionTypeCreate(p, 0, r, 1);\
|
|
||||||
}\
|
|
||||||
WasmEdge_String WasmFunctionName##F = WasmEdge_StringCreateByCString(#F);
|
WasmEdge_String WasmFunctionName##F = WasmEdge_StringCreateByCString(#F);
|
||||||
|
|
||||||
#define DEFINE_HOOK_FUNCTION(R, F, ...)\
|
#define DEFINE_HOOK_FUNCTION(R, F, ...)\
|
||||||
@@ -123,3 +121,107 @@
|
|||||||
#define DEFINE_HOOK_FUNCNARG(R, F)\
|
#define DEFINE_HOOK_FUNCNARG(R, F)\
|
||||||
R hook_api::F(hook::HookContext& hookCtx, WasmEdge_MemoryInstanceContext& memoryCtx)
|
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<int64_t>(host_src_len), static_cast<int64_t>(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<uint64_t>(ptr) + static_cast<uint64_t>(len) > static_cast<uint64_t>(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);\
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,110 +19,7 @@
|
|||||||
|
|
||||||
using namespace ripple;
|
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<uint8_t*>(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<int64_t>(host_src_len), static_cast<int64_t>(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>((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<uint64_t>(ptr) + static_cast<uint64_t>(len) > static_cast<uint64_t>(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
|
namespace hook_float
|
||||||
{
|
{
|
||||||
using namespace hook_api;
|
using namespace hook_api;
|
||||||
@@ -551,12 +448,11 @@ hook::apply(
|
|||||||
>> const& hookParamOverrides,
|
>> const& hookParamOverrides,
|
||||||
ApplyContext& applyCtx,
|
ApplyContext& applyCtx,
|
||||||
ripple::AccountID const& account, /* the account the hook is INSTALLED ON not always the otxn account */
|
ripple::AccountID const& account, /* the account the hook is INSTALLED ON not always the otxn account */
|
||||||
bool callback = false,
|
bool callback,
|
||||||
uint32_t wasmParam,
|
uint32_t wasmParam,
|
||||||
int32_t hookChainPosition)
|
int32_t hookChainPosition)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
HookContext hookCtx =
|
HookContext hookCtx =
|
||||||
{
|
{
|
||||||
.applyCtx = applyCtx,
|
.applyCtx = applyCtx,
|
||||||
@@ -594,39 +490,16 @@ hook::apply(
|
|||||||
? std::optional<ripple::STObject>(
|
? std::optional<ripple::STObject>(
|
||||||
(*(applyCtx.view().peek(
|
(*(applyCtx.view().peek(
|
||||||
keylet::emitted(applyCtx.tx.getFieldH256(sfTransactionHash)))
|
keylet::emitted(applyCtx.tx.getFieldH256(sfTransactionHash)))
|
||||||
)).downcast<STObject>()
|
)).downcast<STObject>())
|
||||||
)
|
|
||||||
: std::optional<ripple::STObject>()
|
: std::optional<ripple::STObject>()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
auto const& j = applyCtx.app.journal("View");
|
auto const& j = applyCtx.app.journal("View");
|
||||||
|
|
||||||
SSVM::VM::Configure cfg;
|
HookExecutor executor { hookCtx } ;
|
||||||
SSVM::VM::VM vm(cfg);
|
|
||||||
HookModule env(hookCtx);
|
|
||||||
vm.registerModule(env);
|
|
||||||
|
|
||||||
std::vector<SSVM::ValVariant> params, results;
|
executor.executeWasm(wasm.data(), wasm.dize(), callback, wasmParam);
|
||||||
params.push_back(wasmParam);
|
|
||||||
|
|
||||||
JLOG(j.trace())
|
|
||||||
<< "HookInfo[" << HC_ACC() << "]: creating wasm instance";
|
|
||||||
if (auto result =
|
|
||||||
vm.runWasmFile(
|
|
||||||
SSVM::Span<const uint8_t>(wasm.data(), wasm.size()), (callback ? "cbak" : "hook"), params))
|
|
||||||
hookCtx.result.instructionCount = vm.getStatistics().getInstrCount();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t ssvm_error = static_cast<uint32_t>(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JLOG(j.trace()) <<
|
JLOG(j.trace()) <<
|
||||||
"HookInfo[" << HC_ACC() << "]: " <<
|
"HookInfo[" << HC_ACC() << "]: " <<
|
||||||
|
|||||||
Reference in New Issue
Block a user