diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index 88fb78564..16829a32b 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -215,7 +215,8 @@ namespace hook_api TOO_MANY_PARAMS = -36, INVALID_TXN = -37, RESERVE_INSUFFICIENT = -38, // setting a new state object would exceed account reserve - COMPLEX_NOT_SUPPORTED = -39 + COMPLEX_NOT_SUPPORTED = -39, + DOES_NOT_MATCH = -40, // two keylets were required to be the same type but werent }; @@ -244,6 +245,7 @@ namespace hook_api "etxn_fee_base", "etxn_generation", "etxn_reserve", + "etxn_nonce", "float_compare", "float_divide", "float_exponent", @@ -271,8 +273,8 @@ namespace hook_api "ledger_seq", "ledger_last_hash", "ledger_last_time", - "etxn_nonce", "ledger_nonce", + "ledger_keylet", "otxn_burden", "otxn_field", "otxn_slot", diff --git a/src/ripple/app/hook/applyHook.h b/src/ripple/app/hook/applyHook.h index 3ed40e355..feb927a0f 100644 --- a/src/ripple/app/hook/applyHook.h +++ b/src/ripple/app/hook/applyHook.h @@ -162,6 +162,9 @@ namespace hook_api DECLARE_HOOK_FUNCTION(int64_t, ledger_last_hash, uint32_t write_ptr, uint32_t write_len ); DECLARE_HOOK_FUNCTION(int64_t, ledger_nonce, uint32_t write_ptr, uint32_t write_len ); + DECLARE_HOOK_FUNCTION(int64_t, ledger_keylet, uint32_t write_ptr, uint32_t write_len, + uint32_t lread_ptr, uint32_t lread_len, + uint32_t hread_ptr, uint32_t hread_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, @@ -583,6 +586,7 @@ namespace hook ADD_HOOK_FUNCTION(ledger_last_hash, ctx); ADD_HOOK_FUNCTION(ledger_last_time, ctx); ADD_HOOK_FUNCTION(ledger_nonce, ctx); + ADD_HOOK_FUNCTION(ledger_keylet, ctx); ADD_HOOK_FUNCTION(hook_param, ctx); ADD_HOOK_FUNCTION(hook_param_set, ctx); diff --git a/src/ripple/app/hook/impl/applyHook.cpp b/src/ripple/app/hook/impl/applyHook.cpp index b3985e8e3..2c403a6e3 100644 --- a/src/ripple/app/hook/impl/applyHook.cpp +++ b/src/ripple/app/hook/impl/applyHook.cpp @@ -2938,6 +2938,48 @@ DEFINE_HOOK_FUNCTION( return 32; } +DEFINE_HOOK_FUNCTION( + int64_t, + ledger_keylet, + uint32_t write_ptr, uint32_t write_len, + uint32_t lread_ptr, uint32_t lread_len, + uint32_t hread_ptr, uint32_t hread_len ) +{ + HOOK_SETUP(); + + if (NOT_IN_BOUNDS(write_ptr, write_len, memory_length) || + NOT_IN_BOUNDS(lread_ptr, lread_len, memory_length) || + NOT_IN_BOUNDS(hread_ptr, hread_len, memory_length)) + return OUT_OF_BOUNDS; + + if (lread_len < 34U || hread_len < 34U || write_len < 34U) + return TOO_SMALL; + if (lread_len > 34U || hread_len > 34U || write_len > 34U) + return TOO_BIG; + + std::optional klLo = unserialize_keylet(memory + lread_ptr, lread_len); + if (!klLo) + return INVALID_ARGUMENT; + + std::optional klHi = unserialize_keylet(memory + hread_ptr, hread_len); + if (!klHi) + return INVALID_ARGUMENT; + + // keylets must be the same type! + if ((*klLo).type != (*klHi).type) + return DOES_NOT_MATCH; + + std::optional found = + view.succ((*klLo).key, (*klHi).key.next()); + + if (!found) + return DOESNT_EXIST; + + Keylet kl_out{(*klLo).type, *found}; + + return serialize_keylet(kl_out, memory, write_ptr, write_len); +} + // Reserve one or more transactions for emission from the running hook DEFINE_HOOK_FUNCTION( int64_t, diff --git a/src/ripple/app/tx/impl/SetHook.cpp b/src/ripple/app/tx/impl/SetHook.cpp index e60958713..25f5df595 100644 --- a/src/ripple/app/tx/impl/SetHook.cpp +++ b/src/ripple/app/tx/impl/SetHook.cpp @@ -602,6 +602,15 @@ SetHook::preflight(PreflightContext const& ctx) return temMALFORMED; } + if (hookSetObj->isFieldPresent(sfCreateCode) && + hookSetObj->getFieldVL(sfCreateCode).size() > hook::maxHookWasmSize()) + { + JLOG(ctx.j.trace()) + << "HookSet(" << hook::log::WASM_TOO_BIG << ")[" << HS_ACC() + << "]: Malformed transaction: SetHook operation would create blob larger than max"; + return temMALFORMED; + } + if (hookSetObj->getCount() == 0) // skip blanks continue;