Skip to content

Conversation

promag
Copy link
Contributor

@promag promag commented Mar 23, 2019

Fixes #15591.

@promag
Copy link
Contributor Author

promag commented Mar 23, 2019

If it's the right fix then it needs:

  • update to functional test
  • backport to 0.17 and 0.18.

@gmaxwell
Copy link
Contributor

Do we also need to think about how this interacts with restoring the mempool from disk? e.g. is there a race condition where some transactions being loaded would be missed?

@promag
Copy link
Contributor Author

promag commented Mar 23, 2019

IIUC if the mempool is loaded after postInitProcess then TransactionAddedToMempool is already called.

@laanwj
Copy link
Member

laanwj commented Mar 23, 2019

Ordering checks out:

  • CWallet::postInitProcess() is called first: current mempool will be used, wallet will be notified when transactions added to mempool in LoadMempool()
  • LoadMempool() called first: CWallet::postInitProcess() will process all the transactions

As for concurrency:

CWallet::postInitProcess() locks the mempool for the duration of loading transactions from it. LoadMempool() locks the mempool for every individual transaction inserted. This means that it is posible for CWallet::postInitProcess() to be called while the mempool is being loaded. If it manages to get the lock, it will process the current transactions in the mempool, potentially partially complete.

Is the wallet already registered at this point (before CWallet::postInitProcess()) for receiving TransactionAddedToMempool events? If so, there is no race, but it might get some transactions multiple time (I think that's harmless?), if not, it will start receiving transactions again after registering and miss some in that timeframe.

@promag
Copy link
Contributor Author

promag commented Mar 23, 2019

Wallet is registered in CWallet::CreateWalletFromFile:

walletInstance->m_chain_notifications_handler = chain.handleNotifications(*walletInstance);

which happens before CWallet::postInitProcess, so I think there's no race.

@promag
Copy link
Contributor Author

promag commented Mar 23, 2019

but it might get some transactions multiple time (I think that's harmless?)

I also think that trying to improve that is not worth the pain/complexity. But it may cost a bit for large wallets and a large mempool. I'm happy to followup something to improve that.

promag added a commit to promag/bitcoin that referenced this pull request Mar 23, 2019
@laanwj
Copy link
Member

laanwj commented Mar 23, 2019

I also think that trying to improve that is not worth the pain/complexity. But it may cost a bit for large wallets and a large mempool. I'm happy to followup something to improve that.

I agree (it's not worth handling that explicitly), just wanted to cover all possible scenarios.

@promag promag force-pushed the 2019-03-fix-15591 branch from 363b383 to a617ab3 Compare March 23, 2019 12:51
@promag
Copy link
Contributor Author

promag commented Mar 23, 2019

Moved the fix to LoadWallet(), which is used to dynamically load wallets - and so the startup behavior isn't changed.

Also added a test.

@maflcko
Copy link
Member

maflcko commented Mar 23, 2019

 node1 2019-03-23T13:08:34.742866Z POTENTIAL DEADLOCK DETECTED 
 node1 2019-03-23T13:08:34.742874Z Previous lock order was: 
 node1 2019-03-23T13:08:34.742883Z  (1) ::mempool.cs  wallet/wallet.cpp:152 
 node1 2019-03-23T13:08:34.742898Z  (2) cs_main  interfaces/chain.cpp:264 
 node1 2019-03-23T13:08:34.742912Z Current lock order is: 
 node1 2019-03-23T13:08:34.742921Z  (2) cs_main  init.cpp:1475 
 node1 2019-03-23T13:08:34.742934Z  (2) cs_main  validation.cpp:4300 
 node1 2019-03-23T13:08:34.742947Z  (1) cs  txmempool.cpp:593 

@maflcko maflcko modified the milestones: 0.18.0, 0.17.2 Mar 23, 2019
@promag promag force-pushed the 2019-03-fix-15591 branch from a617ab3 to 3f70633 Compare March 23, 2019 14:20
@promag
Copy link
Contributor Author

promag commented Mar 23, 2019

@MarcoFalke fixed.

@promag promag force-pushed the 2019-03-fix-15591 branch from 3f70633 to 3e31d68 Compare March 23, 2019 23:06
@meshcollider
Copy link
Contributor

tested ACK 3e31d68, cannot reproduce #15591 with this fix

Copy link
Member

@maflcko maflcko left a comment

Choose a reason for hiding this comment

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

Concept ACK

// Update wallet transactions with current mempool transactions.
auto locked_chain = chain.lock();
for (const CTransactionRef& tx : locked_chain->getMemoryPoolTransactions()) {
wallet->TransactionAddedToMempool(tx);
Copy link
Member

Choose a reason for hiding this comment

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

Could there be a race, since we don't take cs_main when removing txs from the mempool?

I.e. a tx is first removed due to eviction, the wallet is notified and then it is re-added here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed, between getMemoryPoolTransactions and TransactionAddedToMempool a tx can be evicted.

I see 2 solutions:

  • lock the wallet before the loop so that TransactionRemovedFromMempool comes after this
  • add a way to lock the mempool in interfaces:: but not sure if this is wanted? cc @ryanofsky

Copy link
Contributor

Choose a reason for hiding this comment

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

re: #15652 (comment)

I see 2 solutions:

I think more ideally the wallet doesn't have knowledge or control of node locks, and can just register for notifications and handle them as they come in. Maybe the ChainImpl::handleNotifications method can be changed to something like:

std::unique_ptr<Handler> handleNotifications(Notifications& notifications) override
{
    LOCK2(::cs_main, ::mempool.cs);
    for (const CTxMemPoolEntry& entry : ::mempool.mapTx) {
        notifications.TransactionAddedToMempool(entry.GetSharedTx());
    }
    return MakeUnique<NotificationsHandlerImpl>(*this, notifications);
}

Copy link
Member

Choose a reason for hiding this comment

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

If you move the loop into postInitProcess, you can just take a LOCK(::mempool.cs) in there

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@MarcoFalke postInitProcess is wallet module, should not use that right? #15652 (comment)

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, you'd have to move it to the interface

Alternatively you could add it to handleNotifications as suggested by @ryanofsky, but then it would also be called for createwallet, which seems a bit wasteful

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ryanofsky nice, I thought of something like replayMemoryPoolNotifications. However I'm not sure if these notifications should come after ReacceptWalletTransactions?

Copy link
Contributor

Choose a reason for hiding this comment

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

re: #15652 (comment)

Alternatively you could add it to handleNotifications as suggested by @ryanofsky, but then it would also be called for createwallet, which seems a bit wasteful

Agree, this would be too wasteful. Having the separate method to replay notifications is probably better.

I'm not sure if these notifications should come after ReacceptWalletTransactions?

I'm not 100% sure, but I don't think I see a problem if notifications about what's already in the mempool happen before the wallet adds more transactions to the mempool. I think what you have now basically seems good though.

@promag promag force-pushed the 2019-03-fix-15591 branch from 3e31d68 to 12fb550 Compare March 25, 2019 16:03
@DrahtBot
Copy link
Contributor

DrahtBot commented Mar 25, 2019

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #15713 (refactor: Replace chain relayTransactions/submitMemoryPool by higher method by ariard)
  • #15639 (bitcoin-wallet tool: Drop libbitcoin_server.a dependency by ryanofsky)
  • #15632 (Remove ResendWalletTransactions from the Validation Interface by jnewbery)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@promag promag force-pushed the 2019-03-fix-15591 branch from 12fb550 to 863a26d Compare March 25, 2019 19:01
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Aug 17, 2020
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Sep 2, 2020
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Sep 2, 2020
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Sep 25, 2020
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Sep 25, 2020
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Apr 11, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Apr 11, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request May 19, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request May 19, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jun 14, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jun 14, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jun 14, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jun 15, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Aug 19, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Aug 19, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Sep 3, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Sep 3, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Oct 5, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Oct 5, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Oct 13, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Oct 13, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Nov 29, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Nov 29, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Nov 29, 2021
This is just a code simplification and revert of
0440481 from
bitcoin#15652. No behavior is changing.
kwvg added a commit to kwvg/dash that referenced this pull request Dec 4, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Dec 12, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Dec 13, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Dec 13, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Dec 13, 2021
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Dec 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

balance wrong after unloading wallet and loading it again
10 participants