This commit is contained in:
Denis Angell
2024-04-16 10:34:53 +02:00
parent 175f436974
commit 7a4e2500bb
9 changed files with 75 additions and 8 deletions

View File

@@ -22,6 +22,8 @@ struct HookContext;
struct HookResult;
bool
isEmittedTxn(ripple::STTx const& tx);
bool
isBatchTxn(ripple::STTx const& tx);
// This map type acts as both a read and write cache for hook execution
// and is preserved across the execution of the set of hook chains

View File

@@ -896,6 +896,12 @@ hook::isEmittedTxn(ripple::STTx const& tx)
return tx.isFieldPresent(ripple::sfEmitDetails);
}
bool
hook::isBatchTxn(ripple::STTx const& tx)
{
return tx.isFieldPresent(ripple::sfBatchIndex);
}
int64_t
hook::computeExecutionFee(uint64_t instructionCount)
{

View File

@@ -135,7 +135,7 @@ OpenLedger::accept(
if (tx->isFieldPresent(sfEmitDetails))
continue;
// skip emitted txns
// skip batch txns
if (tx->isFieldPresent(sfBatchIndex))
continue;

View File

@@ -1218,6 +1218,21 @@ NetworkOPsImp::processTransaction(
return;
}
// This function is called by several different parts of the codebase
// under no circumstances will we ever accept an emitted txn from the
// network. Emitted txns are *always* and *only* inserted by TxQ::accept,
// and only arise from processing ltEMITTED_TXN out of the EMITTED_DIR. This
// isn't always an error because a fetch pack etc might include an emitted
// txn and if this is a deliberate attempt to send an emitted txn over the
// network it was already billed in PeerImp
if (view->rules().enabled(featureBatch) &&
hook::isBatchTxn(*transaction->getSTransaction()))
{
// RH NOTE: cannot set SF_BAD because if the tx will be generated by a
// hook we are about to execute
return;
}
auto const newFlags = app_.getHashRouter().getFlags(transaction->getID());
if ((newFlags & SF_BAD) != 0)
@@ -1280,6 +1295,18 @@ NetworkOPsImp::doTransactionAsync(
return;
}
// Enforce Network bar for batch txn
if (view->rules().enabled(featureBatch) &&
hook::isBatchTxn(*transaction->getSTransaction()))
{
JLOG(m_journal.info())
<< "Transaction received over network has BatchIndex, discarding.";
// RH NOTE: cannot set SF_BAD because if the tx will be generated by a
// hook we are about to execute then this would poison consensus for
// that emitted tx
return;
}
if (transaction->getApplying())
return;
@@ -1318,6 +1345,15 @@ NetworkOPsImp::doTransactionSync(
// that emitted tx
return;
}
// Enforce Network bar for batch txn
if (view->rules().enabled(featureBatch) &&
hook::isBatchTxn(*transaction->getSTransaction()))
{
JLOG(m_journal.info())
<< "Transaction received over network has BatchIndex, discarding.";
return;
}
if (!transaction->getApplying())
{
@@ -1524,8 +1560,10 @@ NetworkOPsImp::apply(std::unique_lock<std::mutex>& batchLock)
bool const isEmitted =
hook::isEmittedTxn(*(e.transaction->getSTransaction()));
bool const isBatch =
hook::isBatchTxn(*(e.transaction->getSTransaction()));
if (toSkip && !isEmitted)
if (toSkip && !isEmitted || !isBatch)
{
protocol::TMTransaction tx;
Serializer s;
@@ -2754,6 +2792,10 @@ NetworkOPsImp::pubProposedTransaction(
if (hook::isEmittedTxn(*transaction))
return;
// never publish emitted txns
if (hook::isBatchTxn(*transaction))
return;
Json::Value jvObj = transJson(*transaction, result, false, ledger);
{

View File

@@ -123,6 +123,12 @@ public:
return tx.isFieldPresent(sfEmitDetails);
}
bool
isBatchTxn()
{
return tx.isFieldPresent(sfBatchIndex);
}
ApplyFlags const&
flags()
{

View File

@@ -480,7 +480,7 @@ Batch::doApply()
meta.setFieldU8(sfTransactionResult, TERtoInt(_result.first));
meta.setFieldU16(sfTransactionType, stx.getTxnType());
if(_result.first != tesSUCCESS)
if(_result.first == tesSUCCESS)
meta.setFieldH256(sfTransactionHash, stx.getTransactionID());
avi.addBatchExecutionMetaData(std::move(meta));
@@ -525,7 +525,7 @@ Batch::doApply()
// std::cout << "ACCOUNT BALANCE: " << sleSrcAcc->getFieldAmount(sfBalance) << "\n";
auto const feePaid = ctx_.tx[sfFee].xrp();
sleSrcAcc->setFieldU32(sfSequence, sleBase->getFieldU32(sfSequence));
// sleSrcAcc->setFieldU32(sfSequence, ctx_.tx.getFieldU32(sfSequence) + 1);
sleSrcAcc->setFieldAmount(sfBalance, sleBase->getFieldAmount(sfBalance).xrp() - feePaid);
sb.update(sleSrcAcc);
sb.apply(ctx_.rawView());

View File

@@ -734,6 +734,10 @@ Transactor::consumeSeqProxy(SLE::pointer const& sleAccount)
// do not update sequence of sfAccountTxnID for emitted tx
if (ctx_.isEmittedTxn())
return tesSUCCESS;
// do not update sequence of sfAccountTxnID for emitted tx
if (ctx_.isBatchTxn())
return tesSUCCESS;
SeqProxy const seqProx = ctx_.tx.getSeqProxy();
if (seqProx.isSeq())

View File

@@ -186,11 +186,18 @@ STTx::getSeqProxy() const
{
std::uint32_t const seq{getFieldU32(sfSequence)};
if (seq != 0)
{
// if (getTxnType() == ttBATCH)
// {
// auto const& txns = ctx_.tx.getFieldArray(sfRawTransactions);
// return SeqProxy::sequence(seq + txns.size());
// }
return SeqProxy::sequence(seq);
}
// std::uint32_t const batchIndex{getFieldU32(sfBatchIndex)};
// if (batchIndex != 0)
// return SeqProxy::sequence(batchIndex);
std::uint32_t const batchIndex{getFieldU32(sfBatchIndex)};
if (batchIndex != 0)
return SeqProxy::sequence(batchIndex);
std::optional<std::uint32_t> const ticketSeq{operator[](~sfTicketSequence)};
if (!ticketSeq)

View File

@@ -89,7 +89,7 @@ class Batch_test : public beast::unit_test::suite
jv[sfRawTransactions.jsonName][index][jss::RawTransaction] = tx;
jv[sfRawTransactions.jsonName][index][jss::RawTransaction][jss::SigningPubKey] = strHex(account.pk());
jv[sfRawTransactions.jsonName][index][jss::RawTransaction][sfFee.jsonName] = 0;
jv[sfRawTransactions.jsonName][index][jss::RawTransaction][jss::Sequence] = next;
jv[sfRawTransactions.jsonName][index][jss::RawTransaction][jss::Sequence] = 0;
jv[sfRawTransactions.jsonName][index][jss::RawTransaction][sfBatchIndex.jsonName] = next;
return jv;
}