mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-28 06:55:50 +00:00
Don't use tapENABLE_TESTING for TxQ.
* Enable FeeEscalation feature in TxQ tests. * Elapsed time for simulated consensus.
This commit is contained in:
committed by
Vinnie Falco
parent
a5583de6e6
commit
1bce85d7b6
@@ -70,7 +70,8 @@ public:
|
||||
server in standalone mode and SHOULD NOT be used during the normal
|
||||
consensus process.
|
||||
*/
|
||||
virtual void simulate () = 0;
|
||||
virtual void simulate (
|
||||
boost::optional<std::chrono::milliseconds> consensusDelay) = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -902,13 +902,14 @@ bool LedgerConsensusImp::peerPosition (LedgerProposal::ref newPosition)
|
||||
return true;
|
||||
}
|
||||
|
||||
void LedgerConsensusImp::simulate ()
|
||||
void LedgerConsensusImp::simulate (
|
||||
boost::optional<std::chrono::milliseconds> consensusDelay)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> _(lock_);
|
||||
|
||||
JLOG (j_.info) << "Simulating consensus";
|
||||
closeLedger ();
|
||||
mCurrentMSeconds = 100ms;
|
||||
mCurrentMSeconds = consensusDelay.value_or(100ms);
|
||||
beginAccept (true);
|
||||
JLOG (j_.info) << "Simulation complete";
|
||||
}
|
||||
|
||||
@@ -150,7 +150,8 @@ public:
|
||||
*/
|
||||
bool peerPosition (LedgerProposal::ref newPosition) override;
|
||||
|
||||
void simulate () override;
|
||||
void simulate(
|
||||
boost::optional<std::chrono::milliseconds> consensusDelay) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
@@ -350,7 +350,8 @@ public:
|
||||
Json::Value getServerInfo (bool human, bool admin) override;
|
||||
void clearLedgerFetch () override;
|
||||
Json::Value getLedgerFetchInfo () override;
|
||||
std::uint32_t acceptLedger () override;
|
||||
std::uint32_t acceptLedger (
|
||||
boost::optional<std::chrono::milliseconds> consensusDelay) override;
|
||||
uint256 getConsensusLCL () override;
|
||||
void reportFeeChange () override;
|
||||
|
||||
@@ -2465,7 +2466,8 @@ bool NetworkOPsImp::unsubBook (std::uint64_t uSeq, Book const& book)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::uint32_t NetworkOPsImp::acceptLedger ()
|
||||
std::uint32_t NetworkOPsImp::acceptLedger (
|
||||
boost::optional<std::chrono::milliseconds> consensusDelay)
|
||||
{
|
||||
// This code-path is exclusively used when the server is in standalone
|
||||
// mode via `ledger_accept`
|
||||
@@ -2477,7 +2479,7 @@ std::uint32_t NetworkOPsImp::acceptLedger ()
|
||||
// FIXME Could we improve on this and remove the need for a specialized
|
||||
// API in LedgerConsensus?
|
||||
beginConsensus (m_ledgerMaster.getClosedLedger ()->getHash ());
|
||||
mLedgerConsensus->simulate ();
|
||||
mLedgerConsensus->simulate (consensusDelay);
|
||||
return m_ledgerMaster.getCurrentLedger ()->info().seq;
|
||||
}
|
||||
|
||||
|
||||
@@ -190,7 +190,8 @@ public:
|
||||
performs a virtual consensus round, with all the transactions we are
|
||||
proposing being accepted.
|
||||
*/
|
||||
virtual std::uint32_t acceptLedger () = 0;
|
||||
virtual std::uint32_t acceptLedger (
|
||||
boost::optional<std::chrono::milliseconds> consensusDelay = boost::none) = 0;
|
||||
|
||||
virtual uint256 getConsensusLCL () = 0;
|
||||
|
||||
|
||||
@@ -214,8 +214,7 @@ public:
|
||||
@return Whether any txs were added to the view.
|
||||
*/
|
||||
bool
|
||||
accept(Application& app, OpenView& view,
|
||||
ApplyFlags flags = tapNONE);
|
||||
accept(Application& app, OpenView& view);
|
||||
|
||||
/**
|
||||
We have a new last validated ledger, update and clean up the
|
||||
@@ -233,8 +232,7 @@ public:
|
||||
*/
|
||||
void
|
||||
processValidatedLedger(Application& app,
|
||||
OpenView const& view, bool timeLeap,
|
||||
ApplyFlags flags = tapNONE);
|
||||
OpenView const& view, bool timeLeap);
|
||||
|
||||
/** Used by tests only.
|
||||
*/
|
||||
|
||||
@@ -304,9 +304,8 @@ TxQ::apply(Application& app, OpenView& view,
|
||||
ApplyFlags flags, beast::Journal j)
|
||||
{
|
||||
auto const allowEscalation =
|
||||
(flags & tapENABLE_TESTING) ||
|
||||
(view.rules().enabled(featureFeeEscalation,
|
||||
app.config().features));
|
||||
(view.rules().enabled(featureFeeEscalation,
|
||||
app.config().features));
|
||||
if (!allowEscalation)
|
||||
{
|
||||
return ripple::apply(app, view, *tx, flags, j);
|
||||
@@ -502,11 +501,9 @@ TxQ::apply(Application& app, OpenView& view,
|
||||
|
||||
void
|
||||
TxQ::processValidatedLedger(Application& app,
|
||||
OpenView const& view, bool timeLeap,
|
||||
ApplyFlags flags)
|
||||
OpenView const& view, bool timeLeap)
|
||||
{
|
||||
auto const allowEscalation =
|
||||
(flags & tapENABLE_TESTING) ||
|
||||
(view.rules().enabled(featureFeeEscalation,
|
||||
app.config().features));
|
||||
if (!allowEscalation)
|
||||
@@ -560,10 +557,9 @@ TxQ::processValidatedLedger(Application& app,
|
||||
|
||||
bool
|
||||
TxQ::accept(Application& app,
|
||||
OpenView& view, ApplyFlags flags)
|
||||
OpenView& view)
|
||||
{
|
||||
auto const allowEscalation =
|
||||
(flags & tapENABLE_TESTING) ||
|
||||
(view.rules().enabled(featureFeeEscalation,
|
||||
app.config().features));
|
||||
if (!allowEscalation)
|
||||
|
||||
@@ -20,9 +20,11 @@
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/misc/TxQ.h>
|
||||
#include <ripple/app/ledger/LedgerConsensus.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/core/LoadFeeTrack.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/TestSuite.h>
|
||||
#include <ripple/protocol/Feature.h>
|
||||
#include <ripple/protocol/JsonFields.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <ripple/test/jtx.h>
|
||||
@@ -58,41 +60,6 @@ class TxQ_test : public TestSuite
|
||||
expect(metrics.expFeeLevel == expectedCurFeeLevel, "expFeeLevel");
|
||||
}
|
||||
|
||||
void
|
||||
close(jtx::Env& env, size_t expectedTxSetSize, bool timeLeap = false)
|
||||
{
|
||||
{
|
||||
auto const view = env.current();
|
||||
expect(view->txCount() == expectedTxSetSize, "TxSet size mismatch");
|
||||
}
|
||||
env.close();
|
||||
}
|
||||
|
||||
void
|
||||
submit(jtx::Env& env, jtx::JTx const& jt)
|
||||
{
|
||||
// Env checks this, but this test shouldn't
|
||||
// generate any malformed txns.
|
||||
expect(jt.stx);
|
||||
|
||||
bool didApply;
|
||||
TER ter;
|
||||
|
||||
env.app().openLedger().modify(
|
||||
[&](OpenView& view, beast::Journal j)
|
||||
{
|
||||
std::tie(ter, didApply) =
|
||||
env.app().getTxQ().apply(env.app(),
|
||||
view, jt.stx, tapENABLE_TESTING,
|
||||
env.journal);
|
||||
|
||||
return didApply;
|
||||
}
|
||||
);
|
||||
|
||||
env.postconditions(jt, ter, didApply);
|
||||
}
|
||||
|
||||
static
|
||||
std::unique_ptr<Config>
|
||||
makeConfig()
|
||||
@@ -111,8 +78,9 @@ public:
|
||||
void testQueue()
|
||||
{
|
||||
using namespace jtx;
|
||||
using namespace std::chrono;
|
||||
|
||||
Env env(*this, makeConfig());
|
||||
Env env(*this, makeConfig(), features(featureFeeEscalation));
|
||||
|
||||
auto& txq = env.app().getTxQ();
|
||||
txq.setMinimumTx(3);
|
||||
@@ -137,14 +105,12 @@ public:
|
||||
checkMetrics(env, 0, boost::none, 4, 3, 256, 500);
|
||||
|
||||
// Alice - price starts exploding: held
|
||||
submit(env,
|
||||
env.jt(noop(alice), queued));
|
||||
env(noop(alice), queued);
|
||||
checkMetrics(env, 1, boost::none, 4, 3, 256, 500);
|
||||
|
||||
// Alice - Alice is already in the queue, so can't hold.
|
||||
submit(env,
|
||||
env.jt(noop(alice), seq(env.seq(alice) + 1),
|
||||
ter(telINSUF_FEE_P)));
|
||||
env(noop(alice), seq(env.seq(alice) + 1),
|
||||
ter(telINSUF_FEE_P));
|
||||
checkMetrics(env, 1, boost::none, 4, 3, 256, 500);
|
||||
|
||||
auto openLedgerFee =
|
||||
@@ -154,22 +120,19 @@ public:
|
||||
};
|
||||
// Alice's next transaction -
|
||||
// fails because the item in the TxQ hasn't applied.
|
||||
submit(env,
|
||||
env.jt(noop(alice), openLedgerFee(),
|
||||
seq(env.seq(alice) + 1), ter(terPRE_SEQ)));
|
||||
env(noop(alice), openLedgerFee(),
|
||||
seq(env.seq(alice) + 1), ter(terPRE_SEQ));
|
||||
checkMetrics(env, 1, boost::none, 4, 3, 256, 500);
|
||||
|
||||
// Bob with really high fee - applies
|
||||
submit(env,
|
||||
env.jt(noop(bob), openLedgerFee()));
|
||||
env(noop(bob), openLedgerFee());
|
||||
checkMetrics(env, 1, boost::none, 5, 3, 256, 500);
|
||||
|
||||
// Daria with low fee: hold
|
||||
submit(env,
|
||||
env.jt(noop(daria), fee(1000), queued));
|
||||
env(noop(daria), fee(1000), queued);
|
||||
checkMetrics(env, 2, boost::none, 5, 3, 256, 500);
|
||||
|
||||
close(env, 5);
|
||||
env.close();
|
||||
// Verify that the held transactions got applied
|
||||
auto lastMedian = 500;
|
||||
checkMetrics(env, 0, 10, 2, 5, 256, lastMedian);
|
||||
@@ -181,27 +144,19 @@ public:
|
||||
checkMetrics(env, 0, 10, 6, 5, 256, lastMedian);
|
||||
|
||||
// Now get a bunch of transactions held.
|
||||
submit(env,
|
||||
env.jt(noop(alice), fee(12), queued));
|
||||
env(noop(alice), fee(12), queued);
|
||||
checkMetrics(env, 1, 10, 6, 5, 256, lastMedian);
|
||||
|
||||
submit(env,
|
||||
env.jt(noop(bob), fee(10), queued)); // won't clear the queue
|
||||
submit(env,
|
||||
env.jt(noop(charlie), fee(20), queued));
|
||||
submit(env,
|
||||
env.jt(noop(daria), fee(15), queued));
|
||||
submit(env,
|
||||
env.jt(noop(elmo), fee(11), queued));
|
||||
submit(env,
|
||||
env.jt(noop(fred), fee(19), queued));
|
||||
submit(env,
|
||||
env.jt(noop(gwen), fee(16), queued));
|
||||
submit(env,
|
||||
env.jt(noop(hank), fee(18), queued));
|
||||
env(noop(bob), fee(10), queued); // won't clear the queue
|
||||
env(noop(charlie), fee(20), queued);
|
||||
env(noop(daria), fee(15), queued);
|
||||
env(noop(elmo), fee(11), queued);
|
||||
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, lastMedian);
|
||||
|
||||
close(env, 6);
|
||||
env.close();
|
||||
// Verify that the held transactions got applied
|
||||
lastMedian = 500;
|
||||
checkMetrics(env, 1, 12, 7, 6, 256, lastMedian);
|
||||
@@ -211,40 +166,35 @@ public:
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// Hank sends another txn
|
||||
submit(env,
|
||||
env.jt(noop(hank), fee(10), queued));
|
||||
env(noop(hank), fee(10), queued);
|
||||
// But he's not going to leave it in the queue
|
||||
checkMetrics(env, 2, 12, 7, 6, 256, lastMedian);
|
||||
|
||||
// Hank sees his txn got held and bumps the fee,
|
||||
// but doesn't even bump it enough to requeue
|
||||
submit(env,
|
||||
env.jt(noop(hank), fee(11), ter(telINSUF_FEE_P)));
|
||||
env(noop(hank), fee(11), ter(telINSUF_FEE_P));
|
||||
checkMetrics(env, 2, 12, 7, 6, 256, lastMedian);
|
||||
|
||||
// Hank sees his txn got held and bumps the fee,
|
||||
// enough to requeue, but doesn't bump it enough to
|
||||
// apply to the ledger
|
||||
submit(env,
|
||||
env.jt(noop(hank), fee(6000), queued));
|
||||
env(noop(hank), fee(6000), queued);
|
||||
// But he's not going to leave it in the queue
|
||||
checkMetrics(env, 2, 12, 7, 6, 256, lastMedian);
|
||||
|
||||
// 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.
|
||||
submit(env,
|
||||
env.jt(noop(hank), openLedgerFee()));
|
||||
env(noop(hank), openLedgerFee());
|
||||
checkMetrics(env, 1, 12, 8, 6, 256, lastMedian);
|
||||
|
||||
// Hank then sends another, less important txn
|
||||
// (In addition to the metrics, this will verify that
|
||||
// the original txn got removed.)
|
||||
submit(env,
|
||||
env.jt(noop(hank), fee(6000), queued));
|
||||
env(noop(hank), fee(6000), queued);
|
||||
checkMetrics(env, 2, 12, 8, 6, 256, lastMedian);
|
||||
|
||||
close(env, 8);
|
||||
env.close();
|
||||
|
||||
// Verify that bob and hank's txns were applied
|
||||
lastMedian = 500;
|
||||
@@ -253,12 +203,12 @@ public:
|
||||
// Close again with a simulated time leap to
|
||||
// reset the escalation limit down to minimum
|
||||
lastMedian = 76928;
|
||||
close(env, 2, true);
|
||||
env.close(env.now() + 5s, 10000ms);
|
||||
checkMetrics(env, 0, 16, 0, 3, 256, lastMedian);
|
||||
// Then close once more without the time leap
|
||||
// to reset the queue maxsize down to minimum
|
||||
lastMedian = 500;
|
||||
close(env, 0);
|
||||
env.close();
|
||||
checkMetrics(env, 0, 6, 0, 3, 256, lastMedian);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
@@ -266,56 +216,44 @@ public:
|
||||
// At this point, the queue should have a limit of 6.
|
||||
// Stuff the ledger and queue so we can verify that
|
||||
// stuff gets kicked out.
|
||||
submit(env,
|
||||
env.jt(noop(hank)));
|
||||
submit(env,
|
||||
env.jt(noop(gwen)));
|
||||
submit(env,
|
||||
env.jt(noop(fred)));
|
||||
submit(env,
|
||||
env.jt(noop(elmo)));
|
||||
env(noop(hank));
|
||||
env(noop(gwen));
|
||||
env(noop(fred));
|
||||
env(noop(elmo));
|
||||
checkMetrics(env, 0, 6, 4, 3, 256, lastMedian);
|
||||
|
||||
// Use explicit fees so we can control which txn
|
||||
// will get dropped
|
||||
submit(env,
|
||||
env.jt(noop(alice), fee(20), queued));
|
||||
submit(env,
|
||||
env.jt(noop(hank), fee(19), queued));
|
||||
submit(env,
|
||||
env.jt(noop(gwen), fee(18), queued));
|
||||
submit(env,
|
||||
env.jt(noop(fred), fee(17), queued));
|
||||
submit(env,
|
||||
env.jt(noop(elmo), fee(16), queued));
|
||||
env(noop(alice), fee(20), queued);
|
||||
env(noop(hank), fee(19), queued);
|
||||
env(noop(gwen), fee(18), queued);
|
||||
env(noop(fred), fee(17), queued);
|
||||
env(noop(elmo), fee(16), queued);
|
||||
// This one gets into the queue, but gets dropped when the
|
||||
// higher fee one is added later.
|
||||
submit(env,
|
||||
env.jt(noop(daria), fee(15), queued));
|
||||
env(noop(daria), fee(15), queued);
|
||||
|
||||
// Queue is full now.
|
||||
checkMetrics(env, 6, 6, 4, 3, 385, lastMedian);
|
||||
|
||||
// Try to add another transaction with the default (low) fee,
|
||||
// it should fail because the queue is full.
|
||||
submit(env,
|
||||
env.jt(noop(charlie), ter(telINSUF_FEE_P)));
|
||||
env(noop(charlie), ter(telINSUF_FEE_P));
|
||||
|
||||
// Add another transaction, with a higher fee,
|
||||
// Not high enough to get into the ledger, but high
|
||||
// enough to get into the queue (and kick somebody out)
|
||||
submit(env,
|
||||
env.jt(noop(charlie), fee(100), queued));
|
||||
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, lastMedian);
|
||||
|
||||
close(env, 4);
|
||||
env.close();
|
||||
lastMedian = 500;
|
||||
checkMetrics(env, 1, 8, 5, 4, 256, lastMedian);
|
||||
|
||||
lastMedian = 500;
|
||||
close(env, 5);
|
||||
env.close();
|
||||
checkMetrics(env, 0, 10, 1, 5, 256, lastMedian);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
@@ -332,13 +270,11 @@ public:
|
||||
// Stuff the ledger.
|
||||
for (int i = 0; i <= txnsNeeded; ++i)
|
||||
{
|
||||
submit(env,
|
||||
env.jt(noop(env.master)));
|
||||
env(noop(env.master));
|
||||
}
|
||||
|
||||
// Queue one straightforward transaction
|
||||
submit(env,
|
||||
env.jt(noop(env.master), fee(20), queued));
|
||||
env(noop(env.master), fee(20), queued);
|
||||
++metrics.txCount;
|
||||
|
||||
checkMetrics(env, metrics.txCount,
|
||||
@@ -350,8 +286,9 @@ public:
|
||||
void testLastLedgerSeq()
|
||||
{
|
||||
using namespace jtx;
|
||||
using namespace std::chrono;
|
||||
|
||||
Env env(*this, makeConfig());
|
||||
Env env(*this, makeConfig(), features(featureFeeEscalation));
|
||||
|
||||
auto& txq = env.app().getTxQ();
|
||||
txq.setMinimumTx(2);
|
||||
@@ -367,53 +304,43 @@ public:
|
||||
|
||||
checkMetrics(env, 0, boost::none, 0, 2, 256, 500);
|
||||
|
||||
// Fund these accounts and close the ledger without
|
||||
// involving the queue, so that stats aren't affected.
|
||||
env.fund(XRP(1000), noripple(alice, bob, charlie, daria, edgar, felicia));
|
||||
env.close();
|
||||
// Fund across several ledgers so the TxQ metrics stay restricted.
|
||||
env.fund(XRP(1000), noripple(alice, bob));
|
||||
env.close(env.now() + 5s, 10000ms);
|
||||
env.fund(XRP(1000), noripple(charlie, daria));
|
||||
env.close(env.now() + 5s, 10000ms);
|
||||
env.fund(XRP(1000), noripple(edgar, felicia));
|
||||
env.close(env.now() + 5s, 10000ms);
|
||||
|
||||
checkMetrics(env, 0, boost::none, 0, 2, 256, 500);
|
||||
submit(env,
|
||||
env.jt(noop(bob)));
|
||||
submit(env,
|
||||
env.jt(noop(charlie)));
|
||||
submit(env,
|
||||
env.jt(noop(daria)));
|
||||
env(noop(bob));
|
||||
env(noop(charlie));
|
||||
env(noop(daria));
|
||||
checkMetrics(env, 0, boost::none, 3, 2, 256, 500);
|
||||
|
||||
// Queue an item with a LastLedgerSeq.
|
||||
submit(env,
|
||||
env.jt(noop(alice), json(R"({"LastLedgerSequence":4})"),
|
||||
queued));
|
||||
env(noop(alice), json(R"({"LastLedgerSequence":7})"),
|
||||
queued);
|
||||
// Queue items with higher fees to force the previous
|
||||
// txn to wait.
|
||||
submit(env,
|
||||
env.jt(noop(bob), fee(20), queued));
|
||||
submit(env,
|
||||
env.jt(noop(charlie), fee(20), queued));
|
||||
submit(env,
|
||||
env.jt(noop(daria), fee(20), queued));
|
||||
submit(env,
|
||||
env.jt(noop(edgar), fee(20), queued));
|
||||
env(noop(bob), fee(20), queued);
|
||||
env(noop(charlie), fee(20), queued);
|
||||
env(noop(daria), fee(20), queued);
|
||||
env(noop(edgar), fee(20), queued);
|
||||
checkMetrics(env, 5, boost::none, 3, 2, 256, 500);
|
||||
|
||||
close(env, 3);
|
||||
env.close();
|
||||
checkMetrics(env, 1, 6, 4, 3, 256, 500);
|
||||
|
||||
// Keep alice's transaction waiting.
|
||||
submit(env,
|
||||
env.jt(noop(bob), fee(20), queued));
|
||||
submit(env,
|
||||
env.jt(noop(charlie), fee(20), queued));
|
||||
submit(env,
|
||||
env.jt(noop(daria), fee(20), queued));
|
||||
submit(env,
|
||||
env.jt(noop(edgar), fee(20), queued));
|
||||
submit(env,
|
||||
env.jt(noop(felicia), fee(20), queued));
|
||||
env(noop(bob), fee(20), queued);
|
||||
env(noop(charlie), fee(20), queued);
|
||||
env(noop(daria), fee(20), queued);
|
||||
env(noop(edgar), fee(20), queued);
|
||||
env(noop(felicia), fee(20), queued);
|
||||
checkMetrics(env, 6, 6, 4, 3, 257, 500);
|
||||
|
||||
close(env, 4);
|
||||
env.close();
|
||||
// alice's transaction expired without getting
|
||||
// into the ledger, so the queue is now empty.
|
||||
checkMetrics(env, 0, 8, 5, 4, 256, 512);
|
||||
@@ -423,8 +350,9 @@ public:
|
||||
void testZeroFeeTxn()
|
||||
{
|
||||
using namespace jtx;
|
||||
using namespace std::chrono;
|
||||
|
||||
Env env(*this, makeConfig());
|
||||
Env env(*this, makeConfig(), features(featureFeeEscalation));
|
||||
|
||||
auto& txq = env.app().getTxQ();
|
||||
txq.setMinimumTx(2);
|
||||
@@ -439,24 +367,22 @@ public:
|
||||
// Fund these accounts and close the ledger without
|
||||
// involving the queue, so that stats aren't affected.
|
||||
env.fund(XRP(1000), noripple(alice, bob));
|
||||
env.close();
|
||||
env.close(env.now() + 5s, 10000ms);
|
||||
|
||||
// Fill the ledger
|
||||
submit(env, env.jt(noop(alice)));
|
||||
submit(env, env.jt(noop(alice)));
|
||||
submit(env, env.jt(noop(alice)));
|
||||
env(noop(alice));
|
||||
env(noop(alice));
|
||||
env(noop(alice));
|
||||
checkMetrics(env, 0, boost::none, 3, 2, 256, 500);
|
||||
|
||||
submit(env,
|
||||
env.jt(noop(bob), queued));
|
||||
env(noop(bob), queued);
|
||||
checkMetrics(env, 1, boost::none, 3, 2, 256, 500);
|
||||
|
||||
// Even though this transaction has a 0 fee,
|
||||
// SetRegularKey::calculateBaseFee indicates this is
|
||||
// a "free" transaction, so it has an "infinite" fee
|
||||
// level and goes into the open ledger.
|
||||
submit(env,
|
||||
env.jt(regkey(alice, bob), fee(0)));
|
||||
env(regkey(alice, bob), fee(0));
|
||||
checkMetrics(env, 1, boost::none, 4, 2, 256, 500);
|
||||
|
||||
// This transaction also has an "infinite" fee level,
|
||||
@@ -465,9 +391,8 @@ public:
|
||||
// with terPRE_SEQ (notably, *not* telINSUF_FEE_P).
|
||||
// This implicitly relies on preclaim succeeding and
|
||||
// canBeHeld failing under the hood.
|
||||
submit(env,
|
||||
env.jt(regkey(bob, alice), fee(0),
|
||||
seq(env.seq(bob) + 1), ter(terPRE_SEQ)));
|
||||
env(regkey(bob, alice), fee(0),
|
||||
seq(env.seq(bob) + 1), ter(terPRE_SEQ));
|
||||
checkMetrics(env, 1, boost::none, 4, 2, 256, 500);
|
||||
|
||||
}
|
||||
@@ -476,7 +401,7 @@ public:
|
||||
{
|
||||
using namespace jtx;
|
||||
|
||||
Env env(*this, makeConfig());
|
||||
Env env(*this, makeConfig(), features(featureFeeEscalation));
|
||||
|
||||
auto alice = Account("alice");
|
||||
auto bob = Account("bob");
|
||||
@@ -488,21 +413,19 @@ public:
|
||||
// expected.
|
||||
|
||||
// Fail in preflight
|
||||
submit(env,
|
||||
env.jt(pay(alice, bob, XRP(-1000)),
|
||||
ter(temBAD_AMOUNT)));
|
||||
env(pay(alice, bob, XRP(-1000)),
|
||||
ter(temBAD_AMOUNT));
|
||||
|
||||
// Fail in preclaim
|
||||
submit(env,
|
||||
env.jt(noop(alice), fee(XRP(100000)),
|
||||
ter(terINSUF_FEE_B)));
|
||||
env(noop(alice), fee(XRP(100000)),
|
||||
ter(terINSUF_FEE_B));
|
||||
}
|
||||
|
||||
void testQueuedFailure()
|
||||
{
|
||||
using namespace jtx;
|
||||
|
||||
Env env(*this, makeConfig());
|
||||
Env env(*this, makeConfig(), features(featureFeeEscalation));
|
||||
|
||||
auto& txq = env.app().getTxQ();
|
||||
txq.setMinimumTx(2);
|
||||
@@ -519,18 +442,36 @@ public:
|
||||
checkMetrics(env, 0, boost::none, 2, 2, 256, 500);
|
||||
|
||||
// Fill the ledger
|
||||
submit(env, env.jt(noop(alice)));
|
||||
env(noop(alice));
|
||||
checkMetrics(env, 0, boost::none, 3, 2, 256, 500);
|
||||
|
||||
// Put a transaction in the queue
|
||||
submit(env, env.jt(noop(alice), queued));
|
||||
env(noop(alice), queued);
|
||||
checkMetrics(env, 1, boost::none, 3, 2, 256, 500);
|
||||
|
||||
// Now cheat, and bypass the queue.
|
||||
env(noop(alice));
|
||||
{
|
||||
auto const& jt = env.jt(noop(alice));
|
||||
expect(jt.stx);
|
||||
|
||||
bool didApply;
|
||||
TER ter;
|
||||
|
||||
env.app().openLedger().modify(
|
||||
[&](OpenView& view, beast::Journal j)
|
||||
{
|
||||
std::tie(ter, didApply) =
|
||||
ripple::apply(env.app(),
|
||||
view, *jt.stx, tapNONE,
|
||||
env.journal);
|
||||
return didApply;
|
||||
}
|
||||
);
|
||||
env.postconditions(jt, ter, didApply);
|
||||
}
|
||||
checkMetrics(env, 1, boost::none, 4, 2, 256, 500);
|
||||
|
||||
close(env, 4);
|
||||
env.close();
|
||||
// Alice's queued transaction failed in TxQ::accept
|
||||
// with tefPAST_SEQ
|
||||
checkMetrics(env, 0, 8, 0, 4, 256, 500);
|
||||
|
||||
@@ -224,7 +224,8 @@ public:
|
||||
the close time of the resulting ledger.
|
||||
*/
|
||||
void
|
||||
close (NetClock::time_point closeTime);
|
||||
close (NetClock::time_point closeTime,
|
||||
boost::optional<std::chrono::milliseconds> consensusDelay = boost::none);
|
||||
|
||||
/** Close and advance the ledger.
|
||||
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
#include <ripple/test/jtx/seq.h>
|
||||
#include <ripple/test/jtx/sig.h>
|
||||
#include <ripple/test/jtx/utility.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/app/ledger/LedgerMaster.h>
|
||||
#include <ripple/app/ledger/LedgerTiming.h>
|
||||
#include <ripple/app/misc/NetworkOPs.h>
|
||||
#include <ripple/app/misc/TxQ.h>
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/basics/Slice.h>
|
||||
#include <ripple/core/ConfigSections.h>
|
||||
@@ -113,12 +113,13 @@ Env::closed()
|
||||
}
|
||||
|
||||
void
|
||||
Env::close(NetClock::time_point closeTime)
|
||||
Env::close(NetClock::time_point closeTime,
|
||||
boost::optional<std::chrono::milliseconds> consensusDelay)
|
||||
{
|
||||
// Round up to next distinguishable value
|
||||
closeTime += closed()->info().closeTimeResolution - 1s;
|
||||
bundle_.timeKeeper->set(closeTime);
|
||||
app().getOPs().acceptLedger();
|
||||
app().getOPs().acceptLedger(consensusDelay);
|
||||
bundle_.timeKeeper->set(
|
||||
closed()->info().closeTime);
|
||||
}
|
||||
@@ -260,8 +261,8 @@ Env::submit (JTx const& jt)
|
||||
app().openLedger().modify(
|
||||
[&](OpenView& view, beast::Journal j)
|
||||
{
|
||||
std::tie(ter_, didApply) = ripple::apply(
|
||||
app(), view, *jt.stx, applyFlags(),
|
||||
std::tie(ter_, didApply) = app().getTxQ().apply(
|
||||
app(), view, jt.stx, applyFlags(),
|
||||
beast::Journal{});
|
||||
return didApply;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user