diff --git a/src/ripple/app/hook/HookAPI.h b/src/ripple/app/hook/HookAPI.h index e507f9c3a..5d55ef7d9 100644 --- a/src/ripple/app/hook/HookAPI.h +++ b/src/ripple/app/hook/HookAPI.h @@ -239,8 +239,11 @@ public: // trace_num // trace_float - // meta_slot - // xpop_slot + Expected + meta_slot(uint32_t slot_into) const; + + Expected, HookReturnCode> + xpop_slot(uint32_t slot_into_tx, uint32_t slot_into_meta) const; private: HookContext& hookCtx; diff --git a/src/ripple/app/hook/impl/HookAPI.cpp b/src/ripple/app/hook/impl/HookAPI.cpp index d35bfc3cc..3662b6a1b 100644 --- a/src/ripple/app/hook/impl/HookAPI.cpp +++ b/src/ripple/app/hook/impl/HookAPI.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -1950,8 +1951,100 @@ HookAPI::slot_float(uint32_t slot_no) const // trace_num // trace_float -// meta_slot -// xpop_slot +Expected +HookAPI::meta_slot(uint32_t slot_into) const +{ + if (!hookCtx.result.provisionalMeta) + return Unexpected(PREREQUISITE_NOT_MET); + + if (slot_into > hook_api::max_slots) + return Unexpected(INVALID_ARGUMENT); + + // check if we can emplace the object to a slot + if (slot_into == 0 && no_free_slots()) + return Unexpected(NO_FREE_SLOTS); + + if (slot_into == 0) + { + if (auto found = get_free_slot(); found) + slot_into = *found; + else + return Unexpected(NO_FREE_SLOTS); + } + + hookCtx.slot[slot_into] = + hook::SlotEntry{.storage = hookCtx.result.provisionalMeta, .entry = 0}; + + hookCtx.slot[slot_into].entry = &(*hookCtx.slot[slot_into].storage); + + return slot_into; +} + +Expected, HookReturnCode> +HookAPI::xpop_slot(uint32_t slot_into_tx, uint32_t slot_into_meta) const +{ + if (hookCtx.applyCtx.tx.getFieldU16(sfTransactionType) != ttIMPORT) + return Unexpected(PREREQUISITE_NOT_MET); + + if (slot_into_tx > hook_api::max_slots || + slot_into_meta > hook_api::max_slots) + return Unexpected(INVALID_ARGUMENT); + + size_t free_count = hook_api::max_slots - hookCtx.slot.size(); + + size_t needed_count = slot_into_tx == 0 && slot_into_meta == 0 + ? 2 + : slot_into_tx != 0 && slot_into_meta != 0 ? 0 : 1; + + if (free_count < needed_count) + return Unexpected(NO_FREE_SLOTS); + + // if they supply the same slot number for both (other than 0) + // they will produce a collision + if (needed_count == 0 && slot_into_tx == slot_into_meta) + return Unexpected(INVALID_ARGUMENT); + + if (slot_into_tx == 0) + { + if (no_free_slots()) + return Unexpected(NO_FREE_SLOTS); + + if (auto found = get_free_slot(); found) + slot_into_tx = *found; + else + return Unexpected(NO_FREE_SLOTS); + } + + if (slot_into_meta == 0) + { + if (no_free_slots()) + return Unexpected(NO_FREE_SLOTS); + + if (auto found = get_free_slot(); found) + slot_into_meta = *found; + else + return Unexpected(NO_FREE_SLOTS); + } + + auto [tx, meta] = + Import::getInnerTxn(hookCtx.applyCtx.tx, hookCtx.applyCtx.journal); + + if (!tx || !meta) + return Unexpected(INVALID_TXN); + + hookCtx.slot[slot_into_tx] = + hook::SlotEntry{.storage = std::move(tx), .entry = 0}; + + hookCtx.slot[slot_into_tx].entry = &(*hookCtx.slot[slot_into_tx].storage); + + hookCtx.slot[slot_into_meta] = + hook::SlotEntry{.storage = std::move(meta), .entry = 0}; + + hookCtx.slot[slot_into_meta].entry = + &(*hookCtx.slot[slot_into_meta].storage); + + return std::make_pair(slot_into_tx, slot_into_meta); +} /// private diff --git a/src/ripple/app/hook/impl/applyHook.cpp b/src/ripple/app/hook/impl/applyHook.cpp index f5acb508e..e54514f5a 100644 --- a/src/ripple/app/hook/impl/applyHook.cpp +++ b/src/ripple/app/hook/impl/applyHook.cpp @@ -4586,30 +4586,12 @@ DEFINE_HOOK_FUNCTION(int64_t, meta_slot, uint32_t slot_into) { HOOK_SETUP(); - if (!hookCtx.result.provisionalMeta) - return PREREQUISITE_NOT_MET; + hook::HookAPI api(hookCtx); + auto const result = api.meta_slot(slot_into); + if (!result) + return result.error(); - if (slot_into > hook_api::max_slots) - return INVALID_ARGUMENT; - - // check if we can emplace the object to a slot - if (slot_into == 0 && no_free_slots(hookCtx)) - return NO_FREE_SLOTS; - - if (slot_into == 0) - { - if (auto found = get_free_slot(hookCtx); found) - slot_into = *found; - else - return NO_FREE_SLOTS; - } - - hookCtx.slot[slot_into] = - hook::SlotEntry{.storage = hookCtx.result.provisionalMeta, .entry = 0}; - - hookCtx.slot[slot_into].entry = &(*hookCtx.slot[slot_into].storage); - - return slot_into; + return result.value(); HOOK_TEARDOWN(); } @@ -4622,66 +4604,12 @@ DEFINE_HOOK_FUNCTION( { HOOK_SETUP(); - if (applyCtx.tx.getFieldU16(sfTransactionType) != ttIMPORT) - return PREREQUISITE_NOT_MET; + hook::HookAPI api(hookCtx); + auto const result = api.xpop_slot(slot_into_tx, slot_into_meta); + if (!result) + return result.error(); - if (slot_into_tx > hook_api::max_slots || - slot_into_meta > hook_api::max_slots) - return INVALID_ARGUMENT; - - size_t free_count = hook_api::max_slots - hookCtx.slot.size(); - - size_t needed_count = slot_into_tx == 0 && slot_into_meta == 0 - ? 2 - : slot_into_tx != 0 && slot_into_meta != 0 ? 0 : 1; - - if (free_count < needed_count) - return NO_FREE_SLOTS; - - // if they supply the same slot number for both (other than 0) - // they will produce a collision - if (needed_count == 0 && slot_into_tx == slot_into_meta) - return INVALID_ARGUMENT; - - if (slot_into_tx == 0) - { - if (no_free_slots(hookCtx)) - return NO_FREE_SLOTS; - - if (auto found = get_free_slot(hookCtx); found) - slot_into_tx = *found; - else - return NO_FREE_SLOTS; - } - - if (slot_into_meta == 0) - { - if (no_free_slots(hookCtx)) - return NO_FREE_SLOTS; - - if (auto found = get_free_slot(hookCtx); found) - slot_into_meta = *found; - else - return NO_FREE_SLOTS; - } - - auto [tx, meta] = Import::getInnerTxn(applyCtx.tx, j); - - if (!tx || !meta) - return INVALID_TXN; - - hookCtx.slot[slot_into_tx] = - hook::SlotEntry{.storage = std::move(tx), .entry = 0}; - - hookCtx.slot[slot_into_tx].entry = &(*hookCtx.slot[slot_into_tx].storage); - - hookCtx.slot[slot_into_meta] = - hook::SlotEntry{.storage = std::move(meta), .entry = 0}; - - hookCtx.slot[slot_into_meta].entry = - &(*hookCtx.slot[slot_into_meta].storage); - - return (slot_into_tx << 16U) + slot_into_meta; + return std::get<0>(result.value()) << 16U | std::get<1>(result.value()); HOOK_TEARDOWN(); }