From a4c11161b571170c5a9eda4a2be0e33fd1b08cb6 Mon Sep 17 00:00:00 2001 From: rmurphy23 Date: Fri, 31 Jul 2020 15:20:26 -0700 Subject: [PATCH 1/6] Adds invariant checking concept to dactyl-config.yml; Adds invariant-checking.md --- .../consensus-network/invariant-checking.md | 404 ++++++++++++++++++ dactyl-config.yml | 9 + 2 files changed, 413 insertions(+) create mode 100644 content/concepts/consensus-network/invariant-checking.md diff --git a/content/concepts/consensus-network/invariant-checking.md b/content/concepts/consensus-network/invariant-checking.md new file mode 100644 index 0000000000..0dcf9b7b7f --- /dev/null +++ b/content/concepts/consensus-network/invariant-checking.md @@ -0,0 +1,404 @@ +# Invariant Checking + +This article provides a high-level overview of Invariant Checking, why it exist, how it works, and lists active invariant checks. + +When building applications on the XRP Ledger, it is crucial to understand the idea of Invariant Checks so as not to be surprised by specific error codes. + +## Introduction + +Invariant checking is a protection enhancement to the XRP Ledger and reinforces the critical properties of the XRP Ledger. + +Invariant checks should not trigger, but they ensure the XRP Ledger's integrity from bugs yet to be discovered or even created. + + +## Why it Exists + +Nevertheless, why do we need invariant checks? + +- The overarching code for the XRP Ledger is complicated and vast; therefore, there is a high potential for code to execute incorrectly. +- The cost of incorrectly executing a transaction is high and not acceptable by any standards. + + +## How it Works + +A second layer of code runs automatically and in real-time after each transaction completes. It then examines the changes it made for correctness before the results are committed to the ledger. After every transaction runs, the invariant checker runs. Problematic transactions are marked with a **tecINVARIANT_FAILED** result code and are included in the ledger as having done nothing. + +The invariant checker is then invariantly checked to ensure the invariant checker's failure is not due to a bug. If this second level check fails, transactions are marked with a **tefINVARIANT_FAILED** result code. The transaction is in its final state and is not included in the ledger. + + +## Active Invariant Checks + +Following is a list of active checks that the invariant checker runs against each transaction on the XRP Ledger. + +- [Transaction Fee Check](#transaction-fee-check) +- [XRP Not Created](#xrp-not-created) +- [Account Roots Not Deleted](#account-roots-not-deleted) +- [XRP Balance Checks](#xrp-balance-checks) +- [Ledger Entry Types Match](#ledger-entry-types-match) +- [No XRP Trust Lines](#no-xrp-trust-lines) +- [No Bad Offers](#no-bad-offers) +- [No Zero Escrow](#no-zero-escrow) +- [Valid New Account Root](#valid-new-account-root) + + +### Transaction Fee Check + +- **Condition(s) Checked:** + + - [Trnsaction fees](https://xrpl.org/rippleapi-reference.html#transaction-fees) should never be negative nor larger than the transaction itself. + +``` +class TransactionFeeCheck +{ +public: + void + visitEntry( + bool, + std::shared_ptr const&, + std::shared_ptr const&); + + bool + finalize( + STTx const&, + TER const, + XRPAmount const, + ReadView const&, + beast::Journal const&); +}; +``` + +### XRP Not Created + +- **Condition(s) Checked:** + + - A transaction must not create XRP and should only destroy the XRP [fee](https://xrpl.org/rippleapi-reference.html#transaction-fees)). + +``` +class XRPNotCreated +{ + std::int64_t drops_ = 0; + +public: + void + visitEntry( + bool, + std::shared_ptr const&, + std::shared_ptr const&); + + bool + finalize( + STTx const&, + TER const, + XRPAmount const, + ReadView const&, + beast::Journal const&); +}; +``` + +### Account Roots Not Deleted + +- **Condition(s) Checked:** + + - An account ledger entry cannot be removed. + +``` +class AccountRootsNotDeleted +{ + std::uint32_t accountsDeleted_ = 0; + +public: + void + visitEntry( + bool, + std::shared_ptr const&, + std::shared_ptr const&); + + bool + finalize( + STTx const&, + TER const, + XRPAmount const, + ReadView const&, + beast::Journal const&); +}; +``` + +### XRP Balance Checks + +- **Condition(s) Checked:** + + - An account's XRP balance must be of type XRP and take a value between 0 and INITIAL_XRP drops, inclusive. + +``` +/** Number of drops per 1 XRP */ +constexpr XRPAmount DROPS_PER_XRP{1'000'000}; + +/** Number of drops in the genesis account. */ +constexpr XRPAmount INITIAL_XRP{100'000'000'000 * DROPS_PER_XRP}; +``` + +``` +class XRPBalanceChecks +{ + bool bad_ = false; + +public: + void + visitEntry( + bool, + std::shared_ptr const&, + std::shared_ptr const&); + + bool + finalize( + STTx const&, + TER const, + XRPAmount const, + ReadView const&, + beast::Journal const&); +}; +``` + +### Ledger Entry Types Match + +- **Condition(s) Chceked:** + + - Corresponding modified ledger entries should match in type and added entries should be a [valid type](https://xrpl.org/transaction-types.html#transaction-types). + + + +*LedgerEntryTypesMatch* + +``` +class LedgerEntryTypesMatch +{ + bool typeMismatch_ = false; + bool invalidTypeAdded_ = false; + +public: + void + visitEntry( + bool, + std::shared_ptr const&, + std::shared_ptr const&); + + bool + finalize( + STTx const&, + TER const, + XRPAmount const, + ReadView const&, + beast::Journal const&); +}; +``` + +*LedgerEntryType* + +``` +// Used as the type of a transaction or the type of a ledger entry. +enum LedgerEntryType { + /** Special type, anything + This is used when the type in the Keylet is unknown, + such as when building metadata. + */ + ltANY = -3, + + /** Special type, anything not a directory + This is used when the type in the Keylet is unknown, + such as when iterating + */ + ltCHILD = -2, + + ltINVALID = -1, + + //--------------------------------------------------------------------------- + + ltACCOUNT_ROOT = 'a', + + /** Directory node. + A directory is a vector 256-bit values. Usually they represent + hashes of other objects in the ledger. + Used in an append-only fashion. + (There's a little more information than this, see the template) + */ + ltDIR_NODE = 'd', + + ltRIPPLE_STATE = 'r', + + ltTICKET = 'T', + + ltSIGNER_LIST = 'S', + + ltOFFER = 'o', + + ltLEDGER_HASHES = 'h', + + ltAMENDMENTS = 'f', + + ltFEE_SETTINGS = 's', + + ltESCROW = 'u', + + // Simple unidirection xrp channel + ltPAYCHAN = 'x', + + ltCHECK = 'C', + + ltDEPOSIT_PREAUTH = 'p', + + // No longer used or supported. Left here to prevent accidental + // reassignment of the ledger type. + ltNICKNAME = 'n', + + ltNotUsed01 = 'c', +}; +``` + + +### No XRP Trust Lines + +- **Condition(s) Checked:** + + - [Trust lines](https://xrpl.org/trust-lines-and-issuing.html#trust-lines-and-issuing) using XRP are not allowed. + +``` +class NoXRPTrustLines +{ + bool xrpTrustLine_ = false; + +public: + void + visitEntry( + bool, + std::shared_ptr const&, + std::shared_ptr const&); + + bool + finalize( + STTx const&, + TER const, + XRPAmount const, + ReadView const&, + beast::Journal const&); +}; +``` + +### No Bad Offers + +- **Condition(s) Checked:** + + - [Offers](https://xrpl.org/offer.html#offer) should be for non-negative amounts and must not be XRP to XRP. + +``` +class NoBadOffers +{ + bool bad_ = false; + +public: + void + visitEntry( + bool, + std::shared_ptr const&, + std::shared_ptr const&); + + bool + finalize( + STTx const&, + TER const, + XRPAmount const, + ReadView const&, + beast::Journal const&); +}; +``` + +### No Zero Escrow + +- **Condition(s) Checked:** + + - An [escrow](https://xrpl.org/escrow-object.html) entry must take a value between 0 and INITIAL_XRP drops exclusive. + +``` +/** Number of drops per 1 XRP */ +constexpr XRPAmount DROPS_PER_XRP{1'000'000}; + +/** Number of drops in the genesis account. */ +constexpr XRPAmount INITIAL_XRP{100'000'000'000 * DROPS_PER_XRP}; +``` + +``` +class NoZeroEscrow +{ + bool bad_ = false; + +public: + void + visitEntry( + bool, + std::shared_ptr const&, + std::shared_ptr const&); + + bool + finalize( + STTx const&, + TER const, + XRPAmount const, + ReadView const&, + beast::Journal const&); +}; +``` + +### Valid New Account Root + +- **Condition(s) Checked:** + + - A new [account root](https://xrpl.org/accountroot.html?_ga=2.259492554.1588022287.1596050513-879263697.1594345179) must be the consequence of a payment. + - A new account root must have the right starting [sequence](https://xrpl.org/basic-data-types.html#account-sequence). + - A new [account](https://xrpl.org/accounts.html) may not create more than one new account root. + +``` +class ValidNewAccountRoot +{ + std::uint32_t accountsCreated_ = 0; + std::uint32_t accountSeq_ = 0; // Only meaningful if accountsCreated_ > 0 + +public: + void + visitEntry( + bool, + std::shared_ptr const&, + std::shared_ptr const&); + + bool + finalize( + STTx const&, + TER const, + XRPAmount const, + ReadView const&, + beast::Journal const&); +}; +``` + + +## See Also + +- **Blog:** + - [Protecting the Ledger: Invariant Checking](https://xrpl.org/blog/2017/invariant-checking.html) + +- **Repository:** + - [Invariant Check.h](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h) + - [Invariant Check.cpp](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.cpp) + - [System Parameters](https://github.com/ripple/rippled/blob/develop/src/ripple/protocol/SystemParameters.h#L43) + - [XRP Amount](https://github.com/ripple/rippled/blob/develop/src/ripple/basics/XRPAmount.h#L244) + - [Ledger Formats](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/protocol/LedgerFormats.h#L36-L94) + +- **Other:** + - [Authorized Trust Lines](https://xrpl.org/authorized-trust-lines.html#authorized-trust-lines) + - [XRP Properties](https://xrpl.org/xrp.html#xrp-properties) + - [Calculating Balance Changes for a Transaction](https://xrpl.org/blog/2015/calculating-balance-changes-for-a-transaction.html#calculating-balance-changes-for-a-transaction) + + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/dactyl-config.yml b/dactyl-config.yml index 69c62815d3..3c12110e58 100644 --- a/dactyl-config.yml +++ b/dactyl-config.yml @@ -999,6 +999,15 @@ pages: targets: - ja + - md: concepts/consensus-network/invariant-checking.md + html: invariant-checking-concept.html + funnel: Docs + doc_type: Concepts + category: Consensus Network + blurb: Understand what Invariant Checking is, why it exists, how it works, and what invariant checks are active. + targets: + - en + - md: concepts/consensus-network/transaction-queue.md html: transaction-queue.html funnel: Docs From 077ae327688ec7edf94155e9df3ce9e5fd642e26 Mon Sep 17 00:00:00 2001 From: rmurphy23 Date: Thu, 6 Aug 2020 17:19:45 -0700 Subject: [PATCH 2/6] Adds MR feedback, suggestions, and more to invariant-checking.md --- .../consensus-network/invariant-checking.md | 394 ++++-------------- 1 file changed, 71 insertions(+), 323 deletions(-) diff --git a/content/concepts/consensus-network/invariant-checking.md b/content/concepts/consensus-network/invariant-checking.md index 0dcf9b7b7f..faab1c9852 100644 --- a/content/concepts/consensus-network/invariant-checking.md +++ b/content/concepts/consensus-network/invariant-checking.md @@ -1,382 +1,129 @@ # Invariant Checking -This article provides a high-level overview of Invariant Checking, why it exist, how it works, and lists active invariant checks. +This article provides a high-level overview of invariant checking, why it exist, how it works, and lists active invariants. -When building applications on the XRP Ledger, it is crucial to understand the idea of Invariant Checks so as not to be surprised by specific error codes. +Like many safety features, we all hope that invariant checking never actually needs to do anything. However, it can be useful to understand the XRP Ledger's invariants because they define hard limits on the XRP Ledger's transaction processing, and to recognize the problem in the unlikely event that a transaction fails because it violated an invariant check. ## Introduction -Invariant checking is a protection enhancement to the XRP Ledger and reinforces the critical properties of the XRP Ledger. +Invariant checking is a safety feature of the XRP Ledger. It consists of a set of checks, separate from normal transaction processing, that guarantee that certain _invariants_ hold true across all transactions. -Invariant checks should not trigger, but they ensure the XRP Ledger's integrity from bugs yet to be discovered or even created. +Invariants should not trigger, but they ensure the XRP Ledger's integrity from bugs yet to be discovered or even created. + +| Term | Description | +|-----------|-------------| +| Invariant | A rule that should always, without exception, be true. For example, "New XRP cannot be created". | +| Invariant Checking | In the XRP Ledger, a system where code automatically confirms that transaction processing does not break the invariants. If a transaction's execution would break an invariant, the invariant checking system fails the transaction. | ## Why it Exists -Nevertheless, why do we need invariant checks? - - The overarching code for the XRP Ledger is complicated and vast; therefore, there is a high potential for code to execute incorrectly. - The cost of incorrectly executing a transaction is high and not acceptable by any standards. ## How it Works -A second layer of code runs automatically and in real-time after each transaction completes. It then examines the changes it made for correctness before the results are committed to the ledger. After every transaction runs, the invariant checker runs. Problematic transactions are marked with a **tecINVARIANT_FAILED** result code and are included in the ledger as having done nothing. +The invariant checker is a second layer of code that runs automatically in real-time after each transaction. Before the transaction's results are committed to the ledger, the invariant checker examines those changes for correctness. If the transaction's results would break one of the XRP Ledger's strict rules, the invariant checker rejects the transaction. Transactions that are rejected this way have the result code `tecINVARIANT_FAILED` and are included in the ledger with no effects. -The invariant checker is then invariantly checked to ensure the invariant checker's failure is not due to a bug. If this second level check fails, transactions are marked with a **tefINVARIANT_FAILED** result code. The transaction is in its final state and is not included in the ledger. +To include the transaction in the ledger with a `tec`-class code, some minimal processing is necessary. If this minimal processing still breaks an invariant, the transaction fails with the code `tefINVARIANT_FAILED` instead, and is not included in the ledger at all. -## Active Invariant Checks +## Active Invariants -Following is a list of active checks that the invariant checker runs against each transaction on the XRP Ledger. +The XRP Ledger checks all the following invariants on each transaction: + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L92 "Source") - [Transaction Fee Check](#transaction-fee-check) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L118 "Source") + - [XRP Not Created](#xrp-not-created) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L146 "Source") + - [Account Roots Not Deleted](#account-roots-not-deleted) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L173 "Source") + - [XRP Balance Checks](#xrp-balance-checks) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L197 "Source") + - [Ledger Entry Types Match](#ledger-entry-types-match) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L224 "Source") + - [No XRP Trust Lines](#no-xrp-trust-lines) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L251 "Source") + - [No Bad Offers](#no-bad-offers) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L275 "Source") + - [No Zero Escrow](#no-zero-escrow) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L300 "Source") + - [Valid New Account Root](#valid-new-account-root) -### Transaction Fee Check +### [Transaction Fee Check](#active-invariants) -- **Condition(s) Checked:** +- **Invariant Condition(s):** + - [Transaction fees](rippleapi-reference.html#transaction-fees) should never be negative nor larger than the transaction itself. - - [Trnsaction fees](https://xrpl.org/rippleapi-reference.html#transaction-fees) should never be negative nor larger than the transaction itself. -``` -class TransactionFeeCheck -{ -public: - void - visitEntry( - bool, - std::shared_ptr const&, - std::shared_ptr const&); +### [XRP Not Created](#active-invariants) - bool - finalize( - STTx const&, - TER const, - XRPAmount const, - ReadView const&, - beast::Journal const&); -}; -``` +- **Invariant Condition(s):** + - A transaction must not create XRP and should only destroy the XRP [transaction cost](transaction-cost.html). -### XRP Not Created -- **Condition(s) Checked:** - - - A transaction must not create XRP and should only destroy the XRP [fee](https://xrpl.org/rippleapi-reference.html#transaction-fees)). +### [Account Roots Not Deleted](#active-invariants) -``` -class XRPNotCreated -{ - std::int64_t drops_ = 0; +- **Invariant Condition(s):** + - An account ledger entry can be removed by an AccountDelete transaction, but this invariant checks that exactly 1 is deleted by a successful AccountDelete. -public: - void - visitEntry( - bool, - std::shared_ptr const&, - std::shared_ptr const&); - bool - finalize( - STTx const&, - TER const, - XRPAmount const, - ReadView const&, - beast::Journal const&); -}; -``` +### [XRP Balance Checks](#active-invariants) -### Account Roots Not Deleted +- **Invariant Condition(s):** + - An account's XRP balance must be of type XRP, and it cannot be less than 0 or more than 100 billion XRP exactly. -- **Condition(s) Checked:** - - - An account ledger entry cannot be removed. -``` -class AccountRootsNotDeleted -{ - std::uint32_t accountsDeleted_ = 0; +### [Ledger Entry Types Match](#active-invariants) -public: - void - visitEntry( - bool, - std::shared_ptr const&, - std::shared_ptr const&); +- **Invariant Condition(s):** + - Corresponding modified ledger entries should match in type and added entries should be a [valid type](ledger-object-types.html). - bool - finalize( - STTx const&, - TER const, - XRPAmount const, - ReadView const&, - beast::Journal const&); -}; -``` -### XRP Balance Checks +### [No XRP Trust Lines](#active-invariants) -- **Condition(s) Checked:** - - - An account's XRP balance must be of type XRP and take a value between 0 and INITIAL_XRP drops, inclusive. +- **Invariant Condition(s):** + - [Trust lines](trust-lines-and-issuing.html#trust-lines-and-issuing) using XRP are not allowed. -``` -/** Number of drops per 1 XRP */ -constexpr XRPAmount DROPS_PER_XRP{1'000'000}; -/** Number of drops in the genesis account. */ -constexpr XRPAmount INITIAL_XRP{100'000'000'000 * DROPS_PER_XRP}; -``` +### [No Bad Offers](#active-invariants) -``` -class XRPBalanceChecks -{ - bool bad_ = false; +- **Invariant Condition(s):** + - [Offers](offer.html#offer) should be for non-negative amounts and must not be XRP to XRP. -public: - void - visitEntry( - bool, - std::shared_ptr const&, - std::shared_ptr const&); - bool - finalize( - STTx const&, - TER const, - XRPAmount const, - ReadView const&, - beast::Journal const&); -}; -``` +### [No Zero Escrow](#active-invariants) -### Ledger Entry Types Match +- **Invariant Condition(s):** + - An [escrow](escrow-object.html) entry must hold a quantity of XRP between 0 and 99.99 billion. -- **Condition(s) Chceked:** - - - Corresponding modified ledger entries should match in type and added entries should be a [valid type](https://xrpl.org/transaction-types.html#transaction-types). - +### [Valid New Account Root](#active-invariants) -*LedgerEntryTypesMatch* - -``` -class LedgerEntryTypesMatch -{ - bool typeMismatch_ = false; - bool invalidTypeAdded_ = false; - -public: - void - visitEntry( - bool, - std::shared_ptr const&, - std::shared_ptr const&); - - bool - finalize( - STTx const&, - TER const, - XRPAmount const, - ReadView const&, - beast::Journal const&); -}; -``` - -*LedgerEntryType* - -``` -// Used as the type of a transaction or the type of a ledger entry. -enum LedgerEntryType { - /** Special type, anything - This is used when the type in the Keylet is unknown, - such as when building metadata. - */ - ltANY = -3, - - /** Special type, anything not a directory - This is used when the type in the Keylet is unknown, - such as when iterating - */ - ltCHILD = -2, - - ltINVALID = -1, - - //--------------------------------------------------------------------------- - - ltACCOUNT_ROOT = 'a', - - /** Directory node. - A directory is a vector 256-bit values. Usually they represent - hashes of other objects in the ledger. - Used in an append-only fashion. - (There's a little more information than this, see the template) - */ - ltDIR_NODE = 'd', - - ltRIPPLE_STATE = 'r', - - ltTICKET = 'T', - - ltSIGNER_LIST = 'S', - - ltOFFER = 'o', - - ltLEDGER_HASHES = 'h', - - ltAMENDMENTS = 'f', - - ltFEE_SETTINGS = 's', - - ltESCROW = 'u', - - // Simple unidirection xrp channel - ltPAYCHAN = 'x', - - ltCHECK = 'C', - - ltDEPOSIT_PREAUTH = 'p', - - // No longer used or supported. Left here to prevent accidental - // reassignment of the ledger type. - ltNICKNAME = 'n', - - ltNotUsed01 = 'c', -}; -``` - - -### No XRP Trust Lines - -- **Condition(s) Checked:** - - - [Trust lines](https://xrpl.org/trust-lines-and-issuing.html#trust-lines-and-issuing) using XRP are not allowed. - -``` -class NoXRPTrustLines -{ - bool xrpTrustLine_ = false; - -public: - void - visitEntry( - bool, - std::shared_ptr const&, - std::shared_ptr const&); - - bool - finalize( - STTx const&, - TER const, - XRPAmount const, - ReadView const&, - beast::Journal const&); -}; -``` - -### No Bad Offers - -- **Condition(s) Checked:** - - - [Offers](https://xrpl.org/offer.html#offer) should be for non-negative amounts and must not be XRP to XRP. - -``` -class NoBadOffers -{ - bool bad_ = false; - -public: - void - visitEntry( - bool, - std::shared_ptr const&, - std::shared_ptr const&); - - bool - finalize( - STTx const&, - TER const, - XRPAmount const, - ReadView const&, - beast::Journal const&); -}; -``` - -### No Zero Escrow - -- **Condition(s) Checked:** - - - An [escrow](https://xrpl.org/escrow-object.html) entry must take a value between 0 and INITIAL_XRP drops exclusive. - -``` -/** Number of drops per 1 XRP */ -constexpr XRPAmount DROPS_PER_XRP{1'000'000}; - -/** Number of drops in the genesis account. */ -constexpr XRPAmount INITIAL_XRP{100'000'000'000 * DROPS_PER_XRP}; -``` - -``` -class NoZeroEscrow -{ - bool bad_ = false; - -public: - void - visitEntry( - bool, - std::shared_ptr const&, - std::shared_ptr const&); - - bool - finalize( - STTx const&, - TER const, - XRPAmount const, - ReadView const&, - beast::Journal const&); -}; -``` - -### Valid New Account Root - -- **Condition(s) Checked:** - - - A new [account root](https://xrpl.org/accountroot.html?_ga=2.259492554.1588022287.1596050513-879263697.1594345179) must be the consequence of a payment. - - A new account root must have the right starting [sequence](https://xrpl.org/basic-data-types.html#account-sequence). - - A new [account](https://xrpl.org/accounts.html) may not create more than one new account root. - -``` -class ValidNewAccountRoot -{ - std::uint32_t accountsCreated_ = 0; - std::uint32_t accountSeq_ = 0; // Only meaningful if accountsCreated_ > 0 - -public: - void - visitEntry( - bool, - std::shared_ptr const&, - std::shared_ptr const&); - - bool - finalize( - STTx const&, - TER const, - XRPAmount const, - ReadView const&, - beast::Journal const&); -}; -``` +- **Invariant Condition(s):** + - A new [account root](accountroot.html) must be the consequence of a payment. + - A new account root must have the right starting [sequence](basic-data-types.html#account-sequence). + - A new [account](accounts.html) may not create more than one new account root. ## See Also @@ -391,9 +138,10 @@ public: - [XRP Amount](https://github.com/ripple/rippled/blob/develop/src/ripple/basics/XRPAmount.h#L244) - [Ledger Formats](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/protocol/LedgerFormats.h#L36-L94) + - **Other:** - - [Authorized Trust Lines](https://xrpl.org/authorized-trust-lines.html#authorized-trust-lines) - - [XRP Properties](https://xrpl.org/xrp.html#xrp-properties) + - [Authorized Trust Lines](authorized-trust-lines.html) + - [XRP Properties](xrp.html#xrp-properties) - [Calculating Balance Changes for a Transaction](https://xrpl.org/blog/2015/calculating-balance-changes-for-a-transaction.html#calculating-balance-changes-for-a-transaction) From cf047c74c8b809dc9013e8488a099def7884ffb8 Mon Sep 17 00:00:00 2001 From: rmurphy23 Date: Wed, 12 Aug 2020 14:12:55 -0700 Subject: [PATCH 3/6] Adds second level feedback to invariant-checking.md --- .../consensus-network/invariant-checking.md | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/content/concepts/consensus-network/invariant-checking.md b/content/concepts/consensus-network/invariant-checking.md index faab1c9852..951c0dbec1 100644 --- a/content/concepts/consensus-network/invariant-checking.md +++ b/content/concepts/consensus-network/invariant-checking.md @@ -1,26 +1,22 @@ # Invariant Checking -This article provides a high-level overview of invariant checking, why it exist, how it works, and lists active invariants. - -Like many safety features, we all hope that invariant checking never actually needs to do anything. However, it can be useful to understand the XRP Ledger's invariants because they define hard limits on the XRP Ledger's transaction processing, and to recognize the problem in the unlikely event that a transaction fails because it violated an invariant check. - -## Introduction - Invariant checking is a safety feature of the XRP Ledger. It consists of a set of checks, separate from normal transaction processing, that guarantee that certain _invariants_ hold true across all transactions. -Invariants should not trigger, but they ensure the XRP Ledger's integrity from bugs yet to be discovered or even created. +Like many safety features, we all hope that invariant checking never actually needs to do anything. However, it can be useful to understand the XRP Ledger's invariants because they define hard limits on the XRP Ledger's transaction processing, and to recognize the problem in the unlikely event that a transaction fails because it violated an invariant check. -| Term | Description | -|-----------|-------------| -| Invariant | A rule that should always, without exception, be true. For example, "New XRP cannot be created". | -| Invariant Checking | In the XRP Ledger, a system where code automatically confirms that transaction processing does not break the invariants. If a transaction's execution would break an invariant, the invariant checking system fails the transaction. | +Invariants should not trigger, but they ensure the XRP Ledger's integrity from bugs yet to be discovered or even created. ## Why it Exists -- The overarching code for the XRP Ledger is complicated and vast; therefore, there is a high potential for code to execute incorrectly. +- The source code for the XRP Ledger is complicated and vast; there is a high potential for code to execute incorrectly. - The cost of incorrectly executing a transaction is high and not acceptable by any standards. +Specifically, incorrect transaction executions could create invalid or corrupt data that later consistently crashes servers in the network by sending them into an "impossible" state which could halt the entire network. + +The processing of incorrect transaction would undermine the value of trust in the XRP Ledger. Invariant checking provides value to the entire XRP Ledger because it adds the feature of reliability. + + ## How it Works @@ -70,60 +66,61 @@ The XRP Ledger checks all the following invariants on each transaction: - [Valid New Account Root](#valid-new-account-root) -### [Transaction Fee Check](#active-invariants) +### Transaction Fee Check - **Invariant Condition(s):** - - [Transaction fees](rippleapi-reference.html#transaction-fees) should never be negative nor larger than the transaction itself. + - The [transaction cost](transaction-cost.html) amount must never be negative, nor larger than the cost specified in the transaction. -### [XRP Not Created](#active-invariants) +### XRP Not Created - **Invariant Condition(s):** - A transaction must not create XRP and should only destroy the XRP [transaction cost](transaction-cost.html). -### [Account Roots Not Deleted](#active-invariants) +### Account Roots Not Deleted - **Invariant Condition(s):** - - An account ledger entry can be removed by an AccountDelete transaction, but this invariant checks that exactly 1 is deleted by a successful AccountDelete. + - An [account](accounts.html) cannot be deleted from the ledger except by an [AccountDelete transaction][]. + - A successful AccountDelete transaction always deletes exactly 1 account. -### [XRP Balance Checks](#active-invariants) +### XRP Balance Checks - **Invariant Condition(s):** - An account's XRP balance must be of type XRP, and it cannot be less than 0 or more than 100 billion XRP exactly. -### [Ledger Entry Types Match](#active-invariants) +### Ledger Entry Types Match - **Invariant Condition(s):** - Corresponding modified ledger entries should match in type and added entries should be a [valid type](ledger-object-types.html). -### [No XRP Trust Lines](#active-invariants) +### No XRP Trust Lines - **Invariant Condition(s):** - [Trust lines](trust-lines-and-issuing.html#trust-lines-and-issuing) using XRP are not allowed. -### [No Bad Offers](#active-invariants) +### No Bad Offers - **Invariant Condition(s):** - [Offers](offer.html#offer) should be for non-negative amounts and must not be XRP to XRP. -### [No Zero Escrow](#active-invariants) +### No Zero Escrow - **Invariant Condition(s):** - - An [escrow](escrow-object.html) entry must hold a quantity of XRP between 0 and 99.99 billion. + - An [escrow](escrow-object.html) entry must hold more than 0 XRP and less than 100 billion XRP. -### [Valid New Account Root](#active-invariants) +### Valid New Account Root - **Invariant Condition(s):** - A new [account root](accountroot.html) must be the consequence of a payment. - A new account root must have the right starting [sequence](basic-data-types.html#account-sequence). - - A new [account](accounts.html) may not create more than one new account root. + - A transaction must not create more than one new [account](accounts.html). ## See Also From 776d9dfb7573b2ad46caaba67230415fb9c07c21 Mon Sep 17 00:00:00 2001 From: Rome Reginelli Date: Fri, 21 Aug 2020 14:32:09 -0700 Subject: [PATCH 4/6] Add invariant checking page to ja target --- dactyl-config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dactyl-config.yml b/dactyl-config.yml index 3c12110e58..9c26e6cbe2 100644 --- a/dactyl-config.yml +++ b/dactyl-config.yml @@ -999,6 +999,7 @@ pages: targets: - ja + # TODO: translate this page and blurb - md: concepts/consensus-network/invariant-checking.md html: invariant-checking-concept.html funnel: Docs @@ -1007,6 +1008,7 @@ pages: blurb: Understand what Invariant Checking is, why it exists, how it works, and what invariant checks are active. targets: - en + - ja - md: concepts/consensus-network/transaction-queue.md html: transaction-queue.html From 7e59677318806dc229101d849ec98071c9c0f1a5 Mon Sep 17 00:00:00 2001 From: Rome Reginelli Date: Fri, 21 Aug 2020 15:10:57 -0700 Subject: [PATCH 5/6] [JA] Add redirects for untranslated invariant checking doc links --- dactyl-config.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dactyl-config.yml b/dactyl-config.yml index 9c26e6cbe2..a8d7e9e59c 100644 --- a/dactyl-config.yml +++ b/dactyl-config.yml @@ -129,6 +129,9 @@ targets: "transaction-metadata.html#affectednodes": "transaction-metadata.html" # Fix link from untranslated peer-crawler.html: "peer-protocol.html#private-peers": "peer-protocol.html#プライベートピア" + # Fix links from untranslated invariant-checking.html + "basic-data-types.html#account-sequence": "basic-data-types.html#アカウントシーケンス" + "xrp.html#xrp-properties": "xrp.html#xrpの特性" - name: xrp-api-only @@ -1001,7 +1004,7 @@ pages: # TODO: translate this page and blurb - md: concepts/consensus-network/invariant-checking.md - html: invariant-checking-concept.html + html: invariant-checking.html funnel: Docs doc_type: Concepts category: Consensus Network From 535a2273ce238fdb33529a4c0318ec5ccb722914 Mon Sep 17 00:00:00 2001 From: Rome Reginelli Date: Fri, 21 Aug 2020 15:20:01 -0700 Subject: [PATCH 6/6] Invariant Checking: Simplify trust lines link --- content/concepts/consensus-network/invariant-checking.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/concepts/consensus-network/invariant-checking.md b/content/concepts/consensus-network/invariant-checking.md index 951c0dbec1..2b30cd10e2 100644 --- a/content/concepts/consensus-network/invariant-checking.md +++ b/content/concepts/consensus-network/invariant-checking.md @@ -100,7 +100,7 @@ The XRP Ledger checks all the following invariants on each transaction: ### No XRP Trust Lines - **Invariant Condition(s):** - - [Trust lines](trust-lines-and-issuing.html#trust-lines-and-issuing) using XRP are not allowed. + - [Trust lines](trust-lines-and-issuing.html) using XRP are not allowed. ### No Bad Offers @@ -146,4 +146,4 @@ The XRP Ledger checks all the following invariants on each transaction: {% include '_snippets/rippled-api-links.md' %} {% include '_snippets/tx-type-links.md' %} -{% include '_snippets/rippled_versions.md' %} \ No newline at end of file +{% include '_snippets/rippled_versions.md' %}