-
Notifications
You must be signed in to change notification settings - Fork 5k
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
Address resubmit bug #6886
Address resubmit bug #6886
Conversation
A user submitted a transaction from their MetaMask, and found it resulted in 20 nearly-identical transactions (apart from the nonce). In their state logs, those 20 transactions were one, but in that one transaction’s history we could see:
So it seemed clear that MetaMask had in fact submitted these transactions. Upon reviewing the transaction controller, Frankie identified the approveTransaction function as a point of interest. This function performs three critical and related operations:
She also noted that this function is called by the pending-tx-tracker in one place:
This resubmitTx function is called upon each new block, and because of our “network silent mode”, we call this function repeatedly in a loop when reconnecting to the internet and “catching up” to the current block. This theory explains the mysterious chain of 23 empty arrays, because the approveTransaction function begins by setting the transaction status to approved, an operation that shows up as an empty array in the history when the tx status is already approved. When we review the approveTransaction function in this context, it becomes clear that it is filled with asynchronous operations, like getting a nonce, and getting a signature, and publishing, which should not be done while it is being done with another copy of the same transaction. metamask-extension/app/scripts/controllers/transactions/index.js Lines 92 to 103 in 2a7278e
It turns out we began passing it approved transactions to mitigate an issue where a system interruption could leave “approved” transactions hanging, never getting signed. I proposed the simplest solution I could, which was a very simple lock around the There is still room for a better cleanup of this code. The un-sticking of transactions that need to be signed could be broken into its own function, which becomes the part that requires locking, while the pendingTxTracker would no longer need access to a signing method. That said, this is a scary bug that could result in much worse loss than it did, and so I propose we merge this quick fix for now, and can submit a cleaner fix later. |
In retrospect, it makes sense that this bug was rare, because it required some kind of network interruption in the moment between user approval and transaction signing. It then required the user to regain network access, and MetaMask to rapidly attempt to catch up with blocks all before the transaction's initial nonce could be calculated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is good as a hot fix
would still like one other person to review if possible |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent writeup! Seems like a pretty reasonable solution for the time being.
Added some notes, and one possible approach at a fix, for discussion.