forked from XRPLF/rippled
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement transaction invariant checks (RIPD-1425):
Add new functionality to enforce one or more sanity checks (invariants) on transactions. Add tests for each new invariant check. Allow for easily adding additional invariant checks in the future. Also Resolves ------------- - RIPD-1426 - RIPD-1427 - RIPD-1428 - RIPD-1429 - RIPD-1430 - RIPD-1431 - RIPD-1432 Release Notes ------------- Creates a new ammendment named "EnforceInvariants" which must be enabled in order for these new checks to run on each transaction.
- Loading branch information
1 parent
e52614a
commit 026a249
Showing
20 changed files
with
789 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
//------------------------------------------------------------------------------ | ||
/* | ||
This file is part of rippled: https://github.com/ripple/rippled | ||
Copyright (c) 2012-2016 Ripple Labs Inc. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted, provided that the above | ||
copyright notice and this permission notice appear in all copies. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
*/ | ||
//============================================================================== | ||
|
||
#include <ripple/app/tx/impl/InvariantCheck.h> | ||
#include <ripple/basics/Log.h> | ||
|
||
namespace ripple { | ||
|
||
void | ||
XRPNotCreated::visitEntry( | ||
uint256 const&, | ||
bool isDelete, | ||
std::shared_ptr <SLE const> const& before, | ||
std::shared_ptr <SLE const> const& after) | ||
{ | ||
if(before) | ||
{ | ||
switch (before->getType()) | ||
{ | ||
case ltACCOUNT_ROOT: | ||
drops_ -= (*before)[sfBalance].xrp().drops(); | ||
break; | ||
case ltPAYCHAN: | ||
drops_ -= ((*before)[sfAmount] - (*before)[sfBalance]).xrp().drops(); | ||
break; | ||
case ltESCROW: | ||
drops_ -= (*before)[sfAmount].xrp().drops(); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
if(after) | ||
{ | ||
switch (after->getType()) | ||
{ | ||
case ltACCOUNT_ROOT: | ||
drops_ += (*after)[sfBalance].xrp().drops(); | ||
break; | ||
case ltPAYCHAN: | ||
if (! isDelete) | ||
drops_ += ((*after)[sfAmount] - (*after)[sfBalance]).xrp().drops(); | ||
break; | ||
case ltESCROW: | ||
if (! isDelete) | ||
drops_ += (*after)[sfAmount].xrp().drops(); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
} | ||
|
||
bool | ||
XRPNotCreated::finalize(STTx const& tx, TER /*tec*/, beast::Journal const& j) | ||
{ | ||
auto fee = tx.getFieldAmount(sfFee).xrp().drops(); | ||
if(-1*fee <= drops_ && drops_ <= 0) | ||
return true; | ||
|
||
JLOG(j.fatal()) << "Invariant failed: XRP net change was " << drops_ << | ||
" on a fee of " << fee; | ||
return false; | ||
} | ||
|
||
//------------------------------------------------------------------------------ | ||
|
||
void | ||
AccountRootsNotDeleted::visitEntry( | ||
uint256 const&, | ||
bool isDelete, | ||
std::shared_ptr <SLE const> const& before, | ||
std::shared_ptr <SLE const> const&) | ||
{ | ||
if (isDelete && before && before->getType() == ltACCOUNT_ROOT) | ||
accountDeleted_ = true; | ||
} | ||
|
||
bool | ||
AccountRootsNotDeleted::finalize(STTx const&, TER, beast::Journal const& j) | ||
{ | ||
if (! accountDeleted_) | ||
return true; | ||
|
||
JLOG(j.fatal()) << "Invariant failed: an account root was deleted"; | ||
return false; | ||
} | ||
|
||
//------------------------------------------------------------------------------ | ||
|
||
void | ||
LedgerEntryTypesMatch::visitEntry( | ||
uint256 const&, | ||
bool, | ||
std::shared_ptr <SLE const> const& before, | ||
std::shared_ptr <SLE const> const& after) | ||
{ | ||
if (before && after && before->getType() != after->getType()) | ||
typeMismatch_ = true; | ||
|
||
if (after) | ||
{ | ||
switch (after->getType()) | ||
{ | ||
case ltACCOUNT_ROOT: | ||
case ltDIR_NODE: | ||
case ltRIPPLE_STATE: | ||
case ltTICKET: | ||
case ltSIGNER_LIST: | ||
case ltOFFER: | ||
case ltLEDGER_HASHES: | ||
case ltAMENDMENTS: | ||
case ltFEE_SETTINGS: | ||
case ltESCROW: | ||
case ltPAYCHAN: | ||
break; | ||
default: | ||
invalidTypeAdded_ = true; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
bool | ||
LedgerEntryTypesMatch::finalize(STTx const&, TER, beast::Journal const& j) | ||
{ | ||
if ((! typeMismatch_) && (! invalidTypeAdded_)) | ||
return true; | ||
|
||
if (typeMismatch_) | ||
{ | ||
JLOG(j.fatal()) << "Invariant failed: ledger entry type mismatch"; | ||
} | ||
|
||
if (invalidTypeAdded_) | ||
{ | ||
JLOG(j.fatal()) << "Invariant failed: invalid ledger entry type added"; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
//------------------------------------------------------------------------------ | ||
|
||
void | ||
NoXRPTrustLines::visitEntry( | ||
uint256 const&, | ||
bool, | ||
std::shared_ptr <SLE const> const&, | ||
std::shared_ptr <SLE const> const& after) | ||
{ | ||
if (after && after->getType() == ltRIPPLE_STATE) | ||
{ | ||
// checking the issue directly here instead of | ||
// relying on .native() just in case native somehow | ||
// were systematically incorrect | ||
xrpTrustLine_ = | ||
after->getFieldAmount (sfLowLimit).issue() == xrpIssue() || | ||
after->getFieldAmount (sfHighLimit).issue() == xrpIssue(); | ||
} | ||
} | ||
|
||
bool | ||
NoXRPTrustLines::finalize(STTx const&, TER, beast::Journal const& j) | ||
{ | ||
if (! xrpTrustLine_) | ||
return true; | ||
|
||
JLOG(j.fatal()) << "Invariant failed: an XRP trust line was created"; | ||
return false; | ||
} | ||
|
||
} // ripple | ||
|
Oops, something went wrong.