-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Fix pay-to-self Accounts bug #2682
Fix pay-to-self Accounts bug #2682
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2682 +/- ##
========================================
+ Coverage 76.6% 76.7% +<.1%
========================================
Files 113 113
Lines 18383 18431 +48
========================================
+ Hits 14090 14137 +47
- Misses 4293 4294 +1 |
2ad280d
to
5eb5e4d
Compare
5eb5e4d
to
4b7b708
Compare
How does this get pass the account lock code? |
@CriesofCarrots, so the bug is in Accounts::lock_accounts
The reason for the two step commit is because if the tx fails all the keys for the tx need to be reverted. That might be another option. |
@aeyakovenko , actually, I think you mean Accounts::lock_account Line 283 in cdb2a7b
I assumed that was desirable (I'm not clear on the assumptions made about Transaction slices in banking_stage). If it's not, another option would be to remove lines 294-295 |
The double loop in lock_account is why the invalid transaction doesn't report AccountInUse. Merging those loops would catch this invalid transaction, but would make that error ambiguous. It's suppose to mean "try again later", not "invalid transaction - duplicate keys" |
I prefer the fix in this PR |
I'm running with it 👼 |
FYI, @TristanDebrunner , thanks! |
Looks like this broke master |
@garious, we generally want to fail as early as possible. In this case all the accounts remain locked for this failed tx until the entire batch is unlocked. |
@aeyakovenko, I agree, we should fail as early as possible. But in this case, that means we should verify the individual transaction before we do the cross-transaction AccountInUse check. We do other individual tx checks earlier, like sigverify. |
Problem
Top level bug: Given an account with a positive token balance, it is possible to magically increase your balance by paying tokens to yourself (bank processes a
SystemTransaction::new_move
orSystemTransaction::new_account
, where the signing keypair and recipient pubkey are the same account).Root cause: When the same account is listed as both the "from" keypair and "to" pubkey, the account is loaded into the tx accounts vector twice. When
runtime::execute_instruction
is called, the pre_total:post_total check passes, because the debit is applied to one instance of the account, and the credit to the other. Then when the accounts are re-stored, the 2nd account instance overwrites the first, saving the credited account.Summary of Changes
Add check for unique keys when loading accounts for a discrete transaction.
... There are other potential ways to solve this bug, but I have yet to think of any legitimate reasons why one transaction would need to load the same account twice. I believe that is why Instructions index into the accounts array, after all.
Fixes #