-
Notifications
You must be signed in to change notification settings - Fork 592
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
wallet: Avoid duplicate address creation #941
Conversation
This commit adds a test that demonstrates that duplicate addresses can be created in the wallet before the fix.
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.
Thanks for the fix!
Tried to run the test after the fix but got a timeout,
go test -v -timeout=10s -run=TestDuplicateAddressDerivation
Looks like there's a dead lock?
No, it just takes quite a while to derive 10x10x10 addresses... Can you try again with something like 30 seconds or more? |
If I run the test w/o the second commit, I hit it pretty quickly:
|
eebf2d0
to
b901f0b
Compare
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.
Cool the test passed,
=== RUN TestDuplicateAddressDerivation
--- PASS: TestDuplicateAddressDerivation (20.86s)
PASS
ok github.com/btcsuite/btcwallet/wallet 21.450s
Since deep down they are all calling nextAddresses
, also noticed that,
NewChangeAddress -> newChangeAddress -> NextInternalAddresses
CurrentAddress -> newAddress -> NextExternalAddresses
Should we also update these calls?
The alternative, instead of locking over locks, we can make these indices atomic, not sure if it helps,
Lines 157 to 165 in e391a1c
// The external branch is used for all addresses which are intended for | |
// external use. | |
nextExternalIndex uint32 | |
lastExternalAddr ManagedAddress | |
// The internal branch is used for all adddresses which are only | |
// intended for internal wallet use such as change addresses. | |
nextInternalIndex uint32 | |
lastInternalAddr ManagedAddress |
@yyforyongyu I don't think that's enough (making the variables atomic) as we have other operations in the btcwallet/waddrmgr/scoped_manager.go Lines 1199 to 1209 in e391a1c
|
Because the way the scoped manager uses the OnCommit callback of the database transaction mechanism, the manager's lock is released first, then re-acquired in the OnCommit. But during that short time of releasing the lock, another goroutine might already have updated the in-memory state. We add another mutex around the whole database transaction to address the problem.
b901f0b
to
b3fc760
Compare
Thanks for taking a closer look, @yyforyongyu ! You are correct, I missed a couple of paths. I now traced back the Here are the ones I found and now added the new mutex to:
I hope that's all of them. |
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.
LGTM🙏 I think before merging this we can create a PR in lnd
first to see if the CI passes.
CI passing on the |
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.
LGTM 💰
Fixes lightningnetwork/lnd#8697.
Because the way the scoped manager uses the OnCommit callback of the
database transaction mechanism, the manager's lock is released first,
then re-acquired in the OnCommit. But during that short time of
releasing the lock, another goroutine might already have updated the
in-memory state.
We add another mutex around the whole database transaction to address
the problem.