mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-21 03:26:01 +00:00
Improve invariant checking:
Add a new invariant checker that verifies that we never charge a fee higher than specified in the transaction; we will charge less in some corner cases where the transacting account cannot afford the fee. Detect more anomalous conditions, and improve the logged error messages. Clarify the code flow associated with invoking the invariant checker from `Transactor`, add extra comments and improve naming to make the code self-documenting.
This commit is contained in:
committed by
seelabs
parent
118c25c0f0
commit
2ac1c2b433
@@ -52,15 +52,21 @@ class Invariants_test : public beast::unit_test::suite
|
||||
// this is common setup/method for running a failing invariant check. The
|
||||
// precheck function is used to manipulate the ApplyContext with view
|
||||
// changes that will cause the check to fail.
|
||||
using Precheck = std::function <
|
||||
bool (
|
||||
test::jtx::Account const& a,
|
||||
test::jtx::Account const& b,
|
||||
ApplyContext& ac)>;
|
||||
|
||||
using TXMod = std::function <
|
||||
void (STTx& tx)>;
|
||||
|
||||
void
|
||||
doInvariantCheck( bool enabled,
|
||||
std::vector<std::string> const& expect_logs,
|
||||
std::function <
|
||||
bool (
|
||||
test::jtx::Account const& a,
|
||||
test::jtx::Account const& b,
|
||||
ApplyContext& ac)>
|
||||
const& precheck )
|
||||
Precheck const& precheck,
|
||||
XRPAmount fee = XRPAmount{},
|
||||
TXMod txmod = [](STTx&){})
|
||||
{
|
||||
using namespace test::jtx;
|
||||
Env env {*this};
|
||||
@@ -79,6 +85,7 @@ class Invariants_test : public beast::unit_test::suite
|
||||
|
||||
// dummy/empty tx to setup the AccountContext
|
||||
auto tx = STTx {ttACCOUNT_SET, [](STObject&){ } };
|
||||
txmod(tx);
|
||||
OpenView ov {*env.current()};
|
||||
TestSink sink;
|
||||
beast::Journal jlog {sink};
|
||||
@@ -98,7 +105,7 @@ class Invariants_test : public beast::unit_test::suite
|
||||
// invoke check twice to cover tec and tef cases
|
||||
for (auto i : {0,1})
|
||||
{
|
||||
tr = ac.checkInvariants(tr);
|
||||
tr = ac.checkInvariants(tr, fee);
|
||||
if (enabled)
|
||||
{
|
||||
BEAST_EXPECT(tr == (i == 0
|
||||
@@ -144,7 +151,7 @@ class Invariants_test : public beast::unit_test::suite
|
||||
testcase << "checks " << (enabled ? "enabled" : "disabled") <<
|
||||
" - XRP created";
|
||||
doInvariantCheck (enabled,
|
||||
{{ "XRP net change was 500 on a fee of 0" }},
|
||||
{{ "XRP net change was positive: 500" }},
|
||||
[](Account const& A1, Account const&, ApplyContext& ac)
|
||||
{
|
||||
// put a single account in the view and "manufacture" some XRP
|
||||
@@ -185,7 +192,7 @@ class Invariants_test : public beast::unit_test::suite
|
||||
" - LE types don't match";
|
||||
doInvariantCheck (enabled,
|
||||
{{ "ledger entry type mismatch" },
|
||||
{ "XRP net change was -1000000000 on a fee of 0" }},
|
||||
{ "XRP net change of -1000000000 doesn't match fee 0" }},
|
||||
[](Account const& A1, Account const&, ApplyContext& ac)
|
||||
{
|
||||
// replace an entry in the table with an SLE of a different type
|
||||
@@ -258,7 +265,7 @@ class Invariants_test : public beast::unit_test::suite
|
||||
|
||||
doInvariantCheck (enabled,
|
||||
{{ "incorrect account XRP balance" },
|
||||
{ "XRP net change was 99999999000000001 on a fee of 0" }},
|
||||
{ "XRP net change was positive: 99999999000000001" }},
|
||||
[](Account const& A1, Account const&, ApplyContext& ac)
|
||||
{
|
||||
// balance exceeds genesis amount
|
||||
@@ -272,7 +279,7 @@ class Invariants_test : public beast::unit_test::suite
|
||||
|
||||
doInvariantCheck (enabled,
|
||||
{{ "incorrect account XRP balance" },
|
||||
{ "XRP net change was -1000000001 on a fee of 0" }},
|
||||
{ "XRP net change of -1000000001 doesn't match fee 0" }},
|
||||
[](Account const& A1, Account const&, ApplyContext& ac)
|
||||
{
|
||||
// balance is negative
|
||||
@@ -285,6 +292,37 @@ class Invariants_test : public beast::unit_test::suite
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
testTransactionFeeCheck(bool enabled)
|
||||
{
|
||||
using namespace test::jtx;
|
||||
using namespace std::string_literals;
|
||||
testcase << "checks " << (enabled ? "enabled" : "disabled") <<
|
||||
" - Transaction fee checks";
|
||||
|
||||
doInvariantCheck (enabled,
|
||||
{{ "fee paid was negative: -1" },
|
||||
{ "XRP net change of 0 doesn't match fee -1" }},
|
||||
[](Account const&, Account const&, ApplyContext&) { return true; },
|
||||
XRPAmount{-1});
|
||||
|
||||
doInvariantCheck (enabled,
|
||||
{{ "fee paid exceeds system limit: "s +
|
||||
std::to_string(SYSTEM_CURRENCY_START) },
|
||||
{ "XRP net change of 0 doesn't match fee "s +
|
||||
std::to_string(SYSTEM_CURRENCY_START) }},
|
||||
[](Account const&, Account const&, ApplyContext&) { return true; },
|
||||
XRPAmount{SYSTEM_CURRENCY_START});
|
||||
|
||||
doInvariantCheck (enabled,
|
||||
{{ "fee paid is 20 exceeds fee specified in transaction." },
|
||||
{ "XRP net change of 0 doesn't match fee 20" }},
|
||||
[](Account const&, Account const&, ApplyContext&) { return true; },
|
||||
XRPAmount{20},
|
||||
[](STTx& tx) { tx.setFieldAmount(sfFee, XRPAmount{10}); } );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testNoBadOffers(bool enabled)
|
||||
{
|
||||
@@ -373,7 +411,7 @@ class Invariants_test : public beast::unit_test::suite
|
||||
});
|
||||
|
||||
doInvariantCheck (enabled,
|
||||
{{ "XRP net change was -1000000 on a fee of 0"},
|
||||
{{ "XRP net change of -1000000 doesn't match fee 0"},
|
||||
{ "escrow specifies invalid amount" }},
|
||||
[](Account const& A1, Account const&, ApplyContext& ac)
|
||||
{
|
||||
@@ -389,7 +427,7 @@ class Invariants_test : public beast::unit_test::suite
|
||||
});
|
||||
|
||||
doInvariantCheck (enabled,
|
||||
{{ "XRP net change was 100000000000000001 on a fee of 0" },
|
||||
{{ "XRP net change was positive: 100000000000000001" },
|
||||
{ "escrow specifies invalid amount" }},
|
||||
[](Account const& A1, Account const&, ApplyContext& ac)
|
||||
{
|
||||
@@ -419,6 +457,7 @@ public:
|
||||
testTypesMatch (b);
|
||||
testNoXRPTrustLine (b);
|
||||
testXRPBalanceCheck (b);
|
||||
testTransactionFeeCheck(b);
|
||||
testNoBadOffers (b);
|
||||
testNoZeroEscrow (b);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user