Skip to content

Commit

Permalink
Address rare corruption of NFTokenPage linked list (XRPLF#4945)
Browse files Browse the repository at this point in the history
* Add fixNFTokenPageLinks amendment:

It was discovered that under rare circumstances the links between
NFTokenPages could be removed.  If this happens, then the
account_objects and account_nfts RPC commands under-report the
NFTokens owned by an account.

The fixNFTokenPageLinks amendment does the following to address
the problem:

- It fixes the underlying problem so no further broken links
  should be created.
- It adds Invariants so, if such damage were introduced in the
  future, an invariant would stop it.
- It adds a new FixLedgerState transaction that repairs
  directories that were damaged in this fashion.
- It adds unit tests for all of it.
  • Loading branch information
scottschurr authored and vlntb committed Aug 23, 2024
1 parent 911e545 commit 375f500
Show file tree
Hide file tree
Showing 22 changed files with 2,054 additions and 131 deletions.
3 changes: 2 additions & 1 deletion include/xrpl/protocol/Feature.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ namespace detail {
// Feature.cpp. Because it's only used to reserve storage, and determine how
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
// the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures = 78;
static constexpr std::size_t numFeatures = 79;

/** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated
Expand Down Expand Up @@ -371,6 +371,7 @@ extern uint256 const fixReducedOffersV2;
extern uint256 const fixEnforceNFTokenTrustline;
extern uint256 const fixInnerObjTemplate2;
extern uint256 const featureInvariantsV1_1;
extern uint256 const fixNFTokenPageLinks;

} // namespace ripple

Expand Down
1 change: 1 addition & 0 deletions include/xrpl/protocol/SField.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ extern SF_UINT16 const sfHookEmitCount;
extern SF_UINT16 const sfHookExecutionIndex;
extern SF_UINT16 const sfHookApiVersion;
extern SF_UINT16 const sfDiscountedFee;
extern SF_UINT16 const sfLedgerFixType;

// 32-bit integers (common)
extern SF_UINT32 const sfNetworkID;
Expand Down
1 change: 1 addition & 0 deletions include/xrpl/protocol/TER.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ enum TEFcodes : TERUnderlyingType {
tefTOO_BIG,
tefNO_TICKET,
tefNFTOKEN_IS_NOT_TRANSFERABLE,
tefINVALID_LEDGER_FIX_TYPE,
};

//------------------------------------------------------------------------------
Expand Down
5 changes: 4 additions & 1 deletion include/xrpl/protocol/TxFormats.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,16 @@ enum TxType : std::uint16_t
/** This transaction type deletes a DID */
ttDID_DELETE = 50,


/** This transaction type creates an Oracle instance */
ttORACLE_SET = 51,

/** This transaction type deletes an Oracle instance */
ttORACLE_DELETE = 52,

/** This transaction type fixes a problem in the ledger state */
ttLEDGER_STATE_FIX = 53,


/** This system-generated transaction type is used to update the status of the various amendments.
For details, see: https://xrpl.org/amendments.html
Expand Down
1 change: 1 addition & 0 deletions include/xrpl/protocol/jss.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ JSS(NFTokenAcceptOffer); // transaction type.
JSS(NFTokenCancelOffer); // transaction type.
JSS(NFTokenCreateOffer); // transaction type.
JSS(NFTokenPage); // ledger type.
JSS(LedgerStateFix); // transaction type.
JSS(LPTokenOut); // in: AMM Liquidity Provider deposit tokens
JSS(LPTokenIn); // in: AMM Liquidity Provider withdraw tokens
JSS(LPToken); // out: AMM Liquidity Provider tokens info
Expand Down
1 change: 1 addition & 0 deletions src/libxrpl/protocol/Feature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ REGISTER_FEATURE(NFTokenMintOffer, Supported::yes, VoteBehavior::De
REGISTER_FIX (fixReducedOffersV2, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixEnforceNFTokenTrustline, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixInnerObjTemplate2, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixNFTokenPageLinks, Supported::yes, VoteBehavior::DefaultNo);
// InvariantsV1_1 will be changes to Supported::yes when all the
// invariants expected to be included under it are complete.
REGISTER_FEATURE(InvariantsV1_1, Supported::no, VoteBehavior::DefaultNo);
Expand Down
1 change: 1 addition & 0 deletions src/libxrpl/protocol/SField.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ CONSTRUCT_TYPED_SFIELD(sfHookStateChangeCount, "HookStateChangeCount", UINT16,
CONSTRUCT_TYPED_SFIELD(sfHookEmitCount, "HookEmitCount", UINT16, 18);
CONSTRUCT_TYPED_SFIELD(sfHookExecutionIndex, "HookExecutionIndex", UINT16, 19);
CONSTRUCT_TYPED_SFIELD(sfHookApiVersion, "HookApiVersion", UINT16, 20);
CONSTRUCT_TYPED_SFIELD(sfLedgerFixType, "LedgerFixType", UINT16, 21);

// 32-bit integers (common)
CONSTRUCT_TYPED_SFIELD(sfNetworkID, "NetworkID", UINT32, 1);
Expand Down
1 change: 1 addition & 0 deletions src/libxrpl/protocol/TER.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ transResults()
MAKE_ERROR(tefTOO_BIG, "Transaction affects too many items."),
MAKE_ERROR(tefNO_TICKET, "Ticket is not in ledger."),
MAKE_ERROR(tefNFTOKEN_IS_NOT_TRANSFERABLE, "The specified NFToken is not transferable."),
MAKE_ERROR(tefINVALID_LEDGER_FIX_TYPE, "The LedgerFixType field has an invalid value."),

MAKE_ERROR(telLOCAL_ERROR, "Local failure."),
MAKE_ERROR(telBAD_DOMAIN, "Domain too long."),
Expand Down
8 changes: 8 additions & 0 deletions src/libxrpl/protocol/TxFormats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,14 @@ TxFormats::TxFormats()
{sfOracleDocumentID, soeREQUIRED},
},
commonFields);

add(jss::LedgerStateFix,
ttLEDGER_STATE_FIX,
{
{sfLedgerFixType, soeREQUIRED},
{sfOwner, soeOPTIONAL},
},
commonFields);
}

TxFormats const&
Expand Down
Loading

0 comments on commit 375f500

Please sign in to comment.