use txnid instead of emitnonce where seq is not available in applicable transactors

This commit is contained in:
Richard Holland
2022-06-16 09:14:36 +00:00
parent d3f6c4ef2d
commit 602c280dd4
7 changed files with 40 additions and 51 deletions

View File

@@ -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;

View File

@@ -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<STObject> emitDetails;
if (hooksEnabled && ctx_.tx.isFieldPresent(sfEmitDetails))
emitDetails = const_cast<ripple::STTx&>(ctx_.tx).getField(sfEmitDetails).downcast<STObject>();
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<SLE>(checkKeylet);

View File

@@ -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<STObject> emitDetails;
if (hooksEnabled && ctx_.tx.isFieldPresent(sfEmitDetails))
emitDetails = const_cast<ripple::STTx&>(ctx_.tx).getField(sfEmitDetails).downcast<STObject>();
// 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(

View File

@@ -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<STObject> emitDetails;
if (hooksEnabled && ctx_.tx.isFieldPresent(sfEmitDetails))
emitDetails = const_cast<ripple::STTx&>(ctx_.tx).getField(sfEmitDetails).downcast<STObject>();
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<SLE>(escrowKeylet);
(*slep)[sfAmount] = ctx_.tx[sfAmount];

View File

@@ -174,15 +174,7 @@ NFTokenCreateOffer::doApply()
auto const nftokenID = ctx_.tx[sfNFTokenID];
bool hooksEnabled = ctx_.view().rules().enabled(featureHooks);
std::optional<STObject> emitDetails;
if (hooksEnabled && ctx_.tx.isFieldPresent(sfEmitDetails))
emitDetails = const_cast<ripple::STTx&>(ctx_.tx).getField(sfEmitDetails).downcast<STObject>();
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:
{

View File

@@ -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<STObject> emitDetails;
if (hooksEnabled && ctx_.tx.isFieldPresent(sfEmitDetails))
emitDetails = const_cast<ripple::STTx&>(ctx_.tx).getField(sfEmitDetails).downcast<STObject>();
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<SLE>(payChanKeylet);

View File

@@ -20,13 +20,14 @@
#ifndef RIPPLE_APP_TX_TRANSACTOR_H_INCLUDED
#define RIPPLE_APP_TX_TRANSACTOR_H_INCLUDED
#include <ripple/app/hook/applyHook.h>
#include <ripple/app/hook/applyHook.h>
#include <ripple/app/tx/applySteps.h>
#include <ripple/app/tx/impl/ApplyContext.h>
#include <ripple/basics/XRPAmount.h>
#include <ripple/beast/utility/Journal.h>
#include <ripple/ledger/PaymentSandbox.h>
#include <ripple/ledger/detail/ApplyViewBase.h>
#include <variant>
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<AccountID> 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<class C>
inline
static
std::variant<uint32_t, uint256>
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