New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
XLS-7d Deletable Accounts on the XRP Ledger #8
Comments
Well thought out. I was going to suggest a merge operation instead as most of our users actually have several accounts they want to merge into one, but deleting is probably cleaner. |
What happens to the three accounts listed in Appendix D. |
these account can not delete as the Sequence Greater Than LedgerSequence To delete a account, the current LedgerSequence must be at least 256 higher than the account's sequence number |
This means someone could create an escrow sending me one drop with
and
Why shouldn't the debtee be allowed to delete their account and forgo the owed amount(s), just as the destination accounts of legacy obligations (without links to the destination) are allowed to be deleted? To delete an escrow's destination, replace the destination with the sender account.
Given that the owner reserve is "an increase to the reserve requirement for each object that the address owns in the ledger", why not use it as the amount refunded for a deleted account since the AccountRoot object that was owned by the account is being removed from the ledger? Does the unrefunded amount of the account reserve need to be represented in the fee? |
This could be helped by account sequence skipping functionality (which could also benefit multisign accounts). A transaction flag could allow a transaction sequence to be ahead of the current account sequence, in which case air gapped account setup transaction(s) would use sequence number(s) well ahead of the current ledger sequence. Afaict, being able to subsequently use skipped sequence numbers wouldn't make a difference in this particular case. |
The XRP Ledger utilizes an account model. Unlike systems based on a UTXO model, XRP Ledger accounts are first-class objects. This design choice allows the XRP Ledger to offer rich functionality, including the ability to own objects (offers, escrows, checks, signer lists) as well as other advanced features, such as key rotation and configurable multi-signing without needing to change a destination address. The trade-off is that accounts must be stored on ledger. The XRP Ledger applies reserve requirements, in XRP, to protect the shared global ledger from growing excessively large as the result of spam or malicious usage. Prior to this commit, accounts had been permanent objects; once created, they could never be deleted. This commit introduces a new amendment "DeletableAccounts" which, if enabled, will allow account objects to be deleted by executing the new "AccountDelete" transaction. Any funds remaining in the account will be transferred to an account specified in the deletion transaction. The amendment changes the mechanics of account creation; previously a new account would have an initial sequence number of 1. Accounts created after the amendment will have an initial sequence number that is equal to the ledger in which the account was created. Accounts can only be deleted if they are not associated with any obligations (like RippleStates, Escrows, or PayChannels) and if the current ledger sequence number exceeds the account's sequence number by at least 256 so that, if recreated, the account can be protected from transaction replay.
Given that Deletable Accounts following this spec are live on the ledger, I move to declare this standard settled and commit this standard to the repository. |
Note: embedded in |
The latest version of this spec can be found here: XLS-7 Deletable Accounts
Abstract
One desirable feature for the XRP Ledger would be for it to be possible to completely remove an account from the ledger and recover the reserve from that account. We call this a deletable account.
There are three primary concerns with deleting accounts:
Account Obligations
What are the sorts of obligations that can occur between accounts on the XRP ledger? There are quite a few. But let's start with the classic: a trust line. A trust line, in part, tracks the balance of an issued currency between two accounts in the XRP Ledger. Whenever that balance is anything other than zero, that means one of the two accounts owes that much of the currency to the other account.
What Is Desirable
Conservatively, if one account owes currency to another account both of those accounts must be retained on the ledger until the debt is resolved.
Here's a list of all the ledger objects that represent obligations, both debts and other sorts, between accounts:
Check
,Escrow
,PayChannel
, andRippleState
(the in-ledger representation of a TrustLine)Clearly an account that holds any of these types of ledger objects should not be deleted from the ledger.
Escrow
is worth expanding on. AnEscrow
is often between two accounts. But anEscrow
may be from one account to the same account. Note that anEscrow
from an account to itself is still an obligation between accounts; it's an obligation from that account to all of the other accounts on the ledger. ThatEscrow
says, in effect, the escrowing account will retain ownership of the escrowed XRP (i.e., not spend that XRP) until theEscrow
expires.There are a few ledger types that an account can hold without any obligations to other accounts. Those are:
DepositPreauth
,DirectoryNode
,Offer
,SignerList
, andTicket
(not yet in the XRP Ledger Documentation Portal).And, finally, there are transactions that don't (directly) add or remove any of the account's directory entries:
AccountSet
,Payment
, andSetRegularKey
.So, at least by the guidelines we've set out so far, an account should be deletable if it holds none of the following ledger types:
Check
,Escrow
,PayChannel
, orRippleState
(the in-ledger representation of a TrustLine).What Is Achievable
However there's a fly in this ointment. It is not uniformly easy to tell when an account is associated with one of these obligations. Generally an obligation leaves a link behind in the directories of accounts the obligation is associated with. For example when a
RippleState
is added to the ledger, the two accounts associated with thatRippleState
each have a link added from their directory to the newRippleState
. Those links make it relatively easy to see that the accounts are related to theRippleState
. You just have to walk the account's directory entries.Check
s also have links similar to the ones that are added forRippleState
. AndEscrow
s created since November 14 2017 (when fix1523 was enabled) also have similar links.But older
Escrow
s (none of which are on the production XRP Ledger) and all currentPayChannel
objects only have one link: a link to the owner.We'll call these obligations that lack a back link from their destination accounts legacy obligations.
The lack of a link from the destination to a legacy obligation means we can't currently prevent deletion of an account that is the destination of a legacy obligation.
What to do?
PayChannel
s have links from their destination as well as from their owner. That way newPayChannel
s will have the desired behavior. The amendment will affect thePaymentChannelCreate
transaction and theaccount_channels
andaccount_objects
RPC commands.Escrow
andPaymentChannel
transactions where the destination account is missing from the ledger. More on that in the next section.The upshot is that, as long as legacy
PayChannel
orEscrow
objects are in the ledger, a person deleting an account needs to be careful. But if an account goes missing, then transactions operating on legacy obligations will have reasonable behavior.Obligations Where the Destination Disappeared
It's worth thinking hard about the behavior an
Escrow
and aPayChannel
should exhibit if their destination account goes missing. When thinking about this it is worthwhile to consider two related issues:Once deleted, an account can be resurrected (see section below). To a
PayChannel
and anEscrow
, a destination account that has been deleted and resurrected is indistinguishable from an account that was never deleted. Since that's the case, how many special conditions do we want for the case where the destination account is missing (and might be resurrected later)?My personal take is that we should minimize the number of special conditions that we handle when a destination is absent since that destination may very well be resurrected in the future.
Whatever rules we choose should be minimal and unsurprising. We actually never expect to see these rules applied to
Escrow
s on the production ledger. There are currently no escrows in the production ledger that meet the conditions where these rules would apply. However we do expect these rules may be applied to some number ofPayChannel
s.PayChannel
With a Missing DestinationThere are three transactions that affect
PayChannel
objects. They are:PaymentChannelCreate
is unaffected. The destination must be present for this transaction to succeed.PaymentChannelFund
should fail if the destination is not in the ledger. However thePayChannel
itself should be otherwise unaffected.PaymentChannelClaim
can exhibit a lot of different behaviors (see PaymentChannelClaim) depending on its arguments. Here are the different scenarios:The source address of a channel can:
Send XRP from the channel to the destination.
If the destination account is missing from the ledger this should fail and leave the channel otherwise unaffected.
Set the channel to expire as soon as the channel's SettleDelay has passed.
This should succeed.
Clear a pending Expiration time.
This should succeed.
Close a channel immediately if the channel has no XRP remaining.
This should succeed.
The destination address of a channel can do nothing in any of these cases; the destination account is missing from the ledger.
Any address sending this transaction can:
Cause a channel to be closed if its Expiration or CancelAfter time is older than the previous ledger's close time. Any validly-formed
PaymentChannelClaim
transaction has this effect regardless of the contents of the transaction.This should succeed.
Escrow
With a Missing DestinationThere are three transactions that affect
Escrow
objects. They are:EscrowCreate
is unaffected. The destination must be present for this transaction to succeed.EscrowFinish
should fail with an error if the destination is missing. AnEscrowFinish
cannot be used to create (or resurrect) an account. However theEscrow
object itself is otherwise unaffected and remains in the ledger.EscrowCancel
should be unaffected other than that the destination cannot be the account that does the cancel, since the destination account is missing from the ledger.Preventing Replay
A very important part of the XRP Ledger's security model is that any given transaction can be applied at most once. So we should not only be concerned with accounts being deleted. We also need to be concerned with old transactions if that deleted account is ever recreated in the ledger.
Resurrecting An Account
But first, how could an account be recreated after it has been deleted?
Turns out that's pretty easy. All it takes is a single payment of XRP to the account ID of the deleted account and the account springs back to life. The XRP payment must be sufficient to meet the base reserve. That's it!
The resurrected account has no recollection of its previous life. In effect, it has the same name -- the same identity -- as the earlier account. But that's all it has in common.
Why is it so easy to resurrect an account? Because once an account is deleted it's gone. The current ledger has no idea that the account ever existed. So, as far as the ledger is concerned, the resurrected account is actually a brand new account.
If a deleted account is ever resurrected in this way we want to be sure that old transactions from that identity cannot be re-applied against the resurrected account.
Preventing Replay on a Resurrected Account
The standard mechanism for preventing transaction replay on a given account is the
Sequence
number. AnAccountRoot
carries a 32-bit integralSequence
value. Any successful transaction must carry the matchingSequence
number or else the transaction is rejected. Certain kinds of failing transactions (the nearly successful ones, codedtec
) also must carry the matchingSequence
number.Once the transaction succeeds (or fails with a
tec
) theAccountRoot
'sSequence
is incremented. This increment prevents thatAccountRoot
from accepting that previousSequence
number in a transaction ever again.We can leverage this behavior to make resurrected accounts never accept old transactions. Here's how:
Only allow an account to be deleted if its
AccountRoot
'sSequence
number is at least 256 less than the currentLedgerSequence
number of the ledger the transaction is applied to. This should be an easy requirement for most accounts to meet. There are two ways to fail to meet the requirement.In order to fail that requirement an account would need to, on average, put one or more transactions into every validated ledger. Such accounts do, indeed, exist. But they are rare. See Appendix D.
Another way to fail that requirement is for the account in question to have been created within the last 20 minutes or so.
In either case, simply letting an account (that hasn't been extraordinarily busy) sit quietly for a little while will let the
LedgerSequence
get far enough past theAccountRoot
'sSequence
that the account can be deleted.Change the rule for the starting value of the
AccountRoot
'sSequence
number on a new account. Historically theSequence
number has always started at 1. Now we will start theAccountRoot
'sSequence
at the value of the currentLedgerSequence
of the ledger the transaction is applied to. That will be much greater than 1.Now, when a new account is created, any valid transactions from a previously existing account with the same account ID cannot be replayed on the resurrected account. The sequence numbers of any old transactions are in the past. Every one of those old transactions will fail with a
tefPAST_SEQ
error code.Requiring the
AccountRoot
'sSequence
be at least 256 less than the currentLedgerSequence
is the result of an abundance of caution. It would probably be adequate for theAccountRoot
'sSequence
to be one less than the currentLedgerSequence
. One less should be sufficient to prevent problems if an account is deleted and resurrected in the same ledger. But a difference of 256 gives us some breathing room (to account for things like the TxQ and transaction retries). The particular choice of 256 versus other numbers matches the occurrence rate of flag ledgers. This means there are slightly fewer arbitrary numbers for XRP Ledger users to remember.Consequences of Using the
LedgerSequence
as the FirstSequence
Having the initial
Sequence
number of an account root be the currentLedgerSequence
rather than one will complicate the lives of folks who do air gapped account setup.What is air gapped account setup?
For some folks, setting up a new account on the XRP Ledger is a multi-step process. They want to create the account, yes. But they also want to set certain flags on the
AccountRoot
. They may also want to set up aRegularKey
or, possibly, give the account multisigning capability by adding aSignerList
. Getting it all done takes multiple transactions. That is account setup.Air gapped account setup is when you want to write all of the setup transactions in one shot on an air gapped computer. The air gapping keeps the private key used to sign all of those transactions more secure. Then you (manually) carry all of those signed transactions over to a computer that is connected to the web and submit them to the Ledger.
Historically air gapped account setup has been pretty easy because the newly created account always had
Sequence
one. However if theSequence
value of a newly created account varies depending on when the account is created the problem gets harder.There is at least one work around. But the work around is complicated enough that the description is given in Appendix C. Not here.
Avoiding Abuse
The XRP Ledger doesn't have very many levers to discourage abusive behaviors. Pretty much all it can do is make abusive behaviors more expensive.
So, at least for the initial release, deleting an account will not return all of the XRP. To accomplish this a transaction that deletes an account has a minimum fee that is equal to the owner reserve. At the time of this writing (September 2019) that owner reserve is 5 XRP. So if someone creates an account with 20 XRP, they can get 20 XRP minus 5 XRP equals 15 XRP back.
Once we understand the actual uses of account deletion it will be possible to lower that fee with an amendment. But having a high fee allows us to start with a conservative approach.
One other possible form of abuse would be deleting an account with a huge number of directory entries. If a single transaction affects too many ledger nodes then the transaction can't complete because it produces too much metadata. Producing too much metadata helps no one. All of the nodes on the network execute the transaction which fails and then the transaction's fee is burned.
So rather than allow deleting an account to fail with a
tecOVERFLOW
we set a limit of 1000 directory entries that will be deleted along with the account. This is a high enough number for any reasonable deletable account. And it's also low enough that there shouldn't be any issue with an account delete producing atecOVERFLOW
result. So if an account has more than 1000 directory entries, attempting to delete that account will give atefTOO_BIG
result.How To Delete An Account
We expect deleting an account to be an unusual enough circumstance that it deserves its own, brand new, transaction. We'll call it
AccountDelete
.What are the upsides?
We can give the new transaction exactly the behavior that we want, rather than relying on some pre-existing transaction being pretty close to what we want.
It will be easier to find account deletion in the ledger history.
We can return better error messages if we're certain that the user's intent is to delete the account.
An
AccountDelete
transaction can do extra work, like deletingDepositPreauth
s orTicket
s from the account.We can give the
AccountDelete
transaction aDestination
without anAmount
. TheDestination
receives whatever XRP is left when the transaction completes.What are the downsides? Simply that we're adding a new transaction type.
Summary
Changes That Affect All Newly Created Accounts
AccountRoot
'sSequence
field initialized to the the currentLedgerSequence
value, not to one.Account Deletion
AccountDelete
transaction.AccountDelete
carries aDestination
. XRP left over after the account is deleted goes to theDestination
.AccountRoot
'sSequence
number must be at least 256 less than the current value of theLedgerSequence
.Check
,Escrow
,PayChannel
, orRippleState
.EscrowFinish
,PaymentChannelClaim
, andPaymentChannelFund
.AccountDelete
transaction automatically removes the following ledger types from the account and, if appropriate, recovers their reserve:DepositPreauth
,DirectoryNode
,Offer
,SignerList
, andTicket
(not yet in the XRP Ledger Documentation Portal).AccountDelete
transaction has a minimum fee equal to the owner reserve. This minimum fee is the same regardless of whether the transaction is multisigned or not.Appendix A: Design Decisions
Q: Do the suggested rules miss any conditions that should prevent an account from being deleted?
A: We don't think so. Of course, the proposed rule changes and the implementation should be very carefully reviewed.
Q: Are there preferable approaches besides using a new
AccountDelete
transaction to delete accounts?A: Using a standard
Payment
transaction instead ofAccountDelete
was discussed as a possibility. The feeling was that a transaction specifically designed for deleting an account was a better choice.AccountDelete
improves clarity in the transaction itself and in history for what was intended to be accomplished.AccountDelete
transaction makes it sensible to perform helpful operations, like destroying an account's leftoverTicket
s. The additional work makes no sense within the context of aPayment
transaction.AccountDelete
with noAmount
field removes a scenario where a partial payment might be deployed.Q: Is the proposed
AccountDelete
doing too much work? Should we force people to manually remove any excessSignerList
,DepositPreauth
, orTicket
objects in their directory?A: We don't think so. The work it does is beneficial in three ways:
Q: Should
AccountDelete
support an optionalDeliverMin
field?A: No. If you want to delete the account, you just want it gone. As long as the XRP is recovered you've accomplished your goal. If we discover a reason in the future why a
DeliverMin
is desirable then we can add it later.Q: Should we allow the
Destination
of anAccountDelete
to be the same as theAccount
? Such a transaction would destroy and resurrect the account in a single step.A: No. This is a conservative choice. If two different transactions are required to delete and then to recreate an account, then the ledger history will actually show the account being deleted and then recreated as two separate events. If they happen in the same transaction then the metadata record shows an
AccountRoot
modification, which is not actually what happened.This is also the kind of capability that could be added later if a crying need shows up.
Q: Is it fair to require the
Destination
of anAccountDelete
to already exist?A: Yes. This too is the conservative choice. It allows
AccountDelete
to not know about account creation, which currently only Payment knows. Simpler code runs faster and has fewer bugs.This too is a capability that could be added later if there is a crying need.
Q: This account resurrection thing seems like it could be dangerous. Is there a way to prevent that?
A: Yes, it could be prevented, but at a fairly high cost.
In order to prevent a deleted account from being resurrected, the ledger would need to keep a record of each deleted account. Consider, if account deletion becomes popular, there may eventually be millions of deleted accounts. So any record of deleted accounts needs to be compact, scalable, and support efficient lookup. And, at least with the current design, there would be no cost to ledger users for adding more deleted account records. So users would not be motivated to try to limit the number of deleted accounts that they create.
Therefore, rather than deal with the problem of unbounded in-ledger deleted account record storage, we're choosing to live with the peculiarities of account resurrection.
Q: Should there be a flag that prevents a
Payment
from accidentally resurrecting an account?A: This was considered and rejected. In hindsight it would have been great to require a Payment to set a flag if it was creating an account. Or, even better, have a distinct transaction to create an account. Neither of those are in place today.
What we could do today is add a flag to the
Payment
transaction that would prevent account creation. The general belief is that even if such a flag were added the actual adoption of the flag would be minimal. The added complexity would not be worth the payoff.Appendix B: Specification
Affected Ledger Type:
AccountRoot
Although this change does not show in the structure of the
AccountRoot
anAccountRoot
can now be deleted from the ledger, which has never before been possible.Additionally, once the amendment passes, the starting value of the
Sequence
number of theAccountRoot
is affected.Sequence
field starts at1
.Sequence
field inherits the value of the currentLedgerSequence
as the starting value.Affected Transactions
New Transaction:
AccountDelete
Parameters
Account
Destination
DestinationTag
The following example is an
AccountDelete
transaction that deletes account "a" and sends the remaining XRP to another account,rrrrrrrrrrrrrrrrrrrrrhoLvTp
.Reasons why an
AccountDelete
transaction might fail:AccountDelete
transaction does not specify a large enoughFee
.Account
does not have sufficient XRP to pay the fee.Account
'sAccountRoot
'sSequence
number is not at least 256 less than the currentLedgerSequence
value.Account
andDestination
are the same.Destination
is not present in the ledger.Destination
requires deposit preauthorization which is not granted.Account
has at least one of the following ledger types anywhere in its directory:Check
,Escrow
,PayChannel
, orRippleState
.Account
has more than 1000 directory entries at the time of theAccountDelete
transaction.If successful, the
AccountDelete
:Account
:DepositPreauth
,DirectoryNode
,Offer
,SignerList
, andTicket
(not yet in the XRP Ledger Documentation Portal).Account
intoDestination
's balance.Account
'sAccountRoot
from the ledger.AccountDelete
transaction has a minimum fee equal to the owner reserve. This minimum fee is the same regardless of whether the transaction is multisigned or not.AccountDelete
transaction goes into the TxQ, it is considered a blocker. It is handled the same waySetRegularKey
andSetSignerList
transactions are handled by the Txq.Modified Transaction:
EscrowFinish
An
EscrowFinish
transaction fails if the destination account is missing from the ledger. However theEscrow
object in the ledger is otherwise unaffected.Modified Transaction:
PaymentChannelClaim
A
PaymentChannelClaim
that sends XRP from the channel to the destination should fail if the destination is missing from the ledger. However thePayChannel
object in the ledger is otherwise unaffected.Modified Transaction:
PaymentChannelFund
A
PaymentChannelFund
transaction where the destination account is missing from the ledger fails. However thePayChannel
object in the ledger is otherwise unaffected.Hardening Transaction Processing
All transactions should be audited to make sure they handle a missing
AccountRoot
as well as possible.Affected RPC Commands
It will be useful to modify
account_objects
to return all of those objects that represent obligations. That will help users identify what needs to be explicitly removed before an account can be deleted. So theaccount_objects
RPC command will accept a newtype
argument. Callingaccount_objects
with"type" : "blocks_deletion"
will causeaccount_objects
to return only those objects that will prevent account deletion.Other Things Affected
Error Codes
There are likely to be some number of
tef
andtec
error codes added as a result of this effort. The specific error codes have not been identified yet.Amendments
featureDeletableAccounts
There are two coordinated changes which hinge on a single new
featureDeletableAccounts
amendment. Once that amendment passes two changes occur:Sequence
number of all newly createdAccountRoot
objects is the currentLedgerSequence
of the creation ledger. Previously createdAccountRoot
objects are unaffected.AccountRoot
from the ledger using theAccountDelete
transaction.fixPayChanRecipientOwnerDir
After this amendment passes then newly created
PayChannel
s will install back links from both the owner's and the destination's directories to thePayChannel
.PayChannel
objects created before the amendment passes are unaffected. Accounts that are the destination of these newerPayChannel
s will not be deletable.Invariant Checks
The preexisting AccountRootsNotDeleted check will be modified so it does not fire when the transaction is an
AccountDelete
. It also will verify that exactly one account root is deleted by a successfulAccountDelete
transaction. Otherwise an account root is never deleted.A new invariant check will verify that at most one account root is created in one transaction. If an account root is created then the transaction must be a Payment. It also verifies that the newly created account root has the correct Sequence value.
Appendix C: A Process for Air Gapped Account Setup
As noted in the Consequences of Using the
LedgerSequence
as the FirstSequence
section, air gapped account setup becomes more difficult once theLedgerSequence
is the firstSequence
of a brand newAccountRoot
. Previously a person could build their setup transactions and use them seconds, months, or years later. That will no longer be possible.Three accommodations are required:
The person building the transactions must guess approximately the
LedgerSequence
that will be active when their new account is created. We'll call this the first possible ledger sequence.Additionally, the person must decide how much variability they want to allow for when their new account is created. In 2019 so far ledgers are closing about once every 3.7 seconds. So if you want variability of 60 seconds, that's about 17 ledgers. If you want variability of 10 minutes (600 seconds) that's about 165 ledgers. By adding the number of ledgers of variability to the first possible ledger sequence, then you get what we'll call the last possible ledger sequence.
Finally, the person must monitor the network using the
ledger
RPC command to identify an appropriate time to apply the transactions.Once the first and last possible ledger sequences are known the transactions can be constructed. Here is the process.
Construct the transaction that will fund the new account. Set the
LastLedgerSequence
field of the transaction to the value of the last possible ledger sequence. This will prevent the transaction from succeeding in case the buffer is entirely missed.Construct a set of no-op transactions. The first no-op transaction uses as its
Sequence
the first possible ledger sequence. Then build as many additional no-op transactions as are needed to allow for the desired variability. Each no-op transaction uses the next sequence value for itsSequence
. So, for 60 seconds of variability it would take about 17 no-op transactions total. The last no-op transaction has the last possible ledger sequence as itsSequence
.The no-op transactions supply the buffer. Now create the additional (non-no-op) transactions that should be applied to the account in question. These transactions use
Sequence
numbers starting one after the last possible ledger sequence and increment from there.Move all of the (signed) transactions from the air gapped machine over to the machine attached to the network.
Using the
ledger
RPC command, monitor the main network for the first possible ledger sequence.When the
"open"
ledger shows a"seqNum"
equal to or greater than the first possible ledger sequence then submit all of the transactions to the network.Depending on the number of transactions in the account setup, how busy the server you submit the transactions to is, and how busy the network is, it is possible that not all of the transactions will be processed or queued. Assuming all the transactions are properly signed and well formed, if the server is busy one or more of the transactions may return the error response "slowDown", "tooBusy", or "telCAN_NOT_QUEUE". If this occurs consider dividing your transactions into smaller batches and submit the batches to consecutive ledgers. However, once the new account is successfully created you don't have to hurry to get the transactions into the ledger (except for transactions where the
LastLedgerSequence
field is filled in).The "buffer" works by providing transactions that no one cares if they fail. If the account's first
Sequence
number is several past the first possible ledger sequence, then those no-op transactions simply fail with atefPAST_SEQ
error code and are dropped from the network. The remaining no-op transactions are applied to the account, but have no negative consequences other than the fee they burn.Appendix D: Main Net Accounts With
Sequence
Greater ThanLedgerSequence
The Ripple Data team examined a recent ledger and found a total of three accounts on the Main Net where the
AccountRoot
Sequence
field got ahead of theLedgerSequence
. Here are the transactions where the differences were largest for those three accounts. Note that the table is wide and you need to scroll left and right to see all the contents.The text was updated successfully, but these errors were encountered: