Skip to content
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

electrum: fix update of spend_txid for spending coins #1324

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

jp1ac4
Copy link
Collaborator

@jp1ac4 jp1ac4 commented Sep 11, 2024

If the spend txid of a coin changes, we should update with the new txid.

This would affect a spending coin for which the spending transaction changes and the new spend transaction is confirmed in a single poll.

@jp1ac4 jp1ac4 marked this pull request as ready for review September 11, 2024 16:49
@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Sep 11, 2024

I think if the spending coin is already in the DB, the spending_coins: Vec<OutPoint, Txid> passed to spent_coins would contain one entry with the old spend_txid and one with the new. So it's possible that we would still insert the correct spend_txid into the DB without this fix, depending on the order of iteration.

@darosior
Copy link
Member

A regression test would demonstrate whether the fix is necessary. 🤷

src/bitcoin/mod.rs Outdated Show resolved Hide resolved
@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Sep 12, 2024

A regression test would demonstrate whether the fix is necessary. 🤷

Given that we iterate over the spending coins from the DB first and then the updated spending info, I think we will always use the correct value without this change as we'll first insert the wrong value and then the right value. I wasn't able to write a functional test to trigger this error.

EDIT: Related to this, we should probably modify how the two iterators are chained together so that we only include spending coins from the DB if they're not part of the other, up-to-date iterator. We shouldn't be passing the same outpoint more than once to spent_coins().

@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Sep 12, 2024

I think we should still include this change in the future so that we don't rely on the order of iteration.

EDIT: As a test, I swapped the order of iteration and confirmed that my functional test fails without this PR and passes with it.

EDIT: Note that the replacement tx needs to be broadcast externally to the wallet in order to trigger this failure. Otherwise, the poller runs when broadcasting and the new spend_txid is detected while the coin is still spending.

@nondiremanuel nondiremanuel added this to the v8 - Liana milestone Sep 12, 2024
@jp1ac4 jp1ac4 force-pushed the electrum-fix-spent-coins branch 2 times, most recently from a8bb0d3 to 7180245 Compare September 12, 2024 15:21
@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Sep 12, 2024

I've pushed the functional test that would fail without this PR if the order of iteration of spending coins were reversed.

@jp1ac4 jp1ac4 marked this pull request as draft September 12, 2024 15:38
If a replacement tx is not seen by Liana until it is confirmed,
make sure the coin now confirmed as spent by the replacement
has its spend_txid set correctly.
Comment on lines +1232 to +1233
# The replacement has to be done externally so that Liana doesn't
# see it until it is confirmed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would still see it when it's included in the mempool.

Copy link
Collaborator Author

@jp1ac4 jp1ac4 Sep 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should add to this comment that I stop and start lianad while the replacement is broadcast and confirmed to ensure that it isn't seen by Liana in the mempool.

@darosior
Copy link
Member

EDIT: Related to this, we should probably modify how the two iterators are chained together so that we only include spending coins from the DB if they're not part of the other, up-to-date iterator. We shouldn't be passing the same outpoint more than once to spent_coins().

I agree, looks like this code is only accidentally correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

3 participants