diff --git a/src/ripple/app/misc/TxQ.h b/src/ripple/app/misc/TxQ.h index f78e3b7d8a1..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 @@ -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 3eeda53155d..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; } diff --git a/src/test/app/TxQ_test.cpp b/src/test/app/TxQ_test.cpp index 026a527bd41..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, @@ -52,44 +53,80 @@ class TxQ1_test : public beast::unit_test::suite FeeLevel64 const expectedMed{expectedMedFeeLevel}; auto const metrics = env.app().getTxQ().getMetrics(*env.current()); using namespace std::string_literals; - BEAST_EXPECTS( - metrics.referenceFeeLevel == FeeLevel64{256}, - "reference: "s + std::to_string(metrics.referenceFeeLevel.value()) + - "/256"); - BEAST_EXPECTS( - metrics.txCount == expectedCount, - "txCount: "s + std::to_string(metrics.txCount) + "/" + - std::to_string(expectedCount)); - BEAST_EXPECTS( - metrics.txQMaxSize == expectedMaxCount, - "txQMaxSize: "s + std::to_string(metrics.txQMaxSize.value_or(0)) + - "/" + std::to_string(expectedMaxCount.value_or(0))); - BEAST_EXPECTS( - metrics.txInLedger == expectedInLedger, - "txInLedger: "s + std::to_string(metrics.txInLedger) + "/" + - std::to_string(expectedInLedger)); - BEAST_EXPECTS( - metrics.txPerLedger == expectedPerLedger, - "txPerLedger: "s + std::to_string(metrics.txPerLedger) + "/" + - std::to_string(expectedPerLedger)); - BEAST_EXPECTS( - metrics.minProcessingFeeLevel == expectedMin, - "minProcessingFeeLevel: "s + - std::to_string(metrics.minProcessingFeeLevel.value()) + "/" + - std::to_string(expectedMin.value())); - BEAST_EXPECTS( - metrics.medFeeLevel == expectedMed, - "medFeeLevel: "s + std::to_string(metrics.medFeeLevel.value()) + - "/" + std::to_string(expectedMed.value())); - auto expectedCurFeeLevel = expectedInLedger > expectedPerLedger + + 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_EXPECTS( - metrics.openLedgerFeeLevel == expectedCurFeeLevel, - "openLedgerFeeLevel: "s + - std::to_string(metrics.openLedgerFeeLevel.value()) + "/" + - std::to_string(expectedCurFeeLevel.value())); + + metrics.openLedgerFeeLevel == expectedCurFeeLevel + ? pass() + : fail( + "openLedgerFeeLevel: "s + + std::to_string(metrics.openLedgerFeeLevel.value()) + "/" + + std::to_string(expectedCurFeeLevel.value()), + __FILE__, + line); } void @@ -168,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 @@ -179,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}); @@ -213,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); @@ -252,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. @@ -265,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); ////////////////////////////////////////////////////////////// @@ -313,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 @@ -328,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. @@ -340,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); ////////////////////////////////////////////////////////////// @@ -364,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); @@ -393,6 +430,7 @@ class TxQ1_test : public beast::unit_test::suite ++metrics.txCount; checkMetrics( + __LINE__, env, metrics.txCount, metrics.txQMaxSize, @@ -415,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); ////////////////////////////////////////////////////////////////// @@ -434,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); ////////////////////////////////////////////////////////////////// @@ -465,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. @@ -497,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); ////////////////////////////////////////////////////////////////// @@ -528,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. @@ -556,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); ////////////////////////////////////////////////////////////////// @@ -587,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)); @@ -618,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); ////////////////////////////////////////////////////////////////// @@ -655,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 @@ -670,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 @@ -711,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 @@ -769,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)); @@ -779,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 @@ -798,7 +836,7 @@ 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()); @@ -821,7 +859,7 @@ class TxQ1_test : public beast::unit_test::suite } 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); @@ -829,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. @@ -844,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); } @@ -876,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)); @@ -888,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); @@ -912,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; @@ -928,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 @@ -939,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); @@ -995,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. { @@ -1025,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 @@ -1054,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); @@ -1062,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); @@ -1074,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); @@ -1104,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 @@ -1126,7 +1164,7 @@ 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()); @@ -1157,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 @@ -1183,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. @@ -1193,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; @@ -1218,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 @@ -1240,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))); @@ -1257,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 @@ -1278,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 @@ -1292,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))); } @@ -1325,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); ////////////////////////////////////////////////////////////// @@ -1349,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); @@ -1375,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 @@ -1388,13 +1426,13 @@ 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); // 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); + checkMetrics(__LINE__, env, 3, 10, 6, 5, 256); // This next test should remain unchanged regardless of // transaction ordering @@ -1404,66 +1442,62 @@ class TxQ1_test : public beast::unit_test::suite 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_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)); + 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; + ++(++charlieSeq); + // ++dariaSeq; + ++elmoSeq; + // ++fredSeq; ++gwenSeq; - ++hankSeq; + // ++hankSeq; auto getTxsQueued = [&]() { auto const txs = env.app().getTxQ().getTxs(); std::map result; for (auto const& tx : txs) { - /* - std::cerr << "Acct: " << tx.txn->at(sfAccount) << - ", Seq: " << tx.txn->at(sfSequence) << std::endl; - */ ++result[tx.txn->at(sfAccount)]; } return result; }; auto qTxCount1 = getTxsQueued(); BEAST_EXPECT(qTxCount1.size() <= 3); - /* - std::cerr << "Queued:" << std::endl; - for (auto const& pair : qTxCount1) - { - std::cerr << "\t( " << pair.first << ", " << pair.second << - " )" << std::endl; - } - std::cerr << std::endl; - std::cerr << "alice: " << alice.id() << ", seq: " << aliceSeq << - ", q: " << qTxCount1[alice.id()] << std::endl; - std::cerr << "bob: " << bob.id() << ", seq: " << bobSeq << - ", q: " << qTxCount1[bob.id()] << std::endl; - std::cerr << "charlie: " << charlie.id() << ", seq: " << charlieSeq << - ", q: " << qTxCount1[charlie.id()] << std::endl; - std::cerr << "daria: " << daria.id() << ", seq: " << dariaSeq << - ", q: " << qTxCount1[daria.id()] << std::endl; - std::cerr << "elmo: " << elmo.id() << ", seq: " << elmoSeq << - ", q: " << qTxCount1[elmo.id()] << std::endl; - std::cerr << "fred: " << fred.id() << ", seq: " << fredSeq << - ", q: " << qTxCount1[fred.id()] << std::endl; - std::cerr << "gwen: " << gwen.id() << ", seq: " << gwenSeq << - ", q: " << qTxCount1[gwen.id()] << std::endl; - std::cerr << "hank: " << hank.id() << ", seq: " << hankSeq << - ", q: " << qTxCount1[hank.id()] << std::endl; - */ // Fill up the queue again env(noop(alice), @@ -1482,7 +1516,7 @@ class TxQ1_test : public beast::unit_test::suite 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(env, 10, 10, 6, 5, 385); + 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 @@ -1492,66 +1526,65 @@ class TxQ1_test : public beast::unit_test::suite seq(aliceSeq + qTxCount1[alice.id()]++), queued); - /* - std::cerr << "Queued:" << std::endl; - for (auto const& pair : qTxCount1) - { - std::cerr << "\t( " << pair.first << ", " << pair.second << - " )" << std::endl; - } - */ - checkMetrics(env, 10, 10, 6, 5, 385); + 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); + checkMetrics(__LINE__, env, 4, 12, 7, 6, 256); // Refresh the queue counts auto qTxCount2 = getTxsQueued(); BEAST_EXPECT(qTxCount2.size() <= 4); - /* - std::cerr << "Queued:" << std::endl; - for (auto const& pair : qTxCount2) - { - std::cerr << "\t( " << pair.first << ", " << pair.second << - " )" << std::endl; - } - */ - // This next test should remain unchanged regardless of // transaction ordering BEAST_EXPECT( aliceSeq + bobSeq + charlieSeq + dariaSeq + elmoSeq + fredSeq + - gwenSeq + hankSeq + 9 == + 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_EXPECT( + BEAST_EXPECTS( aliceSeq + qTxCount1[alice.id()] - qTxCount2[alice.id()] == - env.seq(alice)); - BEAST_EXPECT( - bobSeq + qTxCount1[bob.id()] - qTxCount2[bob.id()] == env.seq(bob)); - BEAST_EXPECT( + 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)); - BEAST_EXPECT( + 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)); - BEAST_EXPECT( + 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)); - BEAST_EXPECT( + 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)); - BEAST_EXPECT( + 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)); - BEAST_EXPECT( + 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)); + env.seq(hank), + "hank: "s + std::to_string(hankSeq) + ", " + + std::to_string(env.seq(hank))); } void @@ -1566,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, @@ -1581,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)); } @@ -1611,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 @@ -1713,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. @@ -1737,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. @@ -1745,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. @@ -1753,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, @@ -1767,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 @@ -1779,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 @@ -1805,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. @@ -1818,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); @@ -1844,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. @@ -1886,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. @@ -1914,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); } } @@ -1935,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}; { @@ -1951,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); @@ -1981,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); @@ -2042,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); @@ -2076,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); } } @@ -2108,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"]; @@ -2126,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 @@ -2147,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); @@ -2155,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 @@ -2168,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 @@ -2184,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); @@ -2193,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 @@ -2201,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 @@ -2217,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); @@ -2227,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 @@ -2243,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); @@ -2256,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 @@ -2270,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); @@ -2281,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( @@ -2296,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); @@ -2321,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. @@ -2345,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); @@ -2361,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 @@ -2380,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); @@ -2395,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 @@ -2416,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); @@ -2426,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)); } @@ -2516,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); ///////////////////////////////////////////////////////////////// @@ -2547,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 @@ -2571,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. @@ -2690,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); @@ -2710,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, @@ -2719,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)); @@ -2738,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); } @@ -2784,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); @@ -2831,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, @@ -2841,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 @@ -2866,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 @@ -2897,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)); @@ -2906,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); } @@ -2935,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); @@ -2955,7 +2988,7 @@ 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()); SeqProxy seq = SeqProxy::sequence(aliceSeq); @@ -2980,25 +3013,25 @@ 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()); @@ -3024,7 +3057,7 @@ 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()); auto seq = aliceSeq; @@ -3039,7 +3072,7 @@ 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()); @@ -3097,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); @@ -3125,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); @@ -3172,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); @@ -3183,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); @@ -3239,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); @@ -3307,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); @@ -3378,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"); @@ -3613,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; @@ -3663,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)); @@ -3677,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) { @@ -3746,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); @@ -3792,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 @@ -3805,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 @@ -3815,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"); @@ -3835,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 @@ -3848,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"); @@ -3864,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); @@ -3873,7 +3906,7 @@ 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()); BEAST_EXPECT(aliceQueue.size() == 2); @@ -3887,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)"); @@ -3904,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 @@ -3919,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); @@ -3931,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); } } @@ -3960,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); } @@ -4046,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. @@ -4104,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 @@ -4132,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 @@ -4171,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}; @@ -4183,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 @@ -4204,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 @@ -4238,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 @@ -4286,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; @@ -4297,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, @@ -4310,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, @@ -4337,6 +4372,7 @@ class TxQ1_test : public beast::unit_test::suite } std::size_t expectedInQueue = 60; checkMetrics( + __LINE__, env, expectedInQueue, 5 * expectedPerLedger, @@ -4364,6 +4400,7 @@ class TxQ1_test : public beast::unit_test::suite expectedInLedger -= expectedInQueue; ++expectedPerLedger; checkMetrics( + __LINE__, env, expectedInQueue, 5 * expectedPerLedger, @@ -4450,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. @@ -4496,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; @@ -4509,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; @@ -4522,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 @@ -4546,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. @@ -4563,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()) @@ -4571,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. @@ -4683,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); } { @@ -4744,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();