Skip to content

Commit c19a88f

Browse files
authored
Address rare corruption of NFTokenPage linked list (XRPLF#4945)
* 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.
1 parent 0a331ea commit c19a88f

22 files changed

Lines changed: 2054 additions & 131 deletions

include/xrpl/protocol/Feature.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ namespace detail {
8080
// Feature.cpp. Because it's only used to reserve storage, and determine how
8181
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
8282
// the actual number of amendments. A LogicError on startup will verify this.
83-
static constexpr std::size_t numFeatures = 78;
83+
static constexpr std::size_t numFeatures = 79;
8484

8585
/** Amendments that this server supports and the default voting behavior.
8686
Whether they are enabled depends on the Rules defined in the validated
@@ -371,6 +371,7 @@ extern uint256 const fixReducedOffersV2;
371371
extern uint256 const fixEnforceNFTokenTrustline;
372372
extern uint256 const fixInnerObjTemplate2;
373373
extern uint256 const featureInvariantsV1_1;
374+
extern uint256 const fixNFTokenPageLinks;
374375

375376
} // namespace ripple
376377

include/xrpl/protocol/SField.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ extern SF_UINT16 const sfHookEmitCount;
388388
extern SF_UINT16 const sfHookExecutionIndex;
389389
extern SF_UINT16 const sfHookApiVersion;
390390
extern SF_UINT16 const sfDiscountedFee;
391+
extern SF_UINT16 const sfLedgerFixType;
391392

392393
// 32-bit integers (common)
393394
extern SF_UINT32 const sfNetworkID;

include/xrpl/protocol/TER.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ enum TEFcodes : TERUnderlyingType {
182182
tefTOO_BIG,
183183
tefNO_TICKET,
184184
tefNFTOKEN_IS_NOT_TRANSFERABLE,
185+
tefINVALID_LEDGER_FIX_TYPE,
185186
};
186187

187188
//------------------------------------------------------------------------------

include/xrpl/protocol/TxFormats.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,16 @@ enum TxType : std::uint16_t
190190
/** This transaction type deletes a DID */
191191
ttDID_DELETE = 50,
192192

193-
194193
/** This transaction type creates an Oracle instance */
195194
ttORACLE_SET = 51,
196195

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

199+
/** This transaction type fixes a problem in the ledger state */
200+
ttLEDGER_STATE_FIX = 53,
201+
202+
200203
/** This system-generated transaction type is used to update the status of the various amendments.
201204
202205
For details, see: https://xrpl.org/amendments.html

include/xrpl/protocol/jss.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ JSS(NFTokenAcceptOffer); // transaction type.
104104
JSS(NFTokenCancelOffer); // transaction type.
105105
JSS(NFTokenCreateOffer); // transaction type.
106106
JSS(NFTokenPage); // ledger type.
107+
JSS(LedgerStateFix); // transaction type.
107108
JSS(LPTokenOut); // in: AMM Liquidity Provider deposit tokens
108109
JSS(LPTokenIn); // in: AMM Liquidity Provider withdraw tokens
109110
JSS(LPToken); // out: AMM Liquidity Provider tokens info

src/libxrpl/protocol/Feature.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,7 @@ REGISTER_FEATURE(NFTokenMintOffer, Supported::yes, VoteBehavior::De
497497
REGISTER_FIX (fixReducedOffersV2, Supported::yes, VoteBehavior::DefaultNo);
498498
REGISTER_FIX (fixEnforceNFTokenTrustline, Supported::yes, VoteBehavior::DefaultNo);
499499
REGISTER_FIX (fixInnerObjTemplate2, Supported::yes, VoteBehavior::DefaultNo);
500+
REGISTER_FIX (fixNFTokenPageLinks, Supported::yes, VoteBehavior::DefaultNo);
500501
// InvariantsV1_1 will be changes to Supported::yes when all the
501502
// invariants expected to be included under it are complete.
502503
REGISTER_FEATURE(InvariantsV1_1, Supported::no, VoteBehavior::DefaultNo);

src/libxrpl/protocol/SField.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ CONSTRUCT_TYPED_SFIELD(sfHookStateChangeCount, "HookStateChangeCount", UINT16,
113113
CONSTRUCT_TYPED_SFIELD(sfHookEmitCount, "HookEmitCount", UINT16, 18);
114114
CONSTRUCT_TYPED_SFIELD(sfHookExecutionIndex, "HookExecutionIndex", UINT16, 19);
115115
CONSTRUCT_TYPED_SFIELD(sfHookApiVersion, "HookApiVersion", UINT16, 20);
116+
CONSTRUCT_TYPED_SFIELD(sfLedgerFixType, "LedgerFixType", UINT16, 21);
116117

117118
// 32-bit integers (common)
118119
CONSTRUCT_TYPED_SFIELD(sfNetworkID, "NetworkID", UINT32, 1);

src/libxrpl/protocol/TER.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ transResults()
137137
MAKE_ERROR(tefTOO_BIG, "Transaction affects too many items."),
138138
MAKE_ERROR(tefNO_TICKET, "Ticket is not in ledger."),
139139
MAKE_ERROR(tefNFTOKEN_IS_NOT_TRANSFERABLE, "The specified NFToken is not transferable."),
140+
MAKE_ERROR(tefINVALID_LEDGER_FIX_TYPE, "The LedgerFixType field has an invalid value."),
140141

141142
MAKE_ERROR(telLOCAL_ERROR, "Local failure."),
142143
MAKE_ERROR(telBAD_DOMAIN, "Domain too long."),

src/libxrpl/protocol/TxFormats.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,14 @@ TxFormats::TxFormats()
505505
{sfOracleDocumentID, soeREQUIRED},
506506
},
507507
commonFields);
508+
509+
add(jss::LedgerStateFix,
510+
ttLEDGER_STATE_FIX,
511+
{
512+
{sfLedgerFixType, soeREQUIRED},
513+
{sfOwner, soeOPTIONAL},
514+
},
515+
commonFields);
508516
}
509517

510518
TxFormats const&

0 commit comments

Comments
 (0)