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