From 602c280dd4630bf58d1f1de6ffb4169a964b0685 Mon Sep 17 00:00:00 2001 From: Richard Holland Date: Thu, 16 Jun 2022 09:14:36 +0000 Subject: [PATCH] use txnid instead of emitnonce where seq is not available in applicable transactors --- src/ripple/app/hook/impl/applyHook.cpp | 12 ++++++++++- src/ripple/app/tx/impl/CreateCheck.cpp | 10 +-------- src/ripple/app/tx/impl/CreateOffer.cpp | 11 ++-------- src/ripple/app/tx/impl/Escrow.cpp | 18 +++++++--------- src/ripple/app/tx/impl/NFTokenCreateOffer.cpp | 10 +-------- src/ripple/app/tx/impl/PayChan.cpp | 9 +------- src/ripple/app/tx/impl/Transactor.h | 21 +++++++++++++++---- 7 files changed, 40 insertions(+), 51 deletions(-) diff --git a/src/ripple/app/hook/impl/applyHook.cpp b/src/ripple/app/hook/impl/applyHook.cpp index 59a2b1dcc..6b05a27d6 100644 --- a/src/ripple/app/hook/impl/applyHook.cpp +++ b/src/ripple/app/hook/impl/applyHook.cpp @@ -3035,11 +3035,21 @@ DEFINE_HOOK_FUNCTION( if (hookCtx.emit_nonce_counter > hook_api::max_nonce) return TOO_MANY_NONCES; + + // in some cases the same hook might execute multiple times + // on one txn, therefore we need to pass this information to the nonce + uint32_t flags = 0; + flags |= hookCtx.result.isStrong ? 0b10U: 0; + flags |= hookCtx.result.isCallback ? 0b01U: 0; + flags |= (hookCtx.result.hookChainPosition << 2U); + auto hash = ripple::sha512Half( ripple::HashPrefix::emitTxnNonce, applyCtx.tx.getTransactionID(), hookCtx.emit_nonce_counter++, - hookCtx.result.account + hookCtx.result.account, + hookCtx.result.hookHash, + flags ); hookCtx.nonce_used[hash] = true; diff --git a/src/ripple/app/tx/impl/CreateCheck.cpp b/src/ripple/app/tx/impl/CreateCheck.cpp index 7ead633e7..11c212c79 100644 --- a/src/ripple/app/tx/impl/CreateCheck.cpp +++ b/src/ripple/app/tx/impl/CreateCheck.cpp @@ -176,15 +176,7 @@ CreateCheck::doApply() // Check sequence. For more explanation see comments in SeqProxy.h. std::uint32_t const seq = ctx_.tx.getSeqProxy().value(); - bool hooksEnabled = ctx_.view().rules().enabled(featureHooks); - std::optional emitDetails; - if (hooksEnabled && ctx_.tx.isFieldPresent(sfEmitDetails)) - emitDetails = const_cast(ctx_.tx).getField(sfEmitDetails).downcast(); - - Keylet const checkKeylet = - emitDetails - ? keylet::check(account_, (*emitDetails).getFieldH256(sfEmitNonce)) - : keylet::check(account_, seq); + Keylet const checkKeylet = keylet::check(account_, seqID(ctx_)); auto sleCheck = std::make_shared(checkKeylet); diff --git a/src/ripple/app/tx/impl/CreateOffer.cpp b/src/ripple/app/tx/impl/CreateOffer.cpp index 6852b13ef..fb7d49208 100644 --- a/src/ripple/app/tx/impl/CreateOffer.cpp +++ b/src/ripple/app/tx/impl/CreateOffer.cpp @@ -952,7 +952,7 @@ CreateOffer::applyGuts(Sandbox& sb, Sandbox& sbCancel) if (cancelSequence || offerID) { Keylet cancel = offerID - ? keylet::offer(account_, *offerID) + ? Keylet(ltOFFER, *offerID) : keylet::offer(account_, *cancelSequence); auto const sleCancel = sb.peek(cancel); @@ -1163,15 +1163,8 @@ CreateOffer::applyGuts(Sandbox& sb, Sandbox& sbCancel) } } - std::optional emitDetails; - if (hooksEnabled && ctx_.tx.isFieldPresent(sfEmitDetails)) - emitDetails = const_cast(ctx_.tx).getField(sfEmitDetails).downcast(); - // We need to place the remainder of the offer into its order book. - Keylet offer_index = - emitDetails - ? keylet::offer(account_, (*emitDetails).getFieldH256(sfEmitNonce)) - : keylet::offer(account_, offerSequence); + Keylet offer_index = keylet::offer(account_, seqID(ctx_)); // Add offer to owner's directory. auto const ownerNode = sb.dirInsert( diff --git a/src/ripple/app/tx/impl/Escrow.cpp b/src/ripple/app/tx/impl/Escrow.cpp index 25ba80726..722c7683f 100644 --- a/src/ripple/app/tx/impl/Escrow.cpp +++ b/src/ripple/app/tx/impl/Escrow.cpp @@ -231,8 +231,12 @@ EscrowCreate::doApply() return tecINSUFFICIENT_RESERVE; // Check reserve and funds availability - if (isXRP(amount) && balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp()) - return tecUNFUNDED; + if (isXRP(amount)) + { + if (balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp()) + return tecUNFUNDED; + // pass + } else { // preflight will prevent this ever firing, included @@ -310,15 +314,7 @@ EscrowCreate::doApply() // Create escrow in ledger. Note that we we use the value from the // sequence or ticket. For more explanation see comments in SeqProxy.h. - bool hooksEnabled = ctx_.view().rules().enabled(featureHooks); - std::optional emitDetails; - if (hooksEnabled && ctx_.tx.isFieldPresent(sfEmitDetails)) - emitDetails = const_cast(ctx_.tx).getField(sfEmitDetails).downcast(); - - Keylet const escrowKeylet = - emitDetails - ? keylet::escrow(account, (*emitDetails).getFieldH256(sfEmitNonce)) - : keylet::escrow(account, ctx_.tx.getSeqProxy().value()); + Keylet const escrowKeylet = keylet::escrow(account, seqID(ctx_)); auto const slep = std::make_shared(escrowKeylet); (*slep)[sfAmount] = ctx_.tx[sfAmount]; diff --git a/src/ripple/app/tx/impl/NFTokenCreateOffer.cpp b/src/ripple/app/tx/impl/NFTokenCreateOffer.cpp index c3281fa6c..9a6ea5da4 100644 --- a/src/ripple/app/tx/impl/NFTokenCreateOffer.cpp +++ b/src/ripple/app/tx/impl/NFTokenCreateOffer.cpp @@ -174,15 +174,7 @@ NFTokenCreateOffer::doApply() auto const nftokenID = ctx_.tx[sfNFTokenID]; - bool hooksEnabled = ctx_.view().rules().enabled(featureHooks); - std::optional emitDetails; - if (hooksEnabled && ctx_.tx.isFieldPresent(sfEmitDetails)) - emitDetails = const_cast(ctx_.tx).getField(sfEmitDetails).downcast(); - - Keylet const offerID = - emitDetails - ? keylet::nftoffer(account_, (*emitDetails).getFieldH256(sfEmitNonce)) - : keylet::nftoffer(account_, ctx_.tx.getSeqProxy().value()); + Keylet const offerID = keylet::nftoffer(account_, seqID(ctx_)); // Create the offer: { diff --git a/src/ripple/app/tx/impl/PayChan.cpp b/src/ripple/app/tx/impl/PayChan.cpp index 846cc706d..018c9ab31 100644 --- a/src/ripple/app/tx/impl/PayChan.cpp +++ b/src/ripple/app/tx/impl/PayChan.cpp @@ -362,15 +362,8 @@ PayChanCreate::doApply() // // Note that we we use the value from the sequence or ticket as the // payChan sequence. For more explanation see comments in SeqProxy.h. - bool hooksEnabled = ctx_.view().rules().enabled(featureHooks); - std::optional emitDetails; - if (hooksEnabled && ctx_.tx.isFieldPresent(sfEmitDetails)) - emitDetails = const_cast(ctx_.tx).getField(sfEmitDetails).downcast(); - Keylet const payChanKeylet = - emitDetails - ? keylet::payChan(account, dst, (*emitDetails).getFieldH256(sfEmitNonce)) - : keylet::payChan(account, dst, ctx_.tx.getSeqProxy().value()); + Keylet const payChanKeylet = keylet::payChan(account, dst, seqID(ctx_)); auto const slep = std::make_shared(payChanKeylet); diff --git a/src/ripple/app/tx/impl/Transactor.h b/src/ripple/app/tx/impl/Transactor.h index e06b42587..fc7edaab0 100644 --- a/src/ripple/app/tx/impl/Transactor.h +++ b/src/ripple/app/tx/impl/Transactor.h @@ -20,13 +20,14 @@ #ifndef RIPPLE_APP_TX_TRANSACTOR_H_INCLUDED #define RIPPLE_APP_TX_TRANSACTOR_H_INCLUDED -#include +#include #include #include #include #include #include #include +#include namespace hook { // RH TODO: fix applyHook.h so this prototype isn't needed @@ -186,7 +187,7 @@ public: // Hooks static FeeUnit64 - calculateHookChainFee(ReadView const& view, STTx const& tx, Keylet const& hookKeylet, + calculateHookChainFee(ReadView const& view, STTx const& tx, Keylet const& hookKeylet, bool collectCallsOnly = false); protected: @@ -225,8 +226,8 @@ protected: void - addWeakTSHFromSandbox(detail::ApplyViewBase const& pv); - + addWeakTSHFromSandbox(detail::ApplyViewBase const& pv); + // hooks amendment fields, these are unpopulated and unused unless featureHooks is enabled int executedHookCount_ = 0; // record how many hooks have executed across the whole transactor std::set additionalWeakTSH_; // any TSH that needs weak hook execution at the end @@ -289,6 +290,18 @@ preflight1(PreflightContext const& ctx); NotTEC preflight2(PreflightContext const& ctx); +template +inline +static +std::variant +seqID(C const& ctx_) +{ + if (ctx_.view().rules().enabled(featureHooks) && ctx_.tx.isFieldPresent(sfEmitDetails)) + return ctx_.tx.getTransactionID(); + + return ctx_.tx.getSeqProxy().value(); +} + } // namespace ripple #endif