mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +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
@@ -22,6 +22,52 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
void
|
||||
TransactionFeeCheck::visitEntry(
|
||||
uint256 const&,
|
||||
bool,
|
||||
std::shared_ptr<SLE const> const&,
|
||||
std::shared_ptr<SLE const> const&)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
bool
|
||||
TransactionFeeCheck::finalize(
|
||||
STTx const& tx,
|
||||
TER const result,
|
||||
XRPAmount const fee,
|
||||
beast::Journal const& j)
|
||||
{
|
||||
// We should never charge a negative fee
|
||||
if (fee.drops() < 0)
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: fee paid was negative: " << fee.drops();
|
||||
return false;
|
||||
}
|
||||
|
||||
// We should never charge a fee that's greater than or equal to the
|
||||
// entire XRP supply.
|
||||
if (fee.drops() >= SYSTEM_CURRENCY_START)
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: fee paid exceeds system limit: " << fee.drops();
|
||||
return false;
|
||||
}
|
||||
|
||||
// We should never charge more for a transaction than the transaction
|
||||
// authorizes. It's possible to charge less in some circumstances.
|
||||
if (fee > tx.getFieldAmount(sfFee).xrp())
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: fee paid is " << fee.drops() <<
|
||||
" exceeds fee specified in transaction.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
XRPNotCreated::visitEntry(
|
||||
uint256 const&,
|
||||
@@ -29,6 +75,13 @@ XRPNotCreated::visitEntry(
|
||||
std::shared_ptr <SLE const> const& before,
|
||||
std::shared_ptr <SLE const> const& after)
|
||||
{
|
||||
/* We go through all modified ledger entries, looking only at account roots,
|
||||
* escrow payments, and payment channels. We remove from the total any
|
||||
* previous XRP values and add to the total any new XRP values. The net
|
||||
* balance of a payment channel is computed from two fields (amount and
|
||||
* balance) and deletions are ignored for paychan and escrow because the
|
||||
* amount fields have not been adjusted for those in the case of deletion.
|
||||
*/
|
||||
if(before)
|
||||
{
|
||||
switch (before->getType())
|
||||
@@ -69,15 +122,31 @@ XRPNotCreated::visitEntry(
|
||||
}
|
||||
|
||||
bool
|
||||
XRPNotCreated::finalize(STTx const& tx, TER /*tec*/, beast::Journal const& j)
|
||||
XRPNotCreated::finalize(
|
||||
STTx const& tx,
|
||||
TER const,
|
||||
XRPAmount const fee,
|
||||
beast::Journal const& j)
|
||||
{
|
||||
auto fee = tx.getFieldAmount(sfFee).xrp().drops();
|
||||
if(-1*fee <= drops_ && drops_ <= 0)
|
||||
return true;
|
||||
// The net change should never be positive, as this would mean that the
|
||||
// transaction created XRP out of thin air. That's not possible.
|
||||
if (drops_ > 0)
|
||||
{
|
||||
JLOG(j.fatal()) <<
|
||||
"Invariant failed: XRP net change was positive: " << drops_;
|
||||
return false;
|
||||
}
|
||||
|
||||
JLOG(j.fatal()) << "Invariant failed: XRP net change was " << drops_ <<
|
||||
" on a fee of " << fee;
|
||||
return false;
|
||||
// The negative of the net change should be equal to actual fee charged.
|
||||
if (-drops_ != fee.drops())
|
||||
{
|
||||
JLOG(j.fatal()) <<
|
||||
"Invariant failed: XRP net change of " << drops_ <<
|
||||
" doesn't match fee " << fee.drops();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -116,7 +185,7 @@ XRPBalanceChecks::visitEntry(
|
||||
}
|
||||
|
||||
bool
|
||||
XRPBalanceChecks::finalize(STTx const&, TER, beast::Journal const& j)
|
||||
XRPBalanceChecks::finalize(STTx const&, TER const, XRPAmount const, beast::Journal const& j)
|
||||
{
|
||||
if (bad_)
|
||||
{
|
||||
@@ -157,7 +226,7 @@ NoBadOffers::visitEntry(
|
||||
}
|
||||
|
||||
bool
|
||||
NoBadOffers::finalize(STTx const& tx, TER, beast::Journal const& j)
|
||||
NoBadOffers::finalize(STTx const& tx, TER const, XRPAmount const, beast::Journal const& j)
|
||||
{
|
||||
if (bad_)
|
||||
{
|
||||
@@ -199,7 +268,7 @@ NoZeroEscrow::visitEntry(
|
||||
}
|
||||
|
||||
bool
|
||||
NoZeroEscrow::finalize(STTx const& tx, TER, beast::Journal const& j)
|
||||
NoZeroEscrow::finalize(STTx const& tx, TER const, XRPAmount const, beast::Journal const& j)
|
||||
{
|
||||
if (bad_)
|
||||
{
|
||||
@@ -224,7 +293,7 @@ AccountRootsNotDeleted::visitEntry(
|
||||
}
|
||||
|
||||
bool
|
||||
AccountRootsNotDeleted::finalize(STTx const&, TER, beast::Journal const& j)
|
||||
AccountRootsNotDeleted::finalize(STTx const&, TER const, XRPAmount const, beast::Journal const& j)
|
||||
{
|
||||
if (! accountDeleted_)
|
||||
return true;
|
||||
@@ -270,7 +339,7 @@ LedgerEntryTypesMatch::visitEntry(
|
||||
}
|
||||
|
||||
bool
|
||||
LedgerEntryTypesMatch::finalize(STTx const&, TER, beast::Journal const& j)
|
||||
LedgerEntryTypesMatch::finalize(STTx const&, TER const, XRPAmount const, beast::Journal const& j)
|
||||
{
|
||||
if ((! typeMismatch_) && (! invalidTypeAdded_))
|
||||
return true;
|
||||
@@ -309,7 +378,7 @@ NoXRPTrustLines::visitEntry(
|
||||
}
|
||||
|
||||
bool
|
||||
NoXRPTrustLines::finalize(STTx const&, TER, beast::Journal const& j)
|
||||
NoXRPTrustLines::finalize(STTx const&, TER const, XRPAmount const, beast::Journal const& j)
|
||||
{
|
||||
if (! xrpTrustLine_)
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user