From c3cf4b5999655ccd70a9f8698decb81c5f6a1bb1 Mon Sep 17 00:00:00 2001 From: Richard Holland Date: Tue, 7 May 2024 14:56:26 +1000 Subject: [PATCH] start of js util_keylet --- src/ripple/app/hook/applyHook.h | 10 ++- src/ripple/app/hook/impl/applyHook.cpp | 111 ++++++++++++++++++++++++- 2 files changed, 119 insertions(+), 2 deletions(-) diff --git a/src/ripple/app/hook/applyHook.h b/src/ripple/app/hook/applyHook.h index 800d97cf8..fe84d8425 100644 --- a/src/ripple/app/hook/applyHook.h +++ b/src/ripple/app/hook/applyHook.h @@ -195,6 +195,13 @@ DECLARE_WASM_FUNCTION( uint32_t d, uint32_t e, uint32_t f); + +DECLARE_JS_FUNCTION( + JSValue, + util_keylet, + JSValue keylet_type, + JSValue keylet_data); + DECLARE_WASM_FUNCNARG(int64_t, etxn_burden); DECLARE_WASM_FUNCTION( int64_t, @@ -1006,13 +1013,14 @@ public: ADD_JS_FUNCTION(util_accid, ctx); ADD_JS_FUNCTION(util_verify, ctx); ADD_JS_FUNCTION(util_sha512h, ctx); + ADD_JS_FUNCTION(util_keylet, ctx); + /* ADD_JS_FUNCTION(sto_validate, ctx); ADD_JS_FUNCTION(sto_subfield, ctx); ADD_JS_FUNCTION(sto_subarray, ctx); ADD_JS_FUNCTION(sto_emplace, ctx); ADD_JS_FUNCTION(sto_erase, ctx); - ADD_JS_FUNCTION(util_keylet, ctx); ADD_JS_FUNCTION(emit, ctx); ADD_JS_FUNCTION(etxn_burden, ctx); diff --git a/src/ripple/app/hook/impl/applyHook.cpp b/src/ripple/app/hook/impl/applyHook.cpp index 0c984c7f9..3fc9d6a16 100644 --- a/src/ripple/app/hook/impl/applyHook.cpp +++ b/src/ripple/app/hook/impl/applyHook.cpp @@ -783,10 +783,22 @@ FromJSString(JSContext* ctx, JSValueConst& v, int max_len) return {len, out}; } +inline +std::optional +FromJSInt(JSContext* ctx, JSValueConst& v) +{ + if (!JS_IsNumber(v)) + return {}; + + int64_t out = 0; + JS_ToInt64(ctx, &out, v); + return out; +} + template inline std::optional -ToJSIntArray(JSContext* ctx, T& vec) +ToJSIntArray(JSContext* ctx, T const& vec) { if (vec.size() > 65535) return {}; @@ -1031,6 +1043,23 @@ serialize_keylet( return 34; } +inline +std::vector +serialize_keylet_vec(ripple::Keylet const& kl) +{ + + std::vector out; + out.reserve(34); + + out.push_back((kl.type >> 8) & 0xFFU); + out.push_back((kl.type >> 0) & 0xFFU); + + for (int i = 0; i < 32; ++i) + out.push_back(kl.key.data()[i]); + + return out; +} + std::optional unserialize_keylet(uint8_t* ptr, uint32_t len) { @@ -3092,6 +3121,86 @@ DEFINE_WASM_FUNCTION(int64_t, slot_float, uint32_t slot_no) WASM_HOOK_TEARDOWN(); } +/* +#define VAR_JSASSIGN(T, V) T& V = argv[_stack++] + +#define DEFINE_JS_FUNCTION(R, F, ...)\ +JSValue hook_api::JSFunction##F(JSContext *ctx, JSValueConst this_val,\ + int argc, JSValueConst *argv)\ +*/ + +DEFINE_JS_FUNCTION( + JSValue, + util_keylet, + JSValue keylet_type_raw, + JSValue dummy_value) /* use JSValueConst* argv & int argc */ +{ + JS_HOOK_SETUP(); + + std::optional kt = FromJSInt(ctx, keylet_type_raw); + + auto const last = keylet_code::LAST_KLTYPE_V1; + + if (!kt.has_value() || *kt == 0 || *kt > last) + returnJS(INVALID_ARGUMENT); + + try + { + switch(*kt) + { + case keylet_code::QUALITY: + { + // looking for a 34 byte keylet and high 32 bits and low 32 bits of quality + // RHTODO: accept optionally a bigint here? + if (argc < 4) + returnJS(INVALID_ARGUMENT); + + auto h = FromJSInt(ctx, argv[2]); + auto l = FromJSInt(ctx, argv[3]); + auto kl = FromJSIntArrayOrHexString(ctx, argv[1], 34); + + if (!h.has_value() || !l.has_value() || !kl.has_value() || kl->size() != 34) + returnJS(INVALID_ARGUMENT); + + // ensure it's a dir keylet or we will fail an assertion + if ((*kl)[0] != 0 || (*kl)[1] != 0x64U) + returnJS(INVALID_ARGUMENT); + + std::optional k = + unserialize_keylet(kl->data(), kl->size()); + + if (!k) + returnJS(NO_SUCH_KEYLET); + + uint64_t arg = (((uint64_t)(*h)) << 32U) + ((uint64_t)(*l)); + + auto kl_out = ToJSIntArray(ctx, + serialize_keylet_vec(ripple::keylet::quality(*k, arg))); + + if (!kl_out.has_value()) + returnJS(INTERNAL_ERROR); + + return *kl_out; + + } + + default: + { + returnJS(INTERNAL_ERROR); + } + } + } + catch (std::exception& e) + { + JLOG(j.warn()) << "HookError[" << HC_ACC() << "]: Keylet (JS) exception " + << e.what(); + returnJS(INTERNAL_ERROR); + } + + JS_HOOK_TEARDOWN(); +} + + DEFINE_WASM_FUNCTION( int64_t, util_keylet,