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) if (hookCtx.emit_nonce_counter > hook_api::max_nonce)
return TOO_MANY_NONCES; 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( auto hash = ripple::sha512Half(
ripple::HashPrefix::emitTxnNonce, ripple::HashPrefix::emitTxnNonce,
applyCtx.tx.getTransactionID(), applyCtx.tx.getTransactionID(),
hookCtx.emit_nonce_counter++, hookCtx.emit_nonce_counter++,
hookCtx.result.account hookCtx.result.account,
hookCtx.result.hookHash,
flags
); );
hookCtx.nonce_used[hash] = true; hookCtx.nonce_used[hash] = true;

View File

@@ -176,15 +176,7 @@ CreateCheck::doApply()
// Check sequence. For more explanation see comments in SeqProxy.h. // Check sequence. For more explanation see comments in SeqProxy.h.
std::uint32_t const seq = ctx_.tx.getSeqProxy().value(); std::uint32_t const seq = ctx_.tx.getSeqProxy().value();
bool hooksEnabled = ctx_.view().rules().enabled(featureHooks); Keylet const checkKeylet = keylet::check(account_, seqID(ctx_));
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);
auto sleCheck = std::make_shared<SLE>(checkKeylet); auto sleCheck = std::make_shared<SLE>(checkKeylet);

View File

@@ -952,7 +952,7 @@ CreateOffer::applyGuts(Sandbox& sb, Sandbox& sbCancel)
if (cancelSequence || offerID) if (cancelSequence || offerID)
{ {
Keylet cancel = offerID Keylet cancel = offerID
? keylet::offer(account_, *offerID) ? Keylet(ltOFFER, *offerID)
: keylet::offer(account_, *cancelSequence); : keylet::offer(account_, *cancelSequence);
auto const sleCancel = sb.peek(cancel); 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. // We need to place the remainder of the offer into its order book.
Keylet offer_index = Keylet offer_index = keylet::offer(account_, seqID(ctx_));
emitDetails
? keylet::offer(account_, (*emitDetails).getFieldH256(sfEmitNonce))
: keylet::offer(account_, offerSequence);
// Add offer to owner's directory. // Add offer to owner's directory.
auto const ownerNode = sb.dirInsert( auto const ownerNode = sb.dirInsert(

View File

@@ -231,8 +231,12 @@ EscrowCreate::doApply()
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
// Check reserve and funds availability // Check reserve and funds availability
if (isXRP(amount) && balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp()) if (isXRP(amount))
return tecUNFUNDED; {
if (balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp())
return tecUNFUNDED;
// pass
}
else else
{ {
// preflight will prevent this ever firing, included // 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 // Create escrow in ledger. Note that we we use the value from the
// sequence or ticket. For more explanation see comments in SeqProxy.h. // sequence or ticket. For more explanation see comments in SeqProxy.h.
bool hooksEnabled = ctx_.view().rules().enabled(featureHooks); Keylet const escrowKeylet = keylet::escrow(account, seqID(ctx_));
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());
auto const slep = std::make_shared<SLE>(escrowKeylet); auto const slep = std::make_shared<SLE>(escrowKeylet);
(*slep)[sfAmount] = ctx_.tx[sfAmount]; (*slep)[sfAmount] = ctx_.tx[sfAmount];

View File

@@ -174,15 +174,7 @@ NFTokenCreateOffer::doApply()
auto const nftokenID = ctx_.tx[sfNFTokenID]; auto const nftokenID = ctx_.tx[sfNFTokenID];
bool hooksEnabled = ctx_.view().rules().enabled(featureHooks); Keylet const offerID = keylet::nftoffer(account_, seqID(ctx_));
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());
// Create the offer: // 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 // Note that we we use the value from the sequence or ticket as the
// payChan sequence. For more explanation see comments in SeqProxy.h. // 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 = Keylet const payChanKeylet = keylet::payChan(account, dst, seqID(ctx_));
emitDetails
? keylet::payChan(account, dst, (*emitDetails).getFieldH256(sfEmitNonce))
: keylet::payChan(account, dst, ctx_.tx.getSeqProxy().value());
auto const slep = std::make_shared<SLE>(payChanKeylet); auto const slep = std::make_shared<SLE>(payChanKeylet);

View File

@@ -27,6 +27,7 @@
#include <ripple/beast/utility/Journal.h> #include <ripple/beast/utility/Journal.h>
#include <ripple/ledger/PaymentSandbox.h> #include <ripple/ledger/PaymentSandbox.h>
#include <ripple/ledger/detail/ApplyViewBase.h> #include <ripple/ledger/detail/ApplyViewBase.h>
#include <variant>
namespace hook { namespace hook {
// RH TODO: fix applyHook.h so this prototype isn't needed // RH TODO: fix applyHook.h so this prototype isn't needed
@@ -289,6 +290,18 @@ preflight1(PreflightContext const& ctx);
NotTEC NotTEC
preflight2(PreflightContext const& ctx); 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 } // namespace ripple
#endif #endif