From 69b40a164a4a6ad408416d0397ddd4f63843551e Mon Sep 17 00:00:00 2001 From: Edward Hennis Date: Tue, 14 Dec 2021 16:27:14 -0500 Subject: [PATCH] Improve deterministic transaction sorting in TxQ: * Txs with the same fee level will sort by TxID XORed with the parent ledger hash. * The TxQ is re-sorted after every ledger. * Attempt to future-proof the TxQ tie breaking test --- src/ripple/app/misc/TxQ.h | 37 +- src/ripple/app/misc/impl/TxQ.cpp | 40 +- src/ripple/rpc/handlers/AccountInfo.cpp | 5 +- src/ripple/rpc/handlers/LedgerHandler.cpp | 2 +- src/test/app/TxQ_test.cpp | 939 +++++++++++++--------- src/test/rpc/LedgerRPC_test.cpp | 22 +- 6 files changed, 640 insertions(+), 405 deletions(-) diff --git a/src/ripple/app/misc/TxQ.h b/src/ripple/app/misc/TxQ.h index 0c642c1d955..7e004ec7267 100644 --- a/src/ripple/app/misc/TxQ.h +++ b/src/ripple/app/misc/TxQ.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -340,7 +341,7 @@ class TxQ in the queue. */ std::vector - getAccountTxs(AccountID const& account, ReadView const& view) const; + getAccountTxs(AccountID const& account) const; /** Returns information about all transactions currently in the queue. @@ -349,7 +350,7 @@ class TxQ in the queue. */ std::vector - getTxs(ReadView const& view) const; + getTxs() const; /** Summarize current fee metrics for the `fee` RPC command. @@ -575,6 +576,16 @@ class TxQ */ static constexpr int retriesAllowed = 10; + /** The hash of the parent ledger. + + This is used to pseudo-randomize the transaction order when + populating byFee_, by XORing it with the transaction hash (txID). + Using a single static and doing the XOR operation every time was + tested to be as fast or faster than storing the computed "sort key", + and obviously uses less memory. + */ + static LedgerHash parentHashComp; + public: /// Constructor MaybeTx( @@ -621,22 +632,26 @@ class TxQ explicit OrderCandidates() = default; /** Sort @ref MaybeTx by `feeLevel` descending, then by - * transaction ID ascending + * pseudo-randomized transaction ID ascending * * The transaction queue is ordered such that transactions * paying a higher fee are in front of transactions paying * a lower fee, giving them an opportunity to be processed into * the open ledger first. Within transactions paying the same - * fee, order by the arbitrary but consistent transaction ID. - * This allows validators to build similar queues in the same - * order, and thus have more similar initial proposals. + * fee, order by the arbitrary but consistent pseudo-randomized + * transaction ID. The ID is pseudo-randomized by XORing it with + * the open ledger's parent hash, which is deterministic, but + * unpredictable. This allows validators to build similar queues + * in the same order, and thus have more similar initial + * proposals. * */ bool operator()(const MaybeTx& lhs, const MaybeTx& rhs) const { if (lhs.feeLevel == rhs.feeLevel) - return lhs.txID < rhs.txID; + return (lhs.txID ^ MaybeTx::parentHashComp) < + (rhs.txID ^ MaybeTx::parentHashComp); return lhs.feeLevel > rhs.feeLevel; } }; @@ -770,6 +785,14 @@ class TxQ */ std::optional maxSize_; +#if !NDEBUG + /** + parentHash_ checks that no unexpected ledger transitions + happen, and is only checked via debug asserts. + */ + LedgerHash parentHash_{beast::zero}; +#endif + /** Most queue operations are done under the master lock, but use this mutex for the RPC "fee" command, which isn't. */ diff --git a/src/ripple/app/misc/impl/TxQ.cpp b/src/ripple/app/misc/impl/TxQ.cpp index 196060a5bc6..0eeec8d62ae 100644 --- a/src/ripple/app/misc/impl/TxQ.cpp +++ b/src/ripple/app/misc/impl/TxQ.cpp @@ -265,6 +265,8 @@ TxQ::FeeMetrics::escalatedSeriesFeeLevel( return totalFeeLevel; } +LedgerHash TxQ::MaybeTx::parentHashComp{}; + TxQ::MaybeTx::MaybeTx( std::shared_ptr const& txn_, TxID const& txID_, @@ -467,13 +469,12 @@ TxQ::eraseAndAdvance(TxQ::FeeMultiSet::const_iterator_type candidateIter) // Check if the next transaction for this account is earlier in the queue, // which means we skipped it earlier, and need to try it again. - OrderCandidates o; auto const feeNextIter = std::next(candidateIter); bool const useAccountNext = accountNextIter != txQAccount.transactions.end() && accountNextIter->first > candidateIter->seqProxy && (feeNextIter == byFee_.end() || - o(accountNextIter->second, *feeNextIter)); + byFee_.value_comp()(accountNextIter->second, *feeNextIter)); auto const candidateNextIter = byFee_.erase(candidateIter); txQAccount.transactions.erase(accountIter); @@ -1529,6 +1530,37 @@ TxQ::accept(Application& app, OpenView& view) } } + // All transactions that can be moved out of the queue into the open + // ledger have been. Rebuild the queue using the open ledger's + // parent hash, so that transactions paying the same fee are + // reordered. + LedgerHash const& parentHash = view.info().parentHash; +#if !NDEBUG + auto const startingSize = byFee_.size(); + assert(parentHash != parentHash_); + parentHash_ = parentHash; +#endif + // byFee_ doesn't "own" the candidate objects inside it, so it's + // perfectly safe to wipe it and start over, repopulating from + // byAccount_. + // + // In the absence of a "re-sort the list in place" function, this + // was the fastest method tried to repopulate the list. + // Other methods included: create a new list and moving items over one at a + // time, create a new list and merge the old list into it. + byFee_.clear(); + + MaybeTx::parentHashComp = parentHash; + + for (auto& [_, account] : byAccount_) + { + for (auto& [_, candidate] : account.transactions) + { + byFee_.insert(candidate); + } + } + assert(byFee_.size() == startingSize); + return ledgerChanged; } @@ -1740,7 +1772,7 @@ TxQ::getTxRequiredFeeAndSeq( } std::vector -TxQ::getAccountTxs(AccountID const& account, ReadView const& view) const +TxQ::getAccountTxs(AccountID const& account) const { std::vector result; @@ -1761,7 +1793,7 @@ TxQ::getAccountTxs(AccountID const& account, ReadView const& view) const } std::vector -TxQ::getTxs(ReadView const& view) const +TxQ::getTxs() const { std::vector result; diff --git a/src/ripple/rpc/handlers/AccountInfo.cpp b/src/ripple/rpc/handlers/AccountInfo.cpp index ee192935856..417a3ffcd38 100644 --- a/src/ripple/rpc/handlers/AccountInfo.cpp +++ b/src/ripple/rpc/handlers/AccountInfo.cpp @@ -128,8 +128,7 @@ doAccountInfo(RPC::JsonContext& context) { Json::Value jvQueueData = Json::objectValue; - auto const txs = - context.app.getTxQ().getAccountTxs(accountID, *ledger); + auto const txs = context.app.getTxQ().getAccountTxs(accountID); if (!txs.empty()) { jvQueueData[jss::txn_count] = @@ -298,7 +297,7 @@ doAccountInfoGrpc( return {result, errorStatus}; } std::vector const txs = - context.app.getTxQ().getAccountTxs(accountID, *ledger); + context.app.getTxQ().getAccountTxs(accountID); org::xrpl::rpc::v1::QueueData& queueData = *result.mutable_queue_data(); RPC::convert(queueData, txs); diff --git a/src/ripple/rpc/handlers/LedgerHandler.cpp b/src/ripple/rpc/handlers/LedgerHandler.cpp index c358f27616d..40ae80afb6f 100644 --- a/src/ripple/rpc/handlers/LedgerHandler.cpp +++ b/src/ripple/rpc/handlers/LedgerHandler.cpp @@ -94,7 +94,7 @@ LedgerHandler::check() return rpcINVALID_PARAMS; } - queueTxs_ = context_.app.getTxQ().getTxs(*ledger_); + queueTxs_ = context_.app.getTxQ().getTxs(); } return Status::OK; diff --git a/src/test/app/TxQ_test.cpp b/src/test/app/TxQ_test.cpp index 2ade9e8e307..f3170c9a27b 100644 --- a/src/test/app/TxQ_test.cpp +++ b/src/test/app/TxQ_test.cpp @@ -40,6 +40,7 @@ class TxQ1_test : public beast::unit_test::suite { void checkMetrics( + int line, jtx::Env& env, std::size_t expectedCount, std::optional expectedMaxCount, @@ -51,18 +52,81 @@ class TxQ1_test : public beast::unit_test::suite FeeLevel64 const expectedMin{expectedMinFeeLevel}; FeeLevel64 const expectedMed{expectedMedFeeLevel}; auto const metrics = env.app().getTxQ().getMetrics(*env.current()); - BEAST_EXPECT(metrics.referenceFeeLevel == FeeLevel64{256}); - BEAST_EXPECT(metrics.txCount == expectedCount); - BEAST_EXPECT(metrics.txQMaxSize == expectedMaxCount); - BEAST_EXPECT(metrics.txInLedger == expectedInLedger); - BEAST_EXPECT(metrics.txPerLedger == expectedPerLedger); - BEAST_EXPECT(metrics.minProcessingFeeLevel == expectedMin); - BEAST_EXPECT(metrics.medFeeLevel == expectedMed); - auto expectedCurFeeLevel = expectedInLedger > expectedPerLedger + using namespace std::string_literals; + + metrics.referenceFeeLevel == FeeLevel64{256} + ? pass() + : fail( + "reference: "s + + std::to_string(metrics.referenceFeeLevel.value()) + + "/256", + __FILE__, + line); + + metrics.txCount == expectedCount + ? pass() + : fail( + "txCount: "s + std::to_string(metrics.txCount) + "/" + + std::to_string(expectedCount), + __FILE__, + line); + + metrics.txQMaxSize == expectedMaxCount + ? pass() + : fail( + "txQMaxSize: "s + + std::to_string(metrics.txQMaxSize.value_or(0)) + "/" + + std::to_string(expectedMaxCount.value_or(0)), + __FILE__, + line); + + metrics.txInLedger == expectedInLedger + ? pass() + : fail( + "txInLedger: "s + std::to_string(metrics.txInLedger) + "/" + + std::to_string(expectedInLedger), + __FILE__, + line); + + metrics.txPerLedger == expectedPerLedger + ? pass() + : fail( + "txPerLedger: "s + std::to_string(metrics.txPerLedger) + "/" + + std::to_string(expectedPerLedger), + __FILE__, + line); + + metrics.minProcessingFeeLevel == expectedMin + ? pass() + : fail( + "minProcessingFeeLevel: "s + + std::to_string(metrics.minProcessingFeeLevel.value()) + + "/" + std::to_string(expectedMin.value()), + __FILE__, + line); + + metrics.medFeeLevel == expectedMed + ? pass() + : fail( + "medFeeLevel: "s + + std::to_string(metrics.medFeeLevel.value()) + "/" + + std::to_string(expectedMed.value()), + __FILE__, + line); + + auto const expectedCurFeeLevel = expectedInLedger > expectedPerLedger ? expectedMed * expectedInLedger * expectedInLedger / (expectedPerLedger * expectedPerLedger) : metrics.referenceFeeLevel; - BEAST_EXPECT(metrics.openLedgerFeeLevel == expectedCurFeeLevel); + + metrics.openLedgerFeeLevel == expectedCurFeeLevel + ? pass() + : fail( + "openLedgerFeeLevel: "s + + std::to_string(metrics.openLedgerFeeLevel.value()) + "/" + + std::to_string(expectedCurFeeLevel.value()), + __FILE__, + line); } void @@ -141,7 +205,7 @@ class TxQ1_test : public beast::unit_test::suite // transactions as though they are ordinary transactions. auto const flagPerLedger = 1 + ripple::detail::numUpVotedAmendments(); auto const flagMaxQueue = ledgersInQueue * flagPerLedger; - checkMetrics(env, 0, flagMaxQueue, 0, flagPerLedger, 256); + checkMetrics(__LINE__, env, 0, flagMaxQueue, 0, flagPerLedger, 256); // Pad a couple of txs with normal fees so the median comes // back down to normal @@ -152,7 +216,7 @@ class TxQ1_test : public beast::unit_test::suite // metrics to reset to defaults, EXCEPT the maxQueue size. using namespace std::chrono_literals; env.close(env.now() + 5s, 10000ms); - checkMetrics(env, 0, flagMaxQueue, 0, expectedPerLedger, 256); + checkMetrics(__LINE__, env, 0, flagMaxQueue, 0, expectedPerLedger, 256); auto const fees = env.current()->fees(); BEAST_EXPECT(fees.base == XRPAmount{base}); BEAST_EXPECT(fees.units == FeeUnit64{units}); @@ -186,37 +250,37 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(env.current()->fees().base == 10); - checkMetrics(env, 0, std::nullopt, 0, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 3, 256); // Create several accounts while the fee is cheap so they all apply. env.fund(XRP(50000), noripple(alice, bob, charlie, daria)); - checkMetrics(env, 0, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 4, 3, 256); // Alice - price starts exploding: held env(noop(alice), queued); - checkMetrics(env, 1, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 4, 3, 256); // Bob with really high fee - applies env(noop(bob), openLedgerFee(env)); - checkMetrics(env, 1, std::nullopt, 5, 3, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 5, 3, 256); // Daria with low fee: hold env(noop(daria), fee(1000), queued); - checkMetrics(env, 2, std::nullopt, 5, 3, 256); + checkMetrics(__LINE__, env, 2, std::nullopt, 5, 3, 256); env.close(); // Verify that the held transactions got applied - checkMetrics(env, 0, 10, 2, 5, 256); + checkMetrics(__LINE__, env, 0, 10, 2, 5, 256); ////////////////////////////////////////////////////////////// // Make some more accounts. We'll need them later to abuse the queue. env.fund(XRP(50000), noripple(elmo, fred, gwen, hank)); - checkMetrics(env, 0, 10, 6, 5, 256); + checkMetrics(__LINE__, env, 0, 10, 6, 5, 256); // Now get a bunch of transactions held. env(noop(alice), fee(12), queued); - checkMetrics(env, 1, 10, 6, 5, 256); + checkMetrics(__LINE__, env, 1, 10, 6, 5, 256); env(noop(bob), fee(10), queued); // won't clear the queue env(noop(charlie), fee(20), queued); @@ -225,11 +289,11 @@ class TxQ1_test : public beast::unit_test::suite env(noop(fred), fee(19), queued); env(noop(gwen), fee(16), queued); env(noop(hank), fee(18), queued); - checkMetrics(env, 8, 10, 6, 5, 256); + checkMetrics(__LINE__, env, 8, 10, 6, 5, 256); env.close(); // Verify that the held transactions got applied - checkMetrics(env, 1, 12, 7, 6, 256); + checkMetrics(__LINE__, env, 1, 12, 7, 6, 256); // Bob's transaction is still stuck in the queue. @@ -238,45 +302,45 @@ class TxQ1_test : public beast::unit_test::suite // Hank sends another txn env(noop(hank), fee(10), queued); // But he's not going to leave it in the queue - checkMetrics(env, 2, 12, 7, 6, 256); + checkMetrics(__LINE__, env, 2, 12, 7, 6, 256); // Hank sees his txn got held and bumps the fee, // but doesn't even bump it enough to requeue env(noop(hank), fee(11), ter(telCAN_NOT_QUEUE_FEE)); - checkMetrics(env, 2, 12, 7, 6, 256); + checkMetrics(__LINE__, env, 2, 12, 7, 6, 256); // Hank sees his txn got held and bumps the fee, // enough to requeue, but doesn't bump it enough to // apply to the ledger env(noop(hank), fee(6000), queued); // But he's not going to leave it in the queue - checkMetrics(env, 2, 12, 7, 6, 256); + checkMetrics(__LINE__, env, 2, 12, 7, 6, 256); // Hank sees his txn got held and bumps the fee, // high enough to get into the open ledger, because // he doesn't want to wait. env(noop(hank), openLedgerFee(env)); - checkMetrics(env, 1, 12, 8, 6, 256); + checkMetrics(__LINE__, env, 1, 12, 8, 6, 256); // Hank then sends another, less important txn // (In addition to the metrics, this will verify that // the original txn got removed.) env(noop(hank), fee(6000), queued); - checkMetrics(env, 2, 12, 8, 6, 256); + checkMetrics(__LINE__, env, 2, 12, 8, 6, 256); env.close(); // Verify that bob and hank's txns were applied - checkMetrics(env, 0, 16, 2, 8, 256); + checkMetrics(__LINE__, env, 0, 16, 2, 8, 256); // Close again with a simulated time leap to // reset the escalation limit down to minimum env.close(env.now() + 5s, 10000ms); - checkMetrics(env, 0, 16, 0, 3, 256); + checkMetrics(__LINE__, env, 0, 16, 0, 3, 256); // Then close once more without the time leap // to reset the queue maxsize down to minimum env.close(); - checkMetrics(env, 0, 6, 0, 3, 256); + checkMetrics(__LINE__, env, 0, 6, 0, 3, 256); ////////////////////////////////////////////////////////////// @@ -286,7 +350,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(gwen), fee(7000)); env(noop(fred), fee(7000)); env(noop(elmo), fee(7000)); - checkMetrics(env, 0, 6, 4, 3, 256); + checkMetrics(__LINE__, env, 0, 6, 4, 3, 256); // Use explicit fees so we can control which txn // will get dropped @@ -301,7 +365,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), fee(20), queued); // Queue is full now. - checkMetrics(env, 6, 6, 4, 3, 385); + checkMetrics(__LINE__, env, 6, 6, 4, 3, 385); // Try to add another transaction with the default (low) fee, // it should fail because the queue is full. @@ -313,17 +377,17 @@ class TxQ1_test : public beast::unit_test::suite env(noop(charlie), fee(100), queued); // Queue is still full, of course, but the min fee has gone up - checkMetrics(env, 6, 6, 4, 3, 410); + checkMetrics(__LINE__, env, 6, 6, 4, 3, 410); // Close out the ledger, the transactions are accepted, the // queue is cleared, then the localTxs are retried. At this // point, daria's transaction that was dropped from the queue // is put back in. Neat. env.close(); - checkMetrics(env, 2, 8, 5, 4, 256, 256 * 700); + checkMetrics(__LINE__, env, 2, 8, 5, 4, 256, 256 * 700); env.close(); - checkMetrics(env, 0, 10, 2, 5, 256); + checkMetrics(__LINE__, env, 0, 10, 2, 5, 256); ////////////////////////////////////////////////////////////// @@ -337,10 +401,10 @@ class TxQ1_test : public beast::unit_test::suite env(noop(daria)); env(pay(alice, iris, XRP(1000)), queued); env(noop(iris), seq(1), fee(20), ter(terNO_ACCOUNT)); - checkMetrics(env, 1, 10, 6, 5, 256); + checkMetrics(__LINE__, env, 1, 10, 6, 5, 256); env.close(); - checkMetrics(env, 0, 12, 1, 6, 256); + checkMetrics(__LINE__, env, 0, 12, 1, 6, 256); env.require(balance(iris, XRP(1000))); BEAST_EXPECT(env.seq(iris) == 11); @@ -366,6 +430,7 @@ class TxQ1_test : public beast::unit_test::suite ++metrics.txCount; checkMetrics( + __LINE__, env, metrics.txCount, metrics.txQMaxSize, @@ -388,14 +453,14 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(env.current()->fees().base == 10); - checkMetrics(env, 0, std::nullopt, 0, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 3, 256); // Fund alice and then fill the ledger. env.fund(XRP(50000), noripple(alice)); env(noop(alice)); env(noop(alice)); env(noop(alice)); - checkMetrics(env, 0, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 4, 3, 256); ////////////////////////////////////////////////////////////////// @@ -407,11 +472,11 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), ticket::use(tkt1 - 2), ter(tefNO_TICKET)); env(noop(alice), ticket::use(tkt1 - 1), ter(terPRE_TICKET)); env.require(owners(alice, 0), tickets(alice, 0)); - checkMetrics(env, 1, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 4, 3, 256); env.close(); env.require(owners(alice, 250), tickets(alice, 250)); - checkMetrics(env, 0, 8, 1, 4, 256); + checkMetrics(__LINE__, env, 0, 8, 1, 4, 256); BEAST_EXPECT(env.seq(alice) == tkt1 + 250); ////////////////////////////////////////////////////////////////// @@ -438,7 +503,7 @@ class TxQ1_test : public beast::unit_test::suite ticket::use(tkt1 + 13), fee(23), ter(telCAN_NOT_QUEUE_FULL)); - checkMetrics(env, 8, 8, 5, 4, 385); + checkMetrics(__LINE__, env, 8, 8, 5, 4, 385); // Check which of the queued transactions got into the ledger by // attempting to replace them. @@ -470,7 +535,7 @@ class TxQ1_test : public beast::unit_test::suite // the queue. env(noop(alice), ticket::use(tkt1 + 13), ter(telCAN_NOT_QUEUE_FEE)); - checkMetrics(env, 3, 10, 6, 5, 256); + checkMetrics(__LINE__, env, 3, 10, 6, 5, 256); ////////////////////////////////////////////////////////////////// @@ -501,7 +566,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), seq(nextSeq + 5), queued); env(noop(alice), seq(nextSeq + 6), queued); env(noop(alice), seq(nextSeq + 7), ter(telCAN_NOT_QUEUE_FULL)); - checkMetrics(env, 10, 10, 6, 5, 257); + checkMetrics(__LINE__, env, 10, 10, 6, 5, 257); // Check which of the queued transactions got into the ledger by // attempting to replace them. @@ -529,7 +594,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), seq(nextSeq + 6), ter(telCAN_NOT_QUEUE_FEE)); env(noop(alice), seq(nextSeq + 7), ter(telCAN_NOT_QUEUE_FEE)); - checkMetrics(env, 4, 12, 7, 6, 256); + checkMetrics(__LINE__, env, 4, 12, 7, 6, 256); BEAST_EXPECT(env.seq(alice) == nextSeq + 4); ////////////////////////////////////////////////////////////////// @@ -560,7 +625,7 @@ class TxQ1_test : public beast::unit_test::suite fee(21), ter(telCAN_NOT_QUEUE_FULL)); - checkMetrics(env, 10, 12, 7, 6, 256); + checkMetrics(__LINE__, env, 10, 12, 7, 6, 256); env.close(); env.require(owners(alice, 231), tickets(alice, 231)); @@ -591,7 +656,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), seq(nextSeq + 7), ter(telCAN_NOT_QUEUE_FEE)); BEAST_EXPECT(env.seq(alice) == nextSeq + 6); - checkMetrics(env, 6, 14, 8, 7, 256); + checkMetrics(__LINE__, env, 6, 14, 8, 7, 256); ////////////////////////////////////////////////////////////////// @@ -628,7 +693,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), seq(nextSeq + 7), ter(tefPAST_SEQ)); BEAST_EXPECT(env.seq(alice) == nextSeq + 8); - checkMetrics(env, 0, 16, 6, 8, 256); + checkMetrics(__LINE__, env, 0, 16, 6, 8, 256); } void @@ -643,28 +708,28 @@ class TxQ1_test : public beast::unit_test::suite auto gw = Account("gw"); auto USD = gw["USD"]; - checkMetrics(env, 0, std::nullopt, 0, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 2, 256); // Create accounts env.fund(XRP(50000), noripple(alice, gw)); - checkMetrics(env, 0, std::nullopt, 2, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 2, 2, 256); env.close(); - checkMetrics(env, 0, 4, 0, 2, 256); + checkMetrics(__LINE__, env, 0, 4, 0, 2, 256); // Alice creates an unfunded offer while the ledger is not full env(offer(alice, XRP(1000), USD(1000)), ter(tecUNFUNDED_OFFER)); - checkMetrics(env, 0, 4, 1, 2, 256); + checkMetrics(__LINE__, env, 0, 4, 1, 2, 256); fillQueue(env, alice); - checkMetrics(env, 0, 4, 3, 2, 256); + checkMetrics(__LINE__, env, 0, 4, 3, 2, 256); // Alice creates an unfunded offer that goes in the queue env(offer(alice, XRP(1000), USD(1000)), ter(terQUEUED)); - checkMetrics(env, 1, 4, 3, 2, 256); + checkMetrics(__LINE__, env, 1, 4, 3, 2, 256); // The offer comes out of the queue env.close(); - checkMetrics(env, 0, 6, 1, 3, 256); + checkMetrics(__LINE__, env, 0, 6, 1, 3, 256); } void @@ -684,44 +749,44 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(env.current()->fees().base == 10); - checkMetrics(env, 0, std::nullopt, 0, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 2, 256); // Create several accounts while the fee is cheap so they all apply. env.fund(XRP(50000), noripple(alice, bob, charlie)); - checkMetrics(env, 0, std::nullopt, 3, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 3, 2, 256); // Future transaction for Alice - fails env(noop(alice), openLedgerFee(env), seq(env.seq(alice) + 1), ter(terPRE_SEQ)); - checkMetrics(env, 0, std::nullopt, 3, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 3, 2, 256); // Current transaction for Alice: held env(noop(alice), queued); - checkMetrics(env, 1, std::nullopt, 3, 2, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 3, 2, 256); // Alice - sequence is too far ahead, so won't queue. env(noop(alice), seq(env.seq(alice) + 2), ter(telCAN_NOT_QUEUE)); - checkMetrics(env, 1, std::nullopt, 3, 2, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 3, 2, 256); // Bob with really high fee - applies env(noop(bob), openLedgerFee(env)); - checkMetrics(env, 1, std::nullopt, 4, 2, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 4, 2, 256); // Daria with low fee: hold env(noop(charlie), fee(1000), queued); - checkMetrics(env, 2, std::nullopt, 4, 2, 256); + checkMetrics(__LINE__, env, 2, std::nullopt, 4, 2, 256); // Alice with normal fee: hold env(noop(alice), seq(env.seq(alice) + 1), queued); - checkMetrics(env, 3, std::nullopt, 4, 2, 256); + checkMetrics(__LINE__, env, 3, std::nullopt, 4, 2, 256); env.close(); // Verify that the held transactions got applied // Alice's bad transaction applied from the // Local Txs. - checkMetrics(env, 0, 8, 4, 4, 256); + checkMetrics(__LINE__, env, 0, 8, 4, 4, 256); } void @@ -742,7 +807,7 @@ class TxQ1_test : public beast::unit_test::suite auto queued = ter(terQUEUED); - checkMetrics(env, 0, std::nullopt, 0, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 2, 256); // Fund across several ledgers so the TxQ metrics stay restricted. env.fund(XRP(1000), noripple(alice, bob)); @@ -752,11 +817,11 @@ class TxQ1_test : public beast::unit_test::suite env.fund(XRP(1000), noripple(edgar, felicia)); env.close(env.now() + 5s, 10000ms); - checkMetrics(env, 0, std::nullopt, 0, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 2, 256); env(noop(bob)); env(noop(charlie)); env(noop(daria)); - checkMetrics(env, 0, std::nullopt, 3, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 3, 2, 256); BEAST_EXPECT(env.current()->info().seq == 6); // Fail to queue an item with a low LastLedgerSeq @@ -771,10 +836,10 @@ class TxQ1_test : public beast::unit_test::suite env(noop(charlie), fee(7000), queued); env(noop(daria), fee(7000), queued); env(noop(edgar), fee(7000), queued); - checkMetrics(env, 5, std::nullopt, 3, 2, 256); + checkMetrics(__LINE__, env, 5, std::nullopt, 3, 2, 256); { auto& txQ = env.app().getTxQ(); - auto aliceStat = txQ.getAccountTxs(alice.id(), *env.current()); + auto aliceStat = txQ.getAccountTxs(alice.id()); BEAST_EXPECT(aliceStat.size() == 1); BEAST_EXPECT(aliceStat.begin()->feeLevel == FeeLevel64{256}); BEAST_EXPECT( @@ -782,20 +847,19 @@ class TxQ1_test : public beast::unit_test::suite *aliceStat.begin()->lastValid == 8); BEAST_EXPECT(!aliceStat.begin()->consequences.isBlocker()); - auto bobStat = txQ.getAccountTxs(bob.id(), *env.current()); + auto bobStat = txQ.getAccountTxs(bob.id()); BEAST_EXPECT(bobStat.size() == 1); BEAST_EXPECT( bobStat.begin()->feeLevel == FeeLevel64{7000 * 256 / 10}); BEAST_EXPECT(!bobStat.begin()->lastValid); BEAST_EXPECT(!bobStat.begin()->consequences.isBlocker()); - auto noStat = - txQ.getAccountTxs(Account::master.id(), *env.current()); + auto noStat = txQ.getAccountTxs(Account::master.id()); BEAST_EXPECT(noStat.empty()); } env.close(); - checkMetrics(env, 1, 6, 4, 3, 256); + checkMetrics(__LINE__, env, 1, 6, 4, 3, 256); // Keep alice's transaction waiting. env(noop(bob), fee(7000), queued); @@ -803,11 +867,11 @@ class TxQ1_test : public beast::unit_test::suite env(noop(daria), fee(7000), queued); env(noop(edgar), fee(7000), queued); env(noop(felicia), fee(6999), queued); - checkMetrics(env, 6, 6, 4, 3, 257); + checkMetrics(__LINE__, env, 6, 6, 4, 3, 257); env.close(); // alice's transaction is still hanging around - checkMetrics(env, 1, 8, 5, 4, 256, 700 * 256); + checkMetrics(__LINE__, env, 1, 8, 5, 4, 256, 700 * 256); BEAST_EXPECT(env.seq(alice) == 3); // Keep alice's transaction waiting. @@ -818,19 +882,19 @@ class TxQ1_test : public beast::unit_test::suite env(noop(edgar), fee(8000), queued); env(noop(felicia), fee(7999), queued); env(noop(felicia), fee(7999), seq(env.seq(felicia) + 1), queued); - checkMetrics(env, 8, 8, 5, 4, 257, 700 * 256); + checkMetrics(__LINE__, env, 8, 8, 5, 4, 257, 700 * 256); env.close(); // alice's transaction expired without getting // into the ledger, so her transaction is gone, // though one of felicia's is still in the queue. - checkMetrics(env, 1, 10, 6, 5, 256, 700 * 256); + checkMetrics(__LINE__, env, 1, 10, 6, 5, 256, 700 * 256); BEAST_EXPECT(env.seq(alice) == 3); BEAST_EXPECT(env.seq(felicia) == 7); env.close(); // And now the queue is empty - checkMetrics(env, 0, 12, 1, 6, 256, 800 * 256); + checkMetrics(__LINE__, env, 0, 12, 1, 6, 256, 800 * 256); BEAST_EXPECT(env.seq(alice) == 3); BEAST_EXPECT(env.seq(felicia) == 8); } @@ -850,7 +914,7 @@ class TxQ1_test : public beast::unit_test::suite auto queued = ter(terQUEUED); - checkMetrics(env, 0, std::nullopt, 0, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 2, 256); // Fund across several ledgers so the TxQ metrics stay restricted. env.fund(XRP(1000), noripple(alice, bob)); @@ -862,21 +926,21 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice)); env(noop(alice)); env(noop(alice)); - checkMetrics(env, 0, std::nullopt, 3, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 3, 2, 256); env(noop(bob), queued); - checkMetrics(env, 1, std::nullopt, 3, 2, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 3, 2, 256); // Since Alice's queue is empty this blocker can go into her queue. env(regkey(alice, bob), fee(0), queued); - checkMetrics(env, 2, std::nullopt, 3, 2, 256); + checkMetrics(__LINE__, env, 2, std::nullopt, 3, 2, 256); // Close out this ledger so we can get a maxsize env.close(); - checkMetrics(env, 0, 6, 2, 3, 256); + checkMetrics(__LINE__, env, 0, 6, 2, 3, 256); fillQueue(env, alice); - checkMetrics(env, 0, 6, 4, 3, 256); + checkMetrics(__LINE__, env, 0, 6, 4, 3, 256); auto feeAlice = 30; auto seqAlice = env.seq(alice); @@ -886,12 +950,12 @@ class TxQ1_test : public beast::unit_test::suite feeAlice = (feeAlice + 1) * 125 / 100; ++seqAlice; } - checkMetrics(env, 4, 6, 4, 3, 256); + checkMetrics(__LINE__, env, 4, 6, 4, 3, 256); // Bob adds a zero fee blocker to his queue. auto const seqBob = env.seq(bob); env(regkey(bob, alice), fee(0), queued); - checkMetrics(env, 5, 6, 4, 3, 256); + checkMetrics(__LINE__, env, 5, 6, 4, 3, 256); // Carol fills the queue. auto feeCarol = feeAlice; @@ -902,7 +966,7 @@ class TxQ1_test : public beast::unit_test::suite feeCarol = (feeCarol + 1) * 125 / 100; ++seqCarol; } - checkMetrics(env, 6, 6, 4, 3, 3 * 256 + 1); + checkMetrics(__LINE__, env, 6, 6, 4, 3, 3 * 256 + 1); // Carol submits high enough to beat Bob's average fee which kicks // out Bob's queued transaction. However Bob's transaction stays @@ -913,20 +977,20 @@ class TxQ1_test : public beast::unit_test::suite env.close(); // Some of Alice's transactions stay in the queue. Bob's // transaction returns to the TxQ. - checkMetrics(env, 5, 8, 5, 4, 256); + checkMetrics(__LINE__, env, 5, 8, 5, 4, 256); BEAST_EXPECT(env.seq(alice) == seqAlice - 4); BEAST_EXPECT(env.seq(bob) == seqBob); BEAST_EXPECT(env.seq(carol) == seqCarol + 1); env.close(); // The remaining queued transactions flush through to the ledger. - checkMetrics(env, 0, 10, 5, 5, 256); + checkMetrics(__LINE__, env, 0, 10, 5, 5, 256); BEAST_EXPECT(env.seq(alice) == seqAlice); BEAST_EXPECT(env.seq(bob) == seqBob + 1); BEAST_EXPECT(env.seq(carol) == seqCarol + 1); env.close(); - checkMetrics(env, 0, 10, 0, 5, 256); + checkMetrics(__LINE__, env, 0, 10, 0, 5, 256); BEAST_EXPECT(env.seq(alice) == seqAlice); BEAST_EXPECT(env.seq(bob) == seqBob + 1); BEAST_EXPECT(env.seq(carol) == seqCarol + 1); @@ -969,19 +1033,19 @@ class TxQ1_test : public beast::unit_test::suite auto queued = ter(terQUEUED); - checkMetrics(env, 0, std::nullopt, 0, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 2, 256); env.fund(XRP(1000), noripple(alice, bob)); - checkMetrics(env, 0, std::nullopt, 2, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 2, 2, 256); // Fill the ledger env(noop(alice)); - checkMetrics(env, 0, std::nullopt, 3, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 3, 2, 256); // Put a transaction in the queue env(noop(alice), queued); - checkMetrics(env, 1, std::nullopt, 3, 2, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 3, 2, 256); // Now cheat, and bypass the queue. { @@ -999,12 +1063,12 @@ class TxQ1_test : public beast::unit_test::suite }); env.postconditions(jt, ter, didApply); } - checkMetrics(env, 1, std::nullopt, 4, 2, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 4, 2, 256); env.close(); // Alice's queued transaction failed in TxQ::accept // with tefPAST_SEQ - checkMetrics(env, 0, 8, 0, 4, 256); + checkMetrics(__LINE__, env, 0, 8, 0, 4, 256); } void @@ -1028,7 +1092,7 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(env.current()->fees().base == 10); - checkMetrics(env, 0, std::nullopt, 0, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 3, 256); // ledgers in queue is 2 because of makeConfig auto const initQueueMax = initFee(env, 3, 2, 10, 10, 200, 50); @@ -1036,11 +1100,11 @@ class TxQ1_test : public beast::unit_test::suite // Create several accounts while the fee is cheap so they all apply. env.fund(drops(2000), noripple(alice)); env.fund(XRP(500000), noripple(bob, charlie, daria)); - checkMetrics(env, 0, initQueueMax, 4, 3, 256); + checkMetrics(__LINE__, env, 0, initQueueMax, 4, 3, 256); // Alice - price starts exploding: held env(noop(alice), fee(11), queued); - checkMetrics(env, 1, initQueueMax, 4, 3, 256); + checkMetrics(__LINE__, env, 1, initQueueMax, 4, 3, 256); auto aliceSeq = env.seq(alice); auto bobSeq = env.seq(bob); @@ -1048,28 +1112,28 @@ class TxQ1_test : public beast::unit_test::suite // Alice - try to queue a second transaction, but leave a gap env(noop(alice), seq(aliceSeq + 2), fee(100), ter(telCAN_NOT_QUEUE)); - checkMetrics(env, 1, initQueueMax, 4, 3, 256); + checkMetrics(__LINE__, env, 1, initQueueMax, 4, 3, 256); // Alice - queue a second transaction. Yay! env(noop(alice), seq(aliceSeq + 1), fee(13), queued); - checkMetrics(env, 2, initQueueMax, 4, 3, 256); + checkMetrics(__LINE__, env, 2, initQueueMax, 4, 3, 256); // Alice - queue a third transaction. Yay. env(noop(alice), seq(aliceSeq + 2), fee(17), queued); - checkMetrics(env, 3, initQueueMax, 4, 3, 256); + checkMetrics(__LINE__, env, 3, initQueueMax, 4, 3, 256); // Bob - queue a transaction env(noop(bob), queued); - checkMetrics(env, 4, initQueueMax, 4, 3, 256); + checkMetrics(__LINE__, env, 4, initQueueMax, 4, 3, 256); // Bob - queue a second transaction env(noop(bob), seq(bobSeq + 1), fee(50), queued); - checkMetrics(env, 5, initQueueMax, 4, 3, 256); + checkMetrics(__LINE__, env, 5, initQueueMax, 4, 3, 256); // Charlie - queue a transaction, with a higher fee // than default env(noop(charlie), fee(15), queued); - checkMetrics(env, 6, initQueueMax, 4, 3, 256); + checkMetrics(__LINE__, env, 6, initQueueMax, 4, 3, 256); BEAST_EXPECT(env.seq(alice) == aliceSeq); BEAST_EXPECT(env.seq(bob) == bobSeq); @@ -1078,7 +1142,7 @@ class TxQ1_test : public beast::unit_test::suite env.close(); // Verify that all of but one of the queued transactions // got applied. - checkMetrics(env, 1, 8, 5, 4, 256); + checkMetrics(__LINE__, env, 1, 8, 5, 4, 256); // Verify that the stuck transaction is Bob's second. // Even though it had a higher fee than Alice's and @@ -1100,10 +1164,10 @@ class TxQ1_test : public beast::unit_test::suite queued); ++aliceSeq; } - checkMetrics(env, 8, 8, 5, 4, 513); + checkMetrics(__LINE__, env, 8, 8, 5, 4, 513); { auto& txQ = env.app().getTxQ(); - auto aliceStat = txQ.getAccountTxs(alice.id(), *env.current()); + auto aliceStat = txQ.getAccountTxs(alice.id()); aliceFee = 27; auto const& baseFee = env.current()->fees().base; auto seq = env.seq(alice); @@ -1131,24 +1195,24 @@ class TxQ1_test : public beast::unit_test::suite json(jss::LastLedgerSequence, lastLedgerSeq + 7), fee(aliceFee), ter(telCAN_NOT_QUEUE_FULL)); - checkMetrics(env, 8, 8, 5, 4, 513); + checkMetrics(__LINE__, env, 8, 8, 5, 4, 513); // Charlie - try to add another item to the queue, // which fails because fee is lower than Alice's // queued average. env(noop(charlie), fee(19), ter(telCAN_NOT_QUEUE_FULL)); - checkMetrics(env, 8, 8, 5, 4, 513); + checkMetrics(__LINE__, env, 8, 8, 5, 4, 513); // Charlie - add another item to the queue, which // causes Alice's last txn to drop env(noop(charlie), fee(30), queued); - checkMetrics(env, 8, 8, 5, 4, 538); + checkMetrics(__LINE__, env, 8, 8, 5, 4, 538); // Alice - now attempt to add one more to the queue, // which fails because the last tx was dropped, so // there is no complete chain. env(noop(alice), seq(aliceSeq), fee(aliceFee), ter(telCAN_NOT_QUEUE)); - checkMetrics(env, 8, 8, 5, 4, 538); + checkMetrics(__LINE__, env, 8, 8, 5, 4, 538); // Alice wants this tx more than the dropped tx, // so resubmits with higher fee, but the queue @@ -1157,7 +1221,7 @@ class TxQ1_test : public beast::unit_test::suite seq(aliceSeq - 1), fee(aliceFee), ter(telCAN_NOT_QUEUE_FULL)); - checkMetrics(env, 8, 8, 5, 4, 538); + checkMetrics(__LINE__, env, 8, 8, 5, 4, 538); // Try to replace a middle item in the queue // without enough fee. @@ -1167,18 +1231,18 @@ class TxQ1_test : public beast::unit_test::suite seq(aliceSeq), fee(aliceFee), ter(telCAN_NOT_QUEUE_FEE)); - checkMetrics(env, 8, 8, 5, 4, 538); + checkMetrics(__LINE__, env, 8, 8, 5, 4, 538); // Replace a middle item from the queue successfully ++aliceFee; env(noop(alice), seq(aliceSeq), fee(aliceFee), queued); - checkMetrics(env, 8, 8, 5, 4, 538); + checkMetrics(__LINE__, env, 8, 8, 5, 4, 538); env.close(); // Alice's transactions processed, along with // Charlie's, and the lost one is replayed and // added back to the queue. - checkMetrics(env, 4, 10, 6, 5, 256); + checkMetrics(__LINE__, env, 4, 10, 6, 5, 256); aliceSeq = env.seq(alice) + 1; @@ -1192,18 +1256,18 @@ class TxQ1_test : public beast::unit_test::suite seq(aliceSeq), fee(aliceFee), ter(telCAN_NOT_QUEUE_BALANCE)); - checkMetrics(env, 4, 10, 6, 5, 256); + checkMetrics(__LINE__, env, 4, 10, 6, 5, 256); // Try to spend more than Alice can afford with all the other txs. aliceSeq += 2; env(noop(alice), seq(aliceSeq), fee(aliceFee), ter(terINSUF_FEE_B)); - checkMetrics(env, 4, 10, 6, 5, 256); + checkMetrics(__LINE__, env, 4, 10, 6, 5, 256); // Replace the last queued item with a transaction that will // bankrupt Alice --aliceFee; env(noop(alice), seq(aliceSeq), fee(aliceFee), queued); - checkMetrics(env, 4, 10, 6, 5, 256); + checkMetrics(__LINE__, env, 4, 10, 6, 5, 256); // Alice - Attempt to queue a last transaction, but it // fails because the fee in flight is too high, before @@ -1214,14 +1278,14 @@ class TxQ1_test : public beast::unit_test::suite seq(aliceSeq), fee(aliceFee), ter(telCAN_NOT_QUEUE_BALANCE)); - checkMetrics(env, 4, 10, 6, 5, 256); + checkMetrics(__LINE__, env, 4, 10, 6, 5, 256); env.close(); // All of Alice's transactions applied. - checkMetrics(env, 0, 12, 4, 6, 256); + checkMetrics(__LINE__, env, 0, 12, 4, 6, 256); env.close(); - checkMetrics(env, 0, 12, 0, 6, 256); + checkMetrics(__LINE__, env, 0, 12, 0, 6, 256); // Alice is broke env.require(balance(alice, XRP(0))); @@ -1231,17 +1295,17 @@ class TxQ1_test : public beast::unit_test::suite // account limit (10) txs. fillQueue(env, bob); bobSeq = env.seq(bob); - checkMetrics(env, 0, 12, 7, 6, 256); + checkMetrics(__LINE__, env, 0, 12, 7, 6, 256); for (int i = 0; i < 10; ++i) env(noop(bob), seq(bobSeq + i), queued); - checkMetrics(env, 10, 12, 7, 6, 256); + checkMetrics(__LINE__, env, 10, 12, 7, 6, 256); // Bob hit the single account limit env(noop(bob), seq(bobSeq + 10), ter(telCAN_NOT_QUEUE_FULL)); - checkMetrics(env, 10, 12, 7, 6, 256); + checkMetrics(__LINE__, env, 10, 12, 7, 6, 256); // Bob can replace one of the earlier txs regardless // of the limit env(noop(bob), seq(bobSeq + 5), fee(20), queued); - checkMetrics(env, 10, 12, 7, 6, 256); + checkMetrics(__LINE__, env, 10, 12, 7, 6, 256); // Try to replace a middle item in the queue // with enough fee to bankrupt bob and make the @@ -1252,7 +1316,7 @@ class TxQ1_test : public beast::unit_test::suite seq(bobSeq + 5), fee(bobFee), ter(telCAN_NOT_QUEUE_BALANCE)); - checkMetrics(env, 10, 12, 7, 6, 256); + checkMetrics(__LINE__, env, 10, 12, 7, 6, 256); // Attempt to replace a middle item in the queue with enough fee // to bankrupt bob, and also to use fee averaging to clear out the @@ -1266,14 +1330,14 @@ class TxQ1_test : public beast::unit_test::suite seq(bobSeq + 5), fee(bobFee), ter(telCAN_NOT_QUEUE_BALANCE)); - checkMetrics(env, 10, 12, 7, 6, 256); + checkMetrics(__LINE__, env, 10, 12, 7, 6, 256); // Close the ledger and verify that the queued transactions succeed // and bob has the right ending balance. env.close(); - checkMetrics(env, 3, 14, 8, 7, 256); + checkMetrics(__LINE__, env, 3, 14, 8, 7, 256); env.close(); - checkMetrics(env, 0, 16, 3, 8, 256); + checkMetrics(__LINE__, env, 0, 16, 3, 8, 256); env.require(balance(bob, drops(499'999'999'750))); } @@ -1299,20 +1363,20 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(env.current()->fees().base == 10); - checkMetrics(env, 0, std::nullopt, 0, 4, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 4, 256); // Create several accounts while the fee is cheap so they all apply. env.fund(XRP(50000), noripple(alice, bob, charlie, daria)); - checkMetrics(env, 0, std::nullopt, 4, 4, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 4, 4, 256); env.close(); - checkMetrics(env, 0, 8, 0, 4, 256); + checkMetrics(__LINE__, env, 0, 8, 0, 4, 256); env.fund(XRP(50000), noripple(elmo, fred, gwen, hank)); - checkMetrics(env, 0, 8, 4, 4, 256); + checkMetrics(__LINE__, env, 0, 8, 4, 4, 256); env.close(); - checkMetrics(env, 0, 8, 0, 4, 256); + checkMetrics(__LINE__, env, 0, 8, 0, 4, 256); ////////////////////////////////////////////////////////////// @@ -1323,7 +1387,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(gwen)); env(noop(fred)); env(noop(elmo)); - checkMetrics(env, 0, 8, 5, 4, 256); + checkMetrics(__LINE__, env, 0, 8, 5, 4, 256); auto aliceSeq = env.seq(alice); auto bobSeq = env.seq(bob); @@ -1336,8 +1400,8 @@ class TxQ1_test : public beast::unit_test::suite // This time, use identical fees. - // This one gets into the queue, but gets dropped when the - // higher fee one is added later. + // All of these get into the queue, but one gets dropped when the + // higher fee one is added later. Which one depends on ordering. env(noop(alice), fee(15), queued); env(noop(bob), fee(15), queued); env(noop(charlie), fee(15), queued); @@ -1349,7 +1413,7 @@ class TxQ1_test : public beast::unit_test::suite // Queue is full now. Minimum fee now reflects the // lowest fee in the queue. - checkMetrics(env, 8, 8, 5, 4, 385); + checkMetrics(__LINE__, env, 8, 8, 5, 4, 385); // Try to add another transaction with the default (low) fee, // it should fail because it can't replace the one already @@ -1362,60 +1426,165 @@ class TxQ1_test : public beast::unit_test::suite env(noop(charlie), fee(100), seq(charlieSeq + 1), queued); // Queue is still full. - checkMetrics(env, 8, 8, 5, 4, 385); + checkMetrics(__LINE__, env, 8, 8, 5, 4, 385); - // bob, charlie, daria, elmo, and fred's txs - // are processed out of the queue into the ledger, - // leaving fred and hank's txs. alice's tx is - // retried from localTxs, and put back into the - // queue. + // Six txs are processed out of the queue into the ledger, + // leaving two txs. The dropped tx is retried from localTxs, and + // put back into the queue. env.close(); - checkMetrics(env, 3, 10, 6, 5, 256); - - BEAST_EXPECT(aliceSeq + 1 == env.seq(alice)); - BEAST_EXPECT(bobSeq + 1 == env.seq(bob)); - BEAST_EXPECT(charlieSeq == env.seq(charlie)); - BEAST_EXPECT(dariaSeq + 1 == env.seq(daria)); - BEAST_EXPECT(elmoSeq == env.seq(elmo)); - BEAST_EXPECT(fredSeq + 1 == env.seq(fred)); - BEAST_EXPECT(gwenSeq + 1 == env.seq(gwen)); - BEAST_EXPECT(hankSeq + 1 == env.seq(hank)); - - aliceSeq = env.seq(alice); - bobSeq = env.seq(bob); - charlieSeq = env.seq(charlie); - dariaSeq = env.seq(daria); - elmoSeq = env.seq(elmo); - fredSeq = env.seq(fred); + checkMetrics(__LINE__, env, 3, 10, 6, 5, 256); + + // This next test should remain unchanged regardless of + // transaction ordering + BEAST_EXPECT( + aliceSeq + bobSeq + charlieSeq + dariaSeq + elmoSeq + fredSeq + + gwenSeq + hankSeq + 6 == + env.seq(alice) + env.seq(bob) + env.seq(charlie) + env.seq(daria) + + env.seq(elmo) + env.seq(fred) + env.seq(gwen) + env.seq(hank)); + // These tests may change if TxQ ordering is changed + using namespace std::string_literals; + BEAST_EXPECTS( + aliceSeq + 1 == env.seq(alice), + "alice: "s + std::to_string(aliceSeq) + ", " + + std::to_string(env.seq(alice))); + BEAST_EXPECTS( + bobSeq + 1 == env.seq(bob), + "bob: "s + std::to_string(bobSeq) + ", " + + std::to_string(env.seq(bob))); + BEAST_EXPECTS( + charlieSeq + 2 == env.seq(charlie), + "charlie: "s + std::to_string(charlieSeq) + ", " + + std::to_string(env.seq(charlie))); + BEAST_EXPECTS( + dariaSeq == env.seq(daria), + "daria: "s + std::to_string(dariaSeq) + ", " + + std::to_string(env.seq(daria))); + BEAST_EXPECTS( + elmoSeq + 1 == env.seq(elmo), + "elmo: "s + std::to_string(elmoSeq) + ", " + + std::to_string(env.seq(elmo))); + BEAST_EXPECTS( + fredSeq == env.seq(fred), + "fred: "s + std::to_string(fredSeq) + ", " + + std::to_string(env.seq(fred))); + BEAST_EXPECTS( + gwenSeq + 1 == env.seq(gwen), + "gwen: "s + std::to_string(gwenSeq) + ", " + + std::to_string(env.seq(gwen))); + BEAST_EXPECTS( + hankSeq == env.seq(hank), + "hank: "s + std::to_string(hankSeq) + ", " + + std::to_string(env.seq(hank))); + + // Which sequences get incremented may change if TxQ ordering is + // changed + ++aliceSeq; + ++bobSeq; + ++(++charlieSeq); + // ++dariaSeq; + ++elmoSeq; + // ++fredSeq; + ++gwenSeq; + // ++hankSeq; + + auto getTxsQueued = [&]() { + auto const txs = env.app().getTxQ().getTxs(); + std::map result; + for (auto const& tx : txs) + { + ++result[tx.txn->at(sfAccount)]; + } + return result; + }; + auto qTxCount1 = getTxsQueued(); + BEAST_EXPECT(qTxCount1.size() <= 3); // Fill up the queue again - env(noop(fred), fee(15), queued); - env(noop(fred), seq(fredSeq + 1), fee(15), queued); - env(noop(fred), seq(fredSeq + 2), fee(15), queued); - env(noop(bob), fee(15), queued); - env(noop(charlie), seq(charlieSeq + 2), fee(15), queued); - env(noop(daria), fee(15), queued); - // This one gets into the queue, but gets dropped when the - // higher fee one is added later. - env(noop(elmo), seq(elmoSeq + 1), fee(15), queued); - checkMetrics(env, 10, 10, 6, 5, 385); + env(noop(alice), + seq(aliceSeq + qTxCount1[alice.id()]++), + fee(15), + queued); + env(noop(bob), seq(bobSeq + qTxCount1[bob.id()]++), fee(15), queued); + env(noop(charlie), + seq(charlieSeq + qTxCount1[charlie.id()]++), + fee(15), + queued); + env(noop(daria), + seq(dariaSeq + qTxCount1[daria.id()]++), + fee(15), + queued); + env(noop(elmo), seq(elmoSeq + qTxCount1[elmo.id()]++), fee(15), queued); + env(noop(fred), seq(fredSeq + qTxCount1[fred.id()]++), fee(15), queued); + env(noop(gwen), seq(gwenSeq + qTxCount1[gwen.id()]++), fee(15), queued); + checkMetrics(__LINE__, env, 10, 10, 6, 5, 385); // Add another transaction, with a higher fee, // Not high enough to get into the ledger, but high // enough to get into the queue (and kick somebody out) - env(noop(fred), fee(100), seq(fredSeq + 3), queued); + env(noop(alice), + fee(100), + seq(aliceSeq + qTxCount1[alice.id()]++), + queued); + checkMetrics(__LINE__, env, 10, 10, 6, 5, 385); + + // Seven txs are processed out of the queue, leaving 3. One + // dropped tx is retried from localTxs, and put back into the + // queue. env.close(); - checkMetrics(env, 4, 12, 7, 6, 256); - - BEAST_EXPECT(fredSeq + 4 == env.seq(fred)); - BEAST_EXPECT(gwenSeq + 1 == env.seq(gwen)); - BEAST_EXPECT(hankSeq + 1 == env.seq(hank)); - BEAST_EXPECT(aliceSeq == env.seq(alice)); - BEAST_EXPECT(bobSeq + 1 == env.seq(bob)); - BEAST_EXPECT(charlieSeq + 2 == env.seq(charlie)); - BEAST_EXPECT(dariaSeq == env.seq(daria)); - BEAST_EXPECT(elmoSeq == env.seq(elmo)); + checkMetrics(__LINE__, env, 4, 12, 7, 6, 256); + + // Refresh the queue counts + auto qTxCount2 = getTxsQueued(); + BEAST_EXPECT(qTxCount2.size() <= 4); + + // This next test should remain unchanged regardless of + // transaction ordering + BEAST_EXPECT( + aliceSeq + bobSeq + charlieSeq + dariaSeq + elmoSeq + fredSeq + + gwenSeq + hankSeq + 7 == + env.seq(alice) + env.seq(bob) + env.seq(charlie) + env.seq(daria) + + env.seq(elmo) + env.seq(fred) + env.seq(gwen) + env.seq(hank)); + // These tests may change if TxQ ordering is changed + BEAST_EXPECTS( + aliceSeq + qTxCount1[alice.id()] - qTxCount2[alice.id()] == + env.seq(alice), + "alice: "s + std::to_string(aliceSeq) + ", " + + std::to_string(env.seq(alice))); + BEAST_EXPECTS( + bobSeq + qTxCount1[bob.id()] - qTxCount2[bob.id()] == env.seq(bob), + "bob: "s + std::to_string(bobSeq) + ", " + + std::to_string(env.seq(bob))); + BEAST_EXPECTS( + charlieSeq + qTxCount1[charlie.id()] - qTxCount2[charlie.id()] == + env.seq(charlie), + "charlie: "s + std::to_string(charlieSeq) + ", " + + std::to_string(env.seq(charlie))); + BEAST_EXPECTS( + dariaSeq + qTxCount1[daria.id()] - qTxCount2[daria.id()] == + env.seq(daria), + "daria: "s + std::to_string(dariaSeq) + ", " + + std::to_string(env.seq(daria))); + BEAST_EXPECTS( + elmoSeq + qTxCount1[elmo.id()] - qTxCount2[elmo.id()] == + env.seq(elmo), + "elmo: "s + std::to_string(elmoSeq) + ", " + + std::to_string(env.seq(elmo))); + BEAST_EXPECTS( + fredSeq + qTxCount1[fred.id()] - qTxCount2[fred.id()] == + env.seq(fred), + "fred: "s + std::to_string(fredSeq) + ", " + + std::to_string(env.seq(fred))); + BEAST_EXPECTS( + gwenSeq + qTxCount1[gwen.id()] - qTxCount2[gwen.id()] == + env.seq(gwen), + "gwen: "s + std::to_string(gwenSeq) + ", " + + std::to_string(env.seq(gwen))); + BEAST_EXPECTS( + hankSeq + qTxCount1[hank.id()] - qTxCount2[hank.id()] == + env.seq(hank), + "hank: "s + std::to_string(hankSeq) + ", " + + std::to_string(env.seq(hank))); } void @@ -1430,13 +1599,13 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(env.current()->fees().base == 10); - checkMetrics(env, 0, std::nullopt, 0, 1, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 1, 256); env.fund(XRP(50000), noripple(alice)); - checkMetrics(env, 0, std::nullopt, 1, 1, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 1, 1, 256); env(fset(alice, asfAccountTxnID)); - checkMetrics(env, 0, std::nullopt, 2, 1, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 2, 1, 256); // Immediately after the fset, the sfAccountTxnID field // is still uninitialized, so preflight succeeds here, @@ -1445,14 +1614,14 @@ class TxQ1_test : public beast::unit_test::suite json(R"({"AccountTxnID": "0"})"), ter(telCAN_NOT_QUEUE)); - checkMetrics(env, 0, std::nullopt, 2, 1, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 2, 1, 256); env.close(); // The failed transaction is retried from LocalTx // and succeeds. - checkMetrics(env, 0, 4, 1, 2, 256); + checkMetrics(__LINE__, env, 0, 4, 1, 2, 256); env(noop(alice)); - checkMetrics(env, 0, 4, 2, 2, 256); + checkMetrics(__LINE__, env, 0, 4, 2, 2, 256); env(noop(alice), json(R"({"AccountTxnID": "0"})"), ter(tefWRONG_PRIOR)); } @@ -1475,19 +1644,19 @@ class TxQ1_test : public beast::unit_test::suite auto alice = Account("alice"); - checkMetrics(env, 0, std::nullopt, 0, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 2, 256); env.fund(XRP(50000), noripple(alice)); - checkMetrics(env, 0, std::nullopt, 1, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 1, 2, 256); for (int i = 0; i < 10; ++i) env(noop(alice), openLedgerFee(env)); - checkMetrics(env, 0, std::nullopt, 11, 2, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 11, 2, 256); env.close(); // If not for the maximum, the per ledger would be 11. - checkMetrics(env, 0, 10, 0, 5, 256, 800025); + checkMetrics(__LINE__, env, 0, 10, 0, 5, 256, 800025); } try @@ -1577,22 +1746,22 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(env.current()->fees().base == 10); - checkMetrics(env, 0, initQueueMax, 0, 3, 256); + checkMetrics(__LINE__, env, 0, initQueueMax, 0, 3, 256); env.fund(drops(5000), noripple(alice)); env.fund(XRP(50000), noripple(bob)); - checkMetrics(env, 0, initQueueMax, 2, 3, 256); + checkMetrics(__LINE__, env, 0, initQueueMax, 2, 3, 256); auto USD = bob["USD"]; env(offer(alice, USD(5000), drops(5000)), require(owners(alice, 1))); - checkMetrics(env, 0, initQueueMax, 3, 3, 256); + checkMetrics(__LINE__, env, 0, initQueueMax, 3, 3, 256); env.close(); - checkMetrics(env, 0, 6, 0, 3, 256); + checkMetrics(__LINE__, env, 0, 6, 0, 3, 256); // Fill up the ledger fillQueue(env, alice); - checkMetrics(env, 0, 6, 4, 3, 256); + checkMetrics(__LINE__, env, 0, 6, 4, 3, 256); // Queue up a couple of transactions, plus one // more expensive one. @@ -1601,7 +1770,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), seq(aliceSeq++), queued); env(noop(alice), seq(aliceSeq++), queued); env(noop(alice), fee(drops(1000)), seq(aliceSeq), queued); - checkMetrics(env, 4, 6, 4, 3, 256); + checkMetrics(__LINE__, env, 4, 6, 4, 3, 256); // This offer should take Alice's offer // up to Alice's reserve. @@ -1609,7 +1778,7 @@ class TxQ1_test : public beast::unit_test::suite openLedgerFee(env), require( balance(alice, drops(250)), owners(alice, 1), lines(alice, 1))); - checkMetrics(env, 4, 6, 5, 3, 256); + checkMetrics(__LINE__, env, 4, 6, 5, 3, 256); // Try adding a new transaction. // Too many fees in flight. @@ -1617,12 +1786,12 @@ class TxQ1_test : public beast::unit_test::suite fee(drops(200)), seq(aliceSeq + 1), ter(telCAN_NOT_QUEUE_BALANCE)); - checkMetrics(env, 4, 6, 5, 3, 256); + checkMetrics(__LINE__, env, 4, 6, 5, 3, 256); // Close the ledger. All of Alice's transactions // take a fee, except the last one. env.close(); - checkMetrics(env, 1, 10, 3, 5, 256); + checkMetrics(__LINE__, env, 1, 10, 3, 5, 256); env.require(balance(alice, drops(250 - 30))); // Still can't add a new transaction for Alice, @@ -1631,7 +1800,7 @@ class TxQ1_test : public beast::unit_test::suite fee(drops(200)), seq(aliceSeq + 1), ter(telCAN_NOT_QUEUE_BALANCE)); - checkMetrics(env, 1, 10, 3, 5, 256); + checkMetrics(__LINE__, env, 1, 10, 3, 5, 256); /* At this point, Alice's transaction is indefinitely stuck in the queue. Eventually it will either @@ -1643,13 +1812,13 @@ class TxQ1_test : public beast::unit_test::suite for (int i = 0; i < 9; ++i) { env.close(); - checkMetrics(env, 1, 10, 0, 5, 256); + checkMetrics(__LINE__, env, 1, 10, 0, 5, 256); } // And Alice's transaction expires (via the retry limit, // not LastLedgerSequence). env.close(); - checkMetrics(env, 0, 10, 0, 5, 256); + checkMetrics(__LINE__, env, 0, 10, 0, 5, 256); } void @@ -1669,11 +1838,11 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(env.current()->fees().base == 10); - checkMetrics(env, 0, std::nullopt, 0, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 3, 256); env.fund(XRP(50000), noripple(alice, bob)); env.memoize(charlie); - checkMetrics(env, 0, std::nullopt, 2, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 2, 3, 256); { // Cannot put a blocker in an account's queue if that queue // already holds two or more (non-blocker) entries. @@ -1682,7 +1851,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice)); // Set a regular key just to clear the password spent flag env(regkey(alice, charlie)); - checkMetrics(env, 0, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 4, 3, 256); // Put two "normal" txs in the queue auto const aliceSeq = env.seq(alice); @@ -1708,11 +1877,11 @@ class TxQ1_test : public beast::unit_test::suite // Other accounts are not affected env(noop(bob), queued); - checkMetrics(env, 3, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 3, std::nullopt, 4, 3, 256); // Drain the queue. env.close(); - checkMetrics(env, 0, 8, 4, 4, 256); + checkMetrics(__LINE__, env, 0, 8, 4, 4, 256); } { // Replace a lone non-blocking tx with a blocker. @@ -1750,7 +1919,7 @@ class TxQ1_test : public beast::unit_test::suite // Drain the queue. env.close(); - checkMetrics(env, 0, 10, 3, 5, 256); + checkMetrics(__LINE__, env, 0, 10, 3, 5, 256); } { // Put a blocker in an empty queue. @@ -1778,7 +1947,7 @@ class TxQ1_test : public beast::unit_test::suite // Drain the queue. env.close(); - checkMetrics(env, 0, 12, 3, 6, 256); + checkMetrics(__LINE__, env, 0, 12, 3, 6, 256); } } @@ -1799,12 +1968,12 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(env.current()->fees().base == 10); - checkMetrics(env, 0, std::nullopt, 0, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 3, 256); env.fund(XRP(50000), noripple(alice, bob)); env.memoize(charlie); - checkMetrics(env, 0, std::nullopt, 2, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 2, 3, 256); std::uint32_t tkt{env.seq(alice) + 1}; { @@ -1815,7 +1984,7 @@ class TxQ1_test : public beast::unit_test::suite env(ticket::create(alice, 250), seq(tkt - 1)); // Set a regular key just to clear the password spent flag env(regkey(alice, charlie)); - checkMetrics(env, 0, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 4, 3, 256); // Put two "normal" txs in the queue auto const aliceSeq = env.seq(alice); @@ -1845,11 +2014,11 @@ class TxQ1_test : public beast::unit_test::suite // Other accounts are not affected env(noop(bob), queued); - checkMetrics(env, 3, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 3, std::nullopt, 4, 3, 256); // Drain the queue and local transactions. env.close(); - checkMetrics(env, 0, 8, 5, 4, 256); + checkMetrics(__LINE__, env, 0, 8, 5, 4, 256); // Show that the local transactions have flushed through as well. BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); @@ -1906,7 +2075,7 @@ class TxQ1_test : public beast::unit_test::suite // Drain the queue. env.close(); - checkMetrics(env, 0, 10, 4, 5, 256); + checkMetrics(__LINE__, env, 0, 10, 4, 5, 256); // Show that the local transactions have flushed through as well. BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); @@ -1940,7 +2109,7 @@ class TxQ1_test : public beast::unit_test::suite // Drain the queue. env.close(); - checkMetrics(env, 0, 12, 3, 6, 256); + checkMetrics(__LINE__, env, 0, 12, 3, 6, 256); } } @@ -1972,10 +2141,10 @@ class TxQ1_test : public beast::unit_test::suite auto limit = 3; - checkMetrics(env, 0, initQueueMax, 0, limit, 256); + checkMetrics(__LINE__, env, 0, initQueueMax, 0, limit, 256); env.fund(XRP(50000), noripple(alice, charlie), gw); - checkMetrics(env, 0, initQueueMax, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 0, initQueueMax, limit + 1, limit, 256); auto USD = gw["USD"]; auto BUX = gw["BUX"]; @@ -1990,16 +2159,16 @@ class TxQ1_test : public beast::unit_test::suite // If this offer crosses, all of alice's // XRP will be taken (except the reserve). env(offer(alice, BUX(5000), XRP(50000)), queued); - checkMetrics(env, 1, initQueueMax, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 1, initQueueMax, limit + 1, limit, 256); // But because the reserve is protected, another // transaction will be allowed to queue env(noop(alice), seq(aliceSeq + 1), queued); - checkMetrics(env, 2, initQueueMax, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 2, initQueueMax, limit + 1, limit, 256); env.close(); ++limit; - checkMetrics(env, 0, limit * 2, 2, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, 2, limit, 256); // But once we close the ledger, we find alice // has plenty of XRP, because the offer didn't @@ -2011,7 +2180,7 @@ class TxQ1_test : public beast::unit_test::suite ////////////////////////////////////////// // Offer with high XRP out and high total fee blocks later txs fillQueue(env, alice); - checkMetrics(env, 0, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, limit + 1, limit, 256); aliceSeq = env.seq(alice); aliceBal = env.balance(alice); @@ -2019,12 +2188,12 @@ class TxQ1_test : public beast::unit_test::suite // Alice creates an offer with a fee of half the reserve env(offer(alice, BUX(5000), XRP(50000)), fee(drops(100)), queued); - checkMetrics(env, 1, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 1, limit * 2, limit + 1, limit, 256); // Alice creates another offer with a fee // that brings the total to just shy of the reserve env(noop(alice), fee(drops(99)), seq(aliceSeq + 1), queued); - checkMetrics(env, 2, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 2, limit * 2, limit + 1, limit, 256); // So even a noop will look like alice // doesn't have the balance to pay the fee @@ -2032,11 +2201,11 @@ class TxQ1_test : public beast::unit_test::suite fee(drops(51)), seq(aliceSeq + 2), ter(terINSUF_FEE_B)); - checkMetrics(env, 2, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 2, limit * 2, limit + 1, limit, 256); env.close(); ++limit; - checkMetrics(env, 0, limit * 2, 3, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, 3, limit, 256); // But once we close the ledger, we find alice // has plenty of XRP, because the offer didn't @@ -2048,7 +2217,7 @@ class TxQ1_test : public beast::unit_test::suite ////////////////////////////////////////// // Offer with high XRP out and super high fee blocks later txs fillQueue(env, alice); - checkMetrics(env, 0, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, limit + 1, limit, 256); aliceSeq = env.seq(alice); aliceBal = env.balance(alice); @@ -2057,7 +2226,7 @@ class TxQ1_test : public beast::unit_test::suite // Alice creates an offer with a fee larger than the reserve // This one can queue because it's the first in the queue for alice env(offer(alice, BUX(5000), XRP(50000)), fee(drops(300)), queued); - checkMetrics(env, 1, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 1, limit * 2, limit + 1, limit, 256); // So even a noop will look like alice // doesn't have the balance to pay the fee @@ -2065,11 +2234,11 @@ class TxQ1_test : public beast::unit_test::suite fee(drops(51)), seq(aliceSeq + 1), ter(telCAN_NOT_QUEUE_BALANCE)); - checkMetrics(env, 1, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 1, limit * 2, limit + 1, limit, 256); env.close(); ++limit; - checkMetrics(env, 0, limit * 2, 2, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, 2, limit, 256); // But once we close the ledger, we find alice // has plenty of XRP, because the offer didn't @@ -2081,7 +2250,7 @@ class TxQ1_test : public beast::unit_test::suite ////////////////////////////////////////// // Offer with low XRP out allows later txs fillQueue(env, alice); - checkMetrics(env, 0, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, limit + 1, limit, 256); aliceSeq = env.seq(alice); aliceBal = env.balance(alice); @@ -2091,11 +2260,11 @@ class TxQ1_test : public beast::unit_test::suite // And later transactions are just fine env(noop(alice), seq(aliceSeq + 1), queued); - checkMetrics(env, 2, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 2, limit * 2, limit + 1, limit, 256); env.close(); ++limit; - checkMetrics(env, 0, limit * 2, 2, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, 2, limit, 256); // But once we close the ledger, we find alice // has plenty of XRP, because the offer didn't @@ -2107,7 +2276,7 @@ class TxQ1_test : public beast::unit_test::suite ////////////////////////////////////////// // Large XRP payment doesn't block later txs fillQueue(env, alice); - checkMetrics(env, 0, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, limit + 1, limit, 256); aliceSeq = env.seq(alice); aliceBal = env.balance(alice); @@ -2120,11 +2289,11 @@ class TxQ1_test : public beast::unit_test::suite // But because the reserve is protected, another // transaction will be allowed to queue env(noop(alice), seq(aliceSeq + 1), queued); - checkMetrics(env, 2, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 2, limit * 2, limit + 1, limit, 256); env.close(); ++limit; - checkMetrics(env, 0, limit * 2, 2, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, 2, limit, 256); // But once we close the ledger, we find alice // still has most of her balance, because the @@ -2134,7 +2303,7 @@ class TxQ1_test : public beast::unit_test::suite ////////////////////////////////////////// // Small XRP payment allows later txs fillQueue(env, alice); - checkMetrics(env, 0, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, limit + 1, limit, 256); aliceSeq = env.seq(alice); aliceBal = env.balance(alice); @@ -2145,11 +2314,11 @@ class TxQ1_test : public beast::unit_test::suite // And later transactions are just fine env(noop(alice), seq(aliceSeq + 1), queued); - checkMetrics(env, 2, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 2, limit * 2, limit + 1, limit, 256); env.close(); ++limit; - checkMetrics(env, 0, limit * 2, 2, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, 2, limit, 256); // The payment succeeds env.require( @@ -2160,19 +2329,19 @@ class TxQ1_test : public beast::unit_test::suite auto const amount = USD(500000); env(trust(alice, USD(50000000))); env(trust(charlie, USD(50000000))); - checkMetrics(env, 0, limit * 2, 4, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, 4, limit, 256); // Close so we don't have to deal // with tx ordering in consensus. env.close(); env(pay(gw, alice, amount)); - checkMetrics(env, 0, limit * 2, 1, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, 1, limit, 256); // Close so we don't have to deal // with tx ordering in consensus. env.close(); fillQueue(env, alice); - checkMetrics(env, 0, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, limit + 1, limit, 256); aliceSeq = env.seq(alice); aliceBal = env.balance(alice); @@ -2185,11 +2354,11 @@ class TxQ1_test : public beast::unit_test::suite // But that's fine, because it doesn't affect // alice's XRP balance (other than the fee, of course). env(noop(alice), seq(aliceSeq + 1), queued); - checkMetrics(env, 2, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 2, limit * 2, limit + 1, limit, 256); env.close(); ++limit; - checkMetrics(env, 0, limit * 2, 2, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, 2, limit, 256); // So once we close the ledger, alice has her // XRP balance, but her USD balance went to charlie. @@ -2209,7 +2378,7 @@ class TxQ1_test : public beast::unit_test::suite env.close(); fillQueue(env, charlie); - checkMetrics(env, 0, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, limit + 1, limit, 256); aliceSeq = env.seq(alice); aliceBal = env.balance(alice); @@ -2225,11 +2394,11 @@ class TxQ1_test : public beast::unit_test::suite // But because the reserve is protected, another // transaction will be allowed to queue env(noop(alice), seq(aliceSeq + 1), queued); - checkMetrics(env, 2, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 2, limit * 2, limit + 1, limit, 256); env.close(); ++limit; - checkMetrics(env, 0, limit * 2, 2, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, 2, limit, 256); // So once we close the ledger, alice sent a payment // to charlie using only a portion of her XRP balance @@ -2244,7 +2413,7 @@ class TxQ1_test : public beast::unit_test::suite // Small XRP to IOU payment allows later txs. fillQueue(env, charlie); - checkMetrics(env, 0, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, limit + 1, limit, 256); aliceSeq = env.seq(alice); aliceBal = env.balance(alice); @@ -2259,11 +2428,11 @@ class TxQ1_test : public beast::unit_test::suite // And later transactions are just fine env(noop(alice), seq(aliceSeq + 1), queued); - checkMetrics(env, 2, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 2, limit * 2, limit + 1, limit, 256); env.close(); ++limit; - checkMetrics(env, 0, limit * 2, 2, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, 2, limit, 256); // So once we close the ledger, alice sent a payment // to charlie using only a portion of her XRP balance @@ -2280,7 +2449,7 @@ class TxQ1_test : public beast::unit_test::suite env.close(); fillQueue(env, charlie); - checkMetrics(env, 0, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, limit + 1, limit, 256); aliceSeq = env.seq(alice); aliceBal = env.balance(alice); @@ -2290,11 +2459,11 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), seq(aliceSeq + 1), ter(terINSUF_FEE_B)); BEAST_EXPECT(env.balance(alice) == drops(30)); - checkMetrics(env, 1, limit * 2, limit + 1, limit, 256); + checkMetrics(__LINE__, env, 1, limit * 2, limit + 1, limit, 256); env.close(); ++limit; - checkMetrics(env, 0, limit * 2, 1, limit, 256); + checkMetrics(__LINE__, env, 0, limit * 2, 1, limit, 256); BEAST_EXPECT(env.balance(alice) == drops(5)); } @@ -2380,27 +2549,27 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(env.current()->fees().base == 10); - checkMetrics(env, 0, std::nullopt, 0, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 3, 256); // Fund accounts while the fee is cheap so they all apply. env.fund(XRP(50000), noripple(alice, bob, charlie)); - checkMetrics(env, 0, std::nullopt, 3, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 3, 3, 256); // Alice - no fee change yet env(noop(alice)); - checkMetrics(env, 0, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 4, 3, 256); // Bob with really high fee - applies env(noop(bob), openLedgerFee(env)); - checkMetrics(env, 0, std::nullopt, 5, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 5, 3, 256); // Charlie with low fee: queued env(noop(charlie), fee(1000), queued); - checkMetrics(env, 1, std::nullopt, 5, 3, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 5, 3, 256); env.close(); // Verify that the queued transaction was applied - checkMetrics(env, 0, 10, 1, 5, 256); + checkMetrics(__LINE__, env, 0, 10, 1, 5, 256); ///////////////////////////////////////////////////////////////// @@ -2411,7 +2580,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(bob), fee(1000)); env(noop(bob), fee(1000)); env(noop(bob), fee(1000)); - checkMetrics(env, 0, 10, 6, 5, 256); + checkMetrics(__LINE__, env, 0, 10, 6, 5, 256); // Use explicit fees so we can control which txn // will get dropped @@ -2435,7 +2604,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), fee(21), seq(aliceSeq++), queued); // Queue is full now. - checkMetrics(env, 10, 10, 6, 5, 385); + checkMetrics(__LINE__, env, 10, 10, 6, 5, 385); // Try to add another transaction with the default (low) fee, // it should fail because the queue is full. @@ -2554,7 +2723,7 @@ class TxQ1_test : public beast::unit_test::suite auto const bob = Account("bob"); env.fund(XRP(500000), noripple(alice, bob)); - checkMetrics(env, 0, std::nullopt, 2, 1, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 2, 1, 256); auto const aliceSeq = env.seq(alice); BEAST_EXPECT(env.current()->info().seq == 3); @@ -2574,7 +2743,7 @@ class TxQ1_test : public beast::unit_test::suite seq(aliceSeq + 3), json(R"({"LastLedgerSequence":11})"), ter(terQUEUED)); - checkMetrics(env, 4, std::nullopt, 2, 1, 256); + checkMetrics(__LINE__, env, 4, std::nullopt, 2, 1, 256); auto const bobSeq = env.seq(bob); // Ledger 4 gets 3, // Ledger 5 gets 4, @@ -2583,17 +2752,17 @@ class TxQ1_test : public beast::unit_test::suite { env(noop(bob), seq(bobSeq + i), fee(200), ter(terQUEUED)); } - checkMetrics(env, 4 + 3 + 4 + 5, std::nullopt, 2, 1, 256); + checkMetrics(__LINE__, env, 4 + 3 + 4 + 5, std::nullopt, 2, 1, 256); // Close ledger 3 env.close(); - checkMetrics(env, 4 + 4 + 5, 20, 3, 2, 256); + checkMetrics(__LINE__, env, 4 + 4 + 5, 20, 3, 2, 256); // Close ledger 4 env.close(); - checkMetrics(env, 4 + 5, 30, 4, 3, 256); + checkMetrics(__LINE__, env, 4 + 5, 30, 4, 3, 256); // Close ledger 5 env.close(); // Alice's first two txs expired. - checkMetrics(env, 2, 40, 5, 4, 256); + checkMetrics(__LINE__, env, 2, 40, 5, 4, 256); // Because aliceSeq is missing, aliceSeq + 1 fails env(noop(alice), seq(aliceSeq + 1), ter(terPRE_SEQ)); @@ -2602,27 +2771,27 @@ class TxQ1_test : public beast::unit_test::suite env(fset(alice, asfAccountTxnID), seq(aliceSeq), ter(telCAN_NOT_QUEUE_BLOCKS)); - checkMetrics(env, 2, 40, 5, 4, 256); + checkMetrics(__LINE__, env, 2, 40, 5, 4, 256); // However we can fill the gap with a non-blocker. env(noop(alice), seq(aliceSeq), fee(20), ter(terQUEUED)); - checkMetrics(env, 3, 40, 5, 4, 256); + checkMetrics(__LINE__, env, 3, 40, 5, 4, 256); // Attempt to queue up a new aliceSeq + 1 tx that's a blocker. env(fset(alice, asfAccountTxnID), seq(aliceSeq + 1), ter(telCAN_NOT_QUEUE_BLOCKS)); - checkMetrics(env, 3, 40, 5, 4, 256); + checkMetrics(__LINE__, env, 3, 40, 5, 4, 256); // Queue up a non-blocker replacement for aliceSeq + 1. env(noop(alice), seq(aliceSeq + 1), fee(20), ter(terQUEUED)); - checkMetrics(env, 4, 40, 5, 4, 256); + checkMetrics(__LINE__, env, 4, 40, 5, 4, 256); // Close ledger 6 env.close(); // We expect that all of alice's queued tx's got into // the open ledger. - checkMetrics(env, 0, 50, 4, 5, 256); + checkMetrics(__LINE__, env, 0, 50, 4, 5, 256); BEAST_EXPECT(env.seq(alice) == aliceSeq + 4); } @@ -2648,7 +2817,7 @@ class TxQ1_test : public beast::unit_test::suite auto const bob = Account("bob"); env.fund(XRP(500000), noripple(alice, bob)); - checkMetrics(env, 0, std::nullopt, 2, 1, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 2, 1, 256); auto const aliceSeq = env.seq(alice); BEAST_EXPECT(env.current()->info().seq == 3); @@ -2695,7 +2864,7 @@ class TxQ1_test : public beast::unit_test::suite seq(aliceSeq + 19), json(R"({"LastLedgerSequence":11})"), ter(terQUEUED)); - checkMetrics(env, 10, std::nullopt, 2, 1, 256); + checkMetrics(__LINE__, env, 10, std::nullopt, 2, 1, 256); auto const bobSeq = env.seq(bob); // Ledger 4 gets 2 from bob and 1 from alice, @@ -2705,21 +2874,21 @@ class TxQ1_test : public beast::unit_test::suite { env(noop(bob), seq(bobSeq + i), fee(200), ter(terQUEUED)); } - checkMetrics(env, 10 + 2 + 4 + 5, std::nullopt, 2, 1, 256); + checkMetrics(__LINE__, env, 10 + 2 + 4 + 5, std::nullopt, 2, 1, 256); // Close ledger 3 env.close(); - checkMetrics(env, 9 + 4 + 5, 20, 3, 2, 256); + checkMetrics(__LINE__, env, 9 + 4 + 5, 20, 3, 2, 256); BEAST_EXPECT(env.seq(alice) == aliceSeq + 12); // Close ledger 4 env.close(); - checkMetrics(env, 9 + 5, 30, 4, 3, 256); + checkMetrics(__LINE__, env, 9 + 5, 30, 4, 3, 256); BEAST_EXPECT(env.seq(alice) == aliceSeq + 12); // Close ledger 5 env.close(); // Three of Alice's txs expired. - checkMetrics(env, 6, 40, 5, 4, 256); + checkMetrics(__LINE__, env, 6, 40, 5, 4, 256); BEAST_EXPECT(env.seq(alice) == aliceSeq + 12); // Top off Alice's queue again using Tickets so the sequence gap is @@ -2730,7 +2899,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), ticket::use(aliceSeq + 4), ter(terQUEUED)); env(noop(alice), ticket::use(aliceSeq + 5), ter(terQUEUED)); env(noop(alice), ticket::use(aliceSeq + 6), ter(telCAN_NOT_QUEUE_FULL)); - checkMetrics(env, 11, 40, 5, 4, 256); + checkMetrics(__LINE__, env, 11, 40, 5, 4, 256); // Even though alice's queue is full we can still slide in a couple // more transactions because she has a sequence gap. But we @@ -2761,7 +2930,7 @@ class TxQ1_test : public beast::unit_test::suite // Finally we can fill in the entire gap. env(noop(alice), seq(aliceSeq + 18), ter(terQUEUED)); - checkMetrics(env, 14, 40, 5, 4, 256); + checkMetrics(__LINE__, env, 14, 40, 5, 4, 256); // Verify that nothing can be added now that the gap is filled. env(noop(alice), seq(aliceSeq + 20), ter(telCAN_NOT_QUEUE_FULL)); @@ -2770,18 +2939,18 @@ class TxQ1_test : public beast::unit_test::suite // but alice adds one more transaction at seq(aliceSeq + 20) so // we only see a reduction by 5. env.close(); - checkMetrics(env, 9, 50, 6, 5, 256); + checkMetrics(__LINE__, env, 9, 50, 6, 5, 256); BEAST_EXPECT(env.seq(alice) == aliceSeq + 15); // Close ledger 7. That should remove 7 more of alice's transactions. env.close(); - checkMetrics(env, 2, 60, 7, 6, 256); + checkMetrics(__LINE__, env, 2, 60, 7, 6, 256); BEAST_EXPECT(env.seq(alice) == aliceSeq + 19); // Close one last ledger to see all of alice's transactions moved // into the ledger, including the tickets env.close(); - checkMetrics(env, 0, 70, 2, 7, 256); + checkMetrics(__LINE__, env, 0, 70, 2, 7, 256); BEAST_EXPECT(env.seq(alice) == aliceSeq + 21); } @@ -2799,7 +2968,7 @@ class TxQ1_test : public beast::unit_test::suite env.fund(XRP(100000), alice, bob); fillQueue(env, alice); - checkMetrics(env, 0, std::nullopt, 7, 6, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 7, 6, 256); // Queue up several transactions for alice sign-and-submit auto const aliceSeq = env.seq(alice); @@ -2819,9 +2988,9 @@ class TxQ1_test : public beast::unit_test::suite envs(noop(alice), fee(1000), seq(none), ter(terQUEUED))( submitParams); } - checkMetrics(env, 5, std::nullopt, 7, 6, 256); + checkMetrics(__LINE__, env, 5, std::nullopt, 7, 6, 256); { - auto aliceStat = txQ.getAccountTxs(alice.id(), *env.current()); + auto aliceStat = txQ.getAccountTxs(alice.id()); SeqProxy seq = SeqProxy::sequence(aliceSeq); BEAST_EXPECT(aliceStat.size() == 5); for (auto const& tx : aliceStat) @@ -2844,34 +3013,34 @@ class TxQ1_test : public beast::unit_test::suite // Give them a higher fee so they'll beat alice's. for (int i = 0; i < 8; ++i) envs(noop(bob), fee(2000), seq(none), ter(terQUEUED))(); - checkMetrics(env, 13, std::nullopt, 7, 6, 256); + checkMetrics(__LINE__, env, 13, std::nullopt, 7, 6, 256); env.close(); - checkMetrics(env, 5, 14, 8, 7, 256); + checkMetrics(__LINE__, env, 5, 14, 8, 7, 256); // Put some more txs in the queue for bob. // Give them a higher fee so they'll beat alice's. fillQueue(env, bob); for (int i = 0; i < 9; ++i) envs(noop(bob), fee(2000), seq(none), ter(terQUEUED))(); - checkMetrics(env, 14, 14, 8, 7, 25601); + checkMetrics(__LINE__, env, 14, 14, 8, 7, 25601); env.close(); // Put some more txs in the queue for bob. // Give them a higher fee so they'll beat alice's. fillQueue(env, bob); for (int i = 0; i < 10; ++i) envs(noop(bob), fee(2000), seq(none), ter(terQUEUED))(); - checkMetrics(env, 15, 16, 9, 8, 256); + checkMetrics(__LINE__, env, 15, 16, 9, 8, 256); env.close(); - checkMetrics(env, 4, 18, 10, 9, 256); + checkMetrics(__LINE__, env, 4, 18, 10, 9, 256); { // Bob has nothing left in the queue. - auto bobStat = txQ.getAccountTxs(bob.id(), *env.current()); + auto bobStat = txQ.getAccountTxs(bob.id()); BEAST_EXPECT(bobStat.empty()); } // Verify alice's tx got dropped as we BEAST_EXPECT, and that there's // a gap in her queued txs. { - auto aliceStat = txQ.getAccountTxs(alice.id(), *env.current()); + auto aliceStat = txQ.getAccountTxs(alice.id()); auto seq = aliceSeq; BEAST_EXPECT(aliceStat.size() == 4); for (auto const& tx : aliceStat) @@ -2888,9 +3057,9 @@ class TxQ1_test : public beast::unit_test::suite } // Now, fill the gap. envs(noop(alice), fee(1000), seq(none), ter(terQUEUED))(submitParams); - checkMetrics(env, 5, 18, 10, 9, 256); + checkMetrics(__LINE__, env, 5, 18, 10, 9, 256); { - auto aliceStat = txQ.getAccountTxs(alice.id(), *env.current()); + auto aliceStat = txQ.getAccountTxs(alice.id()); auto seq = aliceSeq; BEAST_EXPECT(aliceStat.size() == 5); for (auto const& tx : aliceStat) @@ -2903,14 +3072,14 @@ class TxQ1_test : public beast::unit_test::suite } env.close(); - checkMetrics(env, 0, 20, 5, 10, 256); + checkMetrics(__LINE__, env, 0, 20, 5, 10, 256); { // Bob's data has been cleaned up. - auto bobStat = txQ.getAccountTxs(bob.id(), *env.current()); + auto bobStat = txQ.getAccountTxs(bob.id()); BEAST_EXPECT(bobStat.empty()); } { - auto aliceStat = txQ.getAccountTxs(alice.id(), *env.current()); + auto aliceStat = txQ.getAccountTxs(alice.id()); BEAST_EXPECT(aliceStat.empty()); } } @@ -2961,10 +3130,10 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(!queue_data.isMember(jss::max_spend_drops_total)); BEAST_EXPECT(!queue_data.isMember(jss::transactions)); } - checkMetrics(env, 0, 6, 0, 3, 256); + checkMetrics(__LINE__, env, 0, 6, 0, 3, 256); fillQueue(env, alice); - checkMetrics(env, 0, 6, 4, 3, 256); + checkMetrics(__LINE__, env, 0, 6, 4, 3, 256); { auto const info = env.rpc("json", "account_info", withQueue); @@ -2989,7 +3158,7 @@ class TxQ1_test : public beast::unit_test::suite envs(noop(alice), fee(100), seq(none), ter(terQUEUED))(submitParams); envs(noop(alice), fee(100), seq(none), ter(terQUEUED))(submitParams); envs(noop(alice), fee(100), seq(none), ter(terQUEUED))(submitParams); - checkMetrics(env, 4, 6, 4, 3, 256); + checkMetrics(__LINE__, env, 4, 6, 4, 3, 256); { auto const info = env.rpc("json", "account_info", withQueue); @@ -3036,7 +3205,7 @@ class TxQ1_test : public beast::unit_test::suite // Drain the queue so we can queue up a blocker. env.close(); - checkMetrics(env, 0, 8, 4, 4, 256); + checkMetrics(__LINE__, env, 0, 8, 4, 4, 256); // Fill the ledger and then queue up a blocker. envs(noop(alice), seq(none))(submitParams); @@ -3047,7 +3216,7 @@ class TxQ1_test : public beast::unit_test::suite seq(none), json(jss::LastLedgerSequence, 10), ter(terQUEUED))(submitParams); - checkMetrics(env, 1, 8, 5, 4, 256); + checkMetrics(__LINE__, env, 1, 8, 5, 4, 256); { auto const info = env.rpc("json", "account_info", withQueue); @@ -3103,7 +3272,7 @@ class TxQ1_test : public beast::unit_test::suite envs(noop(alice), fee(100), seq(none), ter(telCAN_NOT_QUEUE_BLOCKED))( submitParams); - checkMetrics(env, 1, 8, 5, 4, 256); + checkMetrics(__LINE__, env, 1, 8, 5, 4, 256); { auto const info = env.rpc("json", "account_info", withQueue); @@ -3171,9 +3340,9 @@ class TxQ1_test : public beast::unit_test::suite } env.close(); - checkMetrics(env, 0, 10, 2, 5, 256); + checkMetrics(__LINE__, env, 0, 10, 2, 5, 256); env.close(); - checkMetrics(env, 0, 10, 0, 5, 256); + checkMetrics(__LINE__, env, 0, 10, 0, 5, 256); { auto const info = env.rpc("json", "account_info", withQueue); @@ -3242,17 +3411,17 @@ class TxQ1_test : public beast::unit_test::suite state[jss::load_factor_fee_reference] == 256); } - checkMetrics(env, 0, 6, 0, 3, 256); + checkMetrics(__LINE__, env, 0, 6, 0, 3, 256); fillQueue(env, alice); - checkMetrics(env, 0, 6, 4, 3, 256); + checkMetrics(__LINE__, env, 0, 6, 4, 3, 256); auto aliceSeq = env.seq(alice); auto submitParams = Json::Value(Json::objectValue); for (auto i = 0; i < 4; ++i) envs(noop(alice), fee(100), seq(aliceSeq + i), ter(terQUEUED))( submitParams); - checkMetrics(env, 4, 6, 4, 3, 256); + checkMetrics(__LINE__, env, 4, 6, 4, 3, 256); { auto const server_info = env.rpc("server_info"); @@ -3477,7 +3646,7 @@ class TxQ1_test : public beast::unit_test::suite // Fund the first few accounts at non escalated fee env.fund(XRP(50000), noripple(a, b, c, d)); - checkMetrics(env, 0, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 4, 3, 256); // First transaction establishes the messaging using namespace std::chrono_literals; @@ -3527,7 +3696,7 @@ class TxQ1_test : public beast::unit_test::suite jv[jss::load_factor_fee_reference] == 256; })); - checkMetrics(env, 0, 8, 0, 4, 256); + checkMetrics(__LINE__, env, 0, 8, 0, 4, 256); // Fund then next few accounts at non escalated fee env.fund(XRP(50000), noripple(e, f, g, h, i)); @@ -3541,7 +3710,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(e), fee(10), queued); env(noop(f), fee(10), queued); env(noop(g), fee(10), queued); - checkMetrics(env, 7, 8, 5, 4, 256); + checkMetrics(__LINE__, env, 7, 8, 5, 4, 256); // Last transaction escalates the fee BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { @@ -3610,7 +3779,7 @@ class TxQ1_test : public beast::unit_test::suite auto alice = Account("alice"); auto bob = Account("bob"); - checkMetrics(env, 0, std::nullopt, 0, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 3, 256); env.fund(XRP(50000000), alice, bob); fillQueue(env, alice); @@ -3656,7 +3825,7 @@ class TxQ1_test : public beast::unit_test::suite seq(aliceSeq++), ter(terQUEUED)); - checkMetrics(env, 3, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 3, std::nullopt, 4, 3, 256); // Figure out how much it would cost to cover all the // queued txs + itself @@ -3669,7 +3838,7 @@ class TxQ1_test : public beast::unit_test::suite // the edge case test. env(noop(alice), fee(totalFee1), seq(aliceSeq++), ter(terQUEUED)); - checkMetrics(env, 4, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 4, std::nullopt, 4, 3, 256); // Now repeat the process including the new tx // and avoiding the rounding error @@ -3679,7 +3848,7 @@ class TxQ1_test : public beast::unit_test::suite // Submit a transaction with that fee. It will succeed. env(noop(alice), fee(totalFee2), seq(aliceSeq++)); - checkMetrics(env, 0, std::nullopt, 9, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 9, 3, 256); } testcase("replace last tx with enough to clear queue"); @@ -3699,7 +3868,7 @@ class TxQ1_test : public beast::unit_test::suite seq(aliceSeq++), ter(terQUEUED)); - checkMetrics(env, 3, std::nullopt, 9, 3, 256); + checkMetrics(__LINE__, env, 3, std::nullopt, 9, 3, 256); // Figure out how much it would cost to cover all the // queued txs + itself @@ -3712,10 +3881,10 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), fee(totalFee), seq(aliceSeq++)); // The queue is clear - checkMetrics(env, 0, std::nullopt, 12, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 12, 3, 256); env.close(); - checkMetrics(env, 0, 24, 0, 12, 256); + checkMetrics(__LINE__, env, 0, 24, 0, 12, 256); } testcase("replace middle tx with enough to clear queue"); @@ -3728,7 +3897,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), fee(100), seq(aliceSeq++), ter(terQUEUED)); } - checkMetrics(env, 5, 24, 13, 12, 256); + checkMetrics(__LINE__, env, 5, 24, 13, 12, 256); // Figure out how much it would cost to cover 3 txns std::uint64_t const totalFee = calcTotalFee(100 * 2, 3); @@ -3737,9 +3906,9 @@ class TxQ1_test : public beast::unit_test::suite aliceSeq -= 3; env(noop(alice), fee(totalFee), seq(aliceSeq++)); - checkMetrics(env, 2, 24, 16, 12, 256); + checkMetrics(__LINE__, env, 2, 24, 16, 12, 256); auto const aliceQueue = - env.app().getTxQ().getAccountTxs(alice.id(), *env.current()); + env.app().getTxQ().getAccountTxs(alice.id()); BEAST_EXPECT(aliceQueue.size() == 2); SeqProxy seq = SeqProxy::sequence(aliceSeq); for (auto const& tx : aliceQueue) @@ -3751,7 +3920,7 @@ class TxQ1_test : public beast::unit_test::suite // Close the ledger to clear the queue env.close(); - checkMetrics(env, 0, 32, 2, 16, 256); + checkMetrics(__LINE__, env, 0, 32, 2, 16, 256); } testcase("clear queue failure (load)"); @@ -3768,7 +3937,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), fee(22), seq(aliceSeq++), ter(terQUEUED)); } - checkMetrics(env, 4, 32, 17, 16, 256); + checkMetrics(__LINE__, env, 4, 32, 17, 16, 256); // Figure out how much it would cost to cover all the txns // + 1 @@ -3783,11 +3952,11 @@ class TxQ1_test : public beast::unit_test::suite env(noop(alice), fee(totalFee), seq(aliceSeq++), ter(terQUEUED)); // The original last transaction is still in the queue - checkMetrics(env, 5, 32, 17, 16, 256); + checkMetrics(__LINE__, env, 5, 32, 17, 16, 256); // With high load, some of the txs stay in the queue env.close(); - checkMetrics(env, 3, 34, 2, 17, 256); + checkMetrics(__LINE__, env, 3, 34, 2, 17, 256); // Load drops back down feeTrack.setRemoteFee(origFee); @@ -3795,14 +3964,14 @@ class TxQ1_test : public beast::unit_test::suite // Because of the earlier failure, alice can not clear the queue, // no matter how high the fee fillQueue(env, bob); - checkMetrics(env, 3, 34, 18, 17, 256); + checkMetrics(__LINE__, env, 3, 34, 18, 17, 256); env(noop(alice), fee(XRP(1)), seq(aliceSeq++), ter(terQUEUED)); - checkMetrics(env, 4, 34, 18, 17, 256); + checkMetrics(__LINE__, env, 4, 34, 18, 17, 256); // With normal load, those txs get into the ledger env.close(); - checkMetrics(env, 0, 36, 4, 18, 256); + checkMetrics(__LINE__, env, 0, 36, 4, 18, 256); } } @@ -3824,77 +3993,77 @@ class TxQ1_test : public beast::unit_test::suite {"maximum_txn_per_account", "200"}})); auto alice = Account("alice"); - checkMetrics(env, 0, std::nullopt, 0, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 3, 256); env.fund(XRP(50000000), alice); fillQueue(env, alice); - checkMetrics(env, 0, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 4, 3, 256); auto seqAlice = env.seq(alice); auto txCount = 140; for (int i = 0; i < txCount; ++i) env(noop(alice), seq(seqAlice++), ter(terQUEUED)); - checkMetrics(env, txCount, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, txCount, std::nullopt, 4, 3, 256); // Close a few ledgers successfully, so the limit grows env.close(); // 4 + 25% = 5 txCount -= 6; - checkMetrics(env, txCount, 10, 6, 5, 257); + checkMetrics(__LINE__, env, txCount, 10, 6, 5, 257); env.close(); // 6 + 25% = 7 txCount -= 8; - checkMetrics(env, txCount, 14, 8, 7, 257); + checkMetrics(__LINE__, env, txCount, 14, 8, 7, 257); env.close(); // 8 + 25% = 10 txCount -= 11; - checkMetrics(env, txCount, 20, 11, 10, 257); + checkMetrics(__LINE__, env, txCount, 20, 11, 10, 257); env.close(); // 11 + 25% = 13 txCount -= 14; - checkMetrics(env, txCount, 26, 14, 13, 257); + checkMetrics(__LINE__, env, txCount, 26, 14, 13, 257); env.close(); // 14 + 25% = 17 txCount -= 18; - checkMetrics(env, txCount, 34, 18, 17, 257); + checkMetrics(__LINE__, env, txCount, 34, 18, 17, 257); env.close(); // 18 + 25% = 22 txCount -= 23; - checkMetrics(env, txCount, 44, 23, 22, 257); + checkMetrics(__LINE__, env, txCount, 44, 23, 22, 257); env.close(); // 23 + 25% = 28 txCount -= 29; - checkMetrics(env, txCount, 56, 29, 28, 256); + checkMetrics(__LINE__, env, txCount, 56, 29, 28, 256); // From 3 expected to 28 in 7 "fast" ledgers. // Close the ledger with a delay. env.close(env.now() + 5s, 10000ms); txCount -= 15; - checkMetrics(env, txCount, 56, 15, 14, 256); + checkMetrics(__LINE__, env, txCount, 56, 15, 14, 256); // Close the ledger with a delay. env.close(env.now() + 5s, 10000ms); txCount -= 8; - checkMetrics(env, txCount, 56, 8, 7, 256); + checkMetrics(__LINE__, env, txCount, 56, 8, 7, 256); // Close the ledger with a delay. env.close(env.now() + 5s, 10000ms); txCount -= 4; - checkMetrics(env, txCount, 56, 4, 3, 256); + checkMetrics(__LINE__, env, txCount, 56, 4, 3, 256); // From 28 expected back down to 3 in 3 "slow" ledgers. // Confirm the minimum sticks env.close(env.now() + 5s, 10000ms); txCount -= 4; - checkMetrics(env, txCount, 56, 4, 3, 256); + checkMetrics(__LINE__, env, txCount, 56, 4, 3, 256); BEAST_EXPECT(!txCount); } @@ -3910,35 +4079,35 @@ class TxQ1_test : public beast::unit_test::suite {"maximum_txn_per_account", "200"}})); auto alice = Account("alice"); - checkMetrics(env, 0, std::nullopt, 0, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 3, 256); env.fund(XRP(50000000), alice); fillQueue(env, alice); - checkMetrics(env, 0, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 4, 3, 256); auto seqAlice = env.seq(alice); auto txCount = 43; for (int i = 0; i < txCount; ++i) env(noop(alice), seq(seqAlice++), ter(terQUEUED)); - checkMetrics(env, txCount, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, txCount, std::nullopt, 4, 3, 256); // Close a few ledgers successfully, so the limit grows env.close(); // 4 + 150% = 10 txCount -= 11; - checkMetrics(env, txCount, 20, 11, 10, 257); + checkMetrics(__LINE__, env, txCount, 20, 11, 10, 257); env.close(); // 11 + 150% = 27 txCount -= 28; - checkMetrics(env, txCount, 54, 28, 27, 256); + checkMetrics(__LINE__, env, txCount, 54, 28, 27, 256); // From 3 expected to 28 in 7 "fast" ledgers. // Close the ledger with a delay. env.close(env.now() + 5s, 10000ms); txCount -= 4; - checkMetrics(env, txCount, 54, 4, 3, 256); + checkMetrics(__LINE__, env, txCount, 54, 4, 3, 256); // From 28 expected back down to 3 in 3 "slow" ledgers. @@ -3968,19 +4137,19 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(env.current()->fees().base == 10); - checkMetrics(env, 0, std::nullopt, 0, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 3, 256); // Create account env.fund(XRP(50000), noripple(alice)); - checkMetrics(env, 0, std::nullopt, 1, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 1, 3, 256); fillQueue(env, alice); - checkMetrics(env, 0, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 4, 3, 256); // Queue a transaction auto const aliceSeq = env.seq(alice); env(noop(alice), queued); - checkMetrics(env, 1, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 4, 3, 256); // Now, apply a (different) transaction directly // to the open ledger, bypassing the queue @@ -3996,23 +4165,23 @@ class TxQ1_test : public beast::unit_test::suite return result.second; }); // the queued transaction is still there - checkMetrics(env, 1, std::nullopt, 5, 3, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 5, 3, 256); // The next transaction should be able to go into the open // ledger, even though aliceSeq is queued. In earlier incarnations // of the TxQ this would cause an assert. env(noop(alice), seq(aliceSeq + 1), openLedgerFee(env)); - checkMetrics(env, 1, std::nullopt, 6, 3, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 6, 3, 256); // Now queue a couple more transactions to make sure // they succeed despite aliceSeq being queued env(noop(alice), seq(aliceSeq + 2), queued); env(noop(alice), seq(aliceSeq + 3), queued); - checkMetrics(env, 3, std::nullopt, 6, 3, 256); + checkMetrics(__LINE__, env, 3, std::nullopt, 6, 3, 256); // Now close the ledger. One of the queued transactions // (aliceSeq) should be dropped. env.close(); - checkMetrics(env, 0, 12, 2, 6, 256); + checkMetrics(__LINE__, env, 0, 12, 2, 6, 256); } void @@ -4035,11 +4204,11 @@ class TxQ1_test : public beast::unit_test::suite BEAST_EXPECT(env.current()->fees().base == 10); - checkMetrics(env, 0, std::nullopt, 0, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 0, 3, 256); // Create account env.fund(XRP(50000), noripple(alice)); - checkMetrics(env, 0, std::nullopt, 1, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 1, 3, 256); // Create tickets std::uint32_t const tktSeq0{env.seq(alice) + 1}; @@ -4047,12 +4216,12 @@ class TxQ1_test : public beast::unit_test::suite // Fill the queue so the next transaction will be queued. fillQueue(env, alice); - checkMetrics(env, 0, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 0, std::nullopt, 4, 3, 256); // Queue a transaction with a ticket. Leave an unused ticket // on either side. env(noop(alice), ticket::use(tktSeq0 + 1), queued); - checkMetrics(env, 1, std::nullopt, 4, 3, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 4, 3, 256); // Now, apply a (different) transaction directly // to the open ledger, bypassing the queue @@ -4068,25 +4237,25 @@ class TxQ1_test : public beast::unit_test::suite return result.second; }); // the queued transaction is still there - checkMetrics(env, 1, std::nullopt, 5, 3, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 5, 3, 256); // The next (sequence-based) transaction should be able to go into // the open ledger, even though tktSeq0 is queued. Note that this // sequence-based transaction goes in front of the queued // transaction, so the queued transaction is left in the queue. env(noop(alice), openLedgerFee(env)); - checkMetrics(env, 1, std::nullopt, 6, 3, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 6, 3, 256); // We should be able to do the same thing with a ticket that goes // if front of the queued transaction. This one too will leave // the queued transaction in place. env(noop(alice), ticket::use(tktSeq0 + 0), openLedgerFee(env)); - checkMetrics(env, 1, std::nullopt, 7, 3, 256); + checkMetrics(__LINE__, env, 1, std::nullopt, 7, 3, 256); // We have one ticketed transaction in the queue. We should able // to add another to the queue. env(noop(alice), ticket::use(tktSeq0 + 2), queued); - checkMetrics(env, 2, std::nullopt, 7, 3, 256); + checkMetrics(__LINE__, env, 2, std::nullopt, 7, 3, 256); // Here we try to force the queued transactions into the ledger by // adding one more queued (ticketed) transaction that pays enough @@ -4102,12 +4271,12 @@ class TxQ1_test : public beast::unit_test::suite // transaction is equally capable of going into the ledger independent // of all other ticket- or sequence-based transactions. env(noop(alice), ticket::use(tktSeq0 + 3), fee(XRP(1))); - checkMetrics(env, 2, std::nullopt, 8, 3, 256); + checkMetrics(__LINE__, env, 2, std::nullopt, 8, 3, 256); // Now close the ledger. One of the queued transactions // (the one with tktSeq0 + 1) should be dropped. env.close(); - checkMetrics(env, 0, 16, 1, 8, 256); + checkMetrics(__LINE__, env, 0, 16, 1, 8, 256); } void @@ -4150,7 +4319,7 @@ class TxQ1_test : public beast::unit_test::suite env.close(); env.fund(XRP(10000), fiona); env.close(); - checkMetrics(env, 0, 10, 0, 2, 256); + checkMetrics(__LINE__, env, 0, 10, 0, 2, 256); // Close ledgers until the amendments show up. int i = 0; @@ -4161,7 +4330,8 @@ class TxQ1_test : public beast::unit_test::suite break; } auto expectedPerLedger = ripple::detail::numUpVotedAmendments() + 1; - checkMetrics(env, 0, 5 * expectedPerLedger, 0, expectedPerLedger, 256); + checkMetrics( + __LINE__, env, 0, 5 * expectedPerLedger, 0, expectedPerLedger, 256); // Now wait 2 weeks modulo 256 ledgers for the amendments to be // enabled. Speed the process by closing ledgers every 80 minutes, @@ -4174,6 +4344,7 @@ class TxQ1_test : public beast::unit_test::suite // We're very close to the flag ledger. Fill the ledger. fillQueue(env, alice); checkMetrics( + __LINE__, env, 0, 5 * expectedPerLedger, @@ -4201,6 +4372,7 @@ class TxQ1_test : public beast::unit_test::suite } std::size_t expectedInQueue = 60; checkMetrics( + __LINE__, env, expectedInQueue, 5 * expectedPerLedger, @@ -4228,6 +4400,7 @@ class TxQ1_test : public beast::unit_test::suite expectedInLedger -= expectedInQueue; ++expectedPerLedger; checkMetrics( + __LINE__, env, expectedInQueue, 5 * expectedPerLedger, @@ -4314,7 +4487,7 @@ class TxQ1_test : public beast::unit_test::suite // of their transactions expire out of the queue. To start out // alice fills the ledger. fillQueue(env, alice); - checkMetrics(env, 0, 50, 7, 6, 256); + checkMetrics(__LINE__, env, 0, 50, 7, 6, 256); // Now put a few transactions into alice's queue, including one that // will expire out soon. @@ -4360,9 +4533,9 @@ class TxQ1_test : public beast::unit_test::suite env(noop(fiona), seq(seqFiona++), fee(--feeDrops), ter(terQUEUED)); } - checkMetrics(env, 34, 50, 7, 6, 256); + checkMetrics(__LINE__, env, 34, 50, 7, 6, 256); env.close(); - checkMetrics(env, 26, 50, 8, 7, 256); + checkMetrics(__LINE__, env, 26, 50, 8, 7, 256); // Re-fill the queue so alice and bob stay stuck. feeDrops = medFee; @@ -4373,9 +4546,9 @@ class TxQ1_test : public beast::unit_test::suite env(noop(ellie), seq(seqEllie++), fee(--feeDrops), ter(terQUEUED)); env(noop(fiona), seq(seqFiona++), fee(--feeDrops), ter(terQUEUED)); } - checkMetrics(env, 38, 50, 8, 7, 256); + checkMetrics(__LINE__, env, 38, 50, 8, 7, 256); env.close(); - checkMetrics(env, 29, 50, 9, 8, 256); + checkMetrics(__LINE__, env, 29, 50, 9, 8, 256); // One more time... feeDrops = medFee; @@ -4386,9 +4559,9 @@ class TxQ1_test : public beast::unit_test::suite env(noop(ellie), seq(seqEllie++), fee(--feeDrops), ter(terQUEUED)); env(noop(fiona), seq(seqFiona++), fee(--feeDrops), ter(terQUEUED)); } - checkMetrics(env, 41, 50, 9, 8, 256); + checkMetrics(__LINE__, env, 41, 50, 9, 8, 256); env.close(); - checkMetrics(env, 29, 50, 10, 9, 256); + checkMetrics(__LINE__, env, 29, 50, 10, 9, 256); // Finally the stage is set. alice's and bob's transactions expired // out of the queue which caused the dropPenalty flag to be set on @@ -4410,7 +4583,7 @@ class TxQ1_test : public beast::unit_test::suite env(noop(carol), seq(seqCarol++), fee(--feeDrops), ter(terQUEUED)); env(noop(daria), seq(seqDaria++), fee(--feeDrops), ter(terQUEUED)); env(noop(ellie), seq(seqEllie++), fee(--feeDrops), ter(terQUEUED)); - checkMetrics(env, 48, 50, 10, 9, 256); + checkMetrics(__LINE__, env, 48, 50, 10, 9, 256); // Now induce a fee jump which should cause all the transactions // in the queue to fail with telINSUF_FEE_P. @@ -4427,7 +4600,7 @@ class TxQ1_test : public beast::unit_test::suite // o The _last_ transaction should be dropped from alice's queue. // o The first failing transaction should be dropped from bob's queue. env.close(); - checkMetrics(env, 46, 50, 0, 10, 256); + checkMetrics(__LINE__, env, 46, 50, 0, 10, 256); // Run the local fee back down. while (env.app().getFeeTrack().lowerLocalFee()) @@ -4435,7 +4608,7 @@ class TxQ1_test : public beast::unit_test::suite // bob fills the ledger so it's easier to probe the TxQ. fillQueue(env, bob); - checkMetrics(env, 46, 50, 11, 10, 256); + checkMetrics(__LINE__, env, 46, 50, 11, 10, 256); // Before the close() alice had two transactions in her queue. // We now expect her to have one. Here's the state of alice's queue. @@ -4547,7 +4720,7 @@ class TxQ1_test : public beast::unit_test::suite env.close(); - checkMetrics(env, 0, 50, 4, 6, 256); + checkMetrics(__LINE__, env, 0, 50, 4, 6, 256); } { @@ -4608,7 +4781,7 @@ class TxQ1_test : public beast::unit_test::suite // The ticket transactions that didn't succeed or get queued succeed // this time because the tickets got consumed when the offers came // out of the queue - checkMetrics(env, 0, 50, 8, 7, 256); + checkMetrics(__LINE__, env, 0, 50, 8, 7, 256); } } diff --git a/src/test/rpc/LedgerRPC_test.cpp b/src/test/rpc/LedgerRPC_test.cpp index df8bebfacee..fdcefbf66c2 100644 --- a/src/test/rpc/LedgerRPC_test.cpp +++ b/src/test/rpc/LedgerRPC_test.cpp @@ -1539,10 +1539,11 @@ class LedgerRPC_test : public beast::unit_test::suite jrr = env.rpc("json", "ledger", to_string(jv))[jss::result]; const std::string txid1 = [&]() { + auto const& parentHash = env.current()->info().parentHash; if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2)) { - const std::string txid0 = [&]() { - auto const& txj = jrr[jss::queue_data][0u]; + const std::string txid1 = [&]() { + auto const& txj = jrr[jss::queue_data][1u]; BEAST_EXPECT(txj[jss::account] == alice.human()); BEAST_EXPECT(txj[jss::fee_level] == "256"); BEAST_EXPECT(txj["preflight_result"] == "tesSUCCESS"); @@ -1554,7 +1555,7 @@ class LedgerRPC_test : public beast::unit_test::suite return tx[jss::hash].asString(); }(); - auto const& txj = jrr[jss::queue_data][1u]; + auto const& txj = jrr[jss::queue_data][0u]; BEAST_EXPECT(txj[jss::account] == alice.human()); BEAST_EXPECT(txj[jss::fee_level] == "256"); BEAST_EXPECT(txj["preflight_result"] == "tesSUCCESS"); @@ -1563,9 +1564,12 @@ class LedgerRPC_test : public beast::unit_test::suite auto const& tx = txj[jss::tx]; BEAST_EXPECT(tx[jss::Account] == alice.human()); BEAST_EXPECT(tx[jss::TransactionType] == jss::OfferCreate); - const auto txid1 = tx[jss::hash].asString(); - BEAST_EXPECT(txid0 < txid1); - return txid1; + const auto txid0 = tx[jss::hash].asString(); + uint256 tx0, tx1; + BEAST_EXPECT(tx0.parseHex(txid0)); + BEAST_EXPECT(tx1.parseHex(txid1)); + BEAST_EXPECT((tx0 ^ parentHash) < (tx1 ^ parentHash)); + return txid0; } return std::string{}; }(); @@ -1577,6 +1581,7 @@ class LedgerRPC_test : public beast::unit_test::suite jrr = env.rpc("json", "ledger", to_string(jv))[jss::result]; if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2)) { + auto const& parentHash = env.current()->info().parentHash; auto const txid0 = [&]() { auto const& txj = jrr[jss::queue_data][0u]; BEAST_EXPECT(txj[jss::account] == alice.human()); @@ -1593,7 +1598,10 @@ class LedgerRPC_test : public beast::unit_test::suite BEAST_EXPECT(txj["last_result"] == "terPRE_SEQ"); BEAST_EXPECT(txj.isMember(jss::tx)); BEAST_EXPECT(txj[jss::tx] == txid1); - BEAST_EXPECT(txid0 < txid1); + uint256 tx0, tx1; + BEAST_EXPECT(tx0.parseHex(txid0)); + BEAST_EXPECT(tx1.parseHex(txid1)); + BEAST_EXPECT((tx0 ^ parentHash) < (tx1 ^ parentHash)); } env.close();