Skip to content

Conversation

ariard
Copy link

@ariard ariard commented Apr 18, 2019

In Chain interface, instead of a isPotentialTip and a WaitForNotifications method, both used only once in CWallet::BlockUntilSyncedToCurrentChain, combine them in a higher WaitForNotificationsUpToTip method. Semantic should be unchanged, wallet wait for pending notifications to be processed unless block hash points to the current chain tip or a descendant.

// for the queue to drain enough to execute it (indicating we are caught up
// at least with the time we entered this function).
chain().waitForNotifications();
chain().waitForNotificationsUpToTip(m_last_block_processed);
Copy link
Contributor

Choose a reason for hiding this comment

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

Accessing m_last_block_processed requires the cs_wallet lock. I think to make this work you'll need to:

  • grab cs_wallet
  • access m_last_block_processed
  • release cs_wallet
  • call the waitForNotificationsUpToTip interface method

Alternatively, we could make m_last_block_processed an atomic.

Thoughts, @ryanofsky ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, John's right this needs to synchronize access to m_last_block_processed. Since I don't think there's a straightforward way to make uint256 atomic, maybe a clean way to do this would be to add a new sync.h macro:

-chain().waitForNotificationsUpToTip(m_last_block_processed);
+chain().waitForNotificationsUpToTip(WITH_LOCK(cs_wallet, return m_last_block_processed));
//! Run code while locking a mutex.
//!
//! Examples:
//!
//!   WITH_LOCK(cs, shared_val = shared_val + 1);
//!
//!   int val = WITH_LOCK(cs, return shared_val);
//!
#define WITH_LOCK(cs, code) [&]{ LOCK(cs); code; }()

Copy link
Contributor

Choose a reason for hiding this comment

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

I like the macro, but I don't like putting the complete expression in the waitForNotificationsUpToTip() function call. It's too easy for a casual observer to think that the lock is held for the entire call to waitForNotificationsUpToTip() (which of course would cause a deadlock). How about:

uint256 last_block_hash = WITH_LOCK(cs_wallet, m_last_block_processed);
chain().waitForNotificationsUpToTip(last_block_hash);

which perhaps compiles to the same thing.

Copy link
Author

Choose a reason for hiding this comment

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

Ah yes, wasn't sure of cs_wallet lock covering. Added a WITH_LOCK commit and used to get back m_last_block_processed as showed in example.

@DrahtBot
Copy link
Contributor

DrahtBot commented Apr 18, 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:

  • #15931 (Remove GetDepthInMainChain dependency on locked chain interface by ariard)
  • #15855 ([refactor] interfaces: Add missing LockAnnotation for cs_main by MarcoFalke)

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.

//! Wait for pending notifications to be processed unless block hash points to the current,
//! chain tip, or to a possible descendant of the current chain tip that isn't currently
//! connected.
virtual void waitForNotificationsUpToTip(const uint256& hash) = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the "wait up to" name I suggested earlier in the todo comment is misleading, because this isn't really deciding what to wait for based on the argument, but deciding whether to wait based on the argument.

I think a better name might be waitForNotificationsIfNewBlocks(old_tip) or waitForNotificationsIfNewBlocksConnected(old_tip)

Copy link
Author

Choose a reason for hiding this comment

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

Yes agree wasn't clear so I added Tip but even followed waitForNotificationsIfNewBlocksConnected(old_tip) suggestion, a little bit more verbose but far more insightful

// for the queue to drain enough to execute it (indicating we are caught up
// at least with the time we entered this function).
chain().waitForNotifications();
chain().waitForNotificationsUpToTip(m_last_block_processed);
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, John's right this needs to synchronize access to m_last_block_processed. Since I don't think there's a straightforward way to make uint256 atomic, maybe a clean way to do this would be to add a new sync.h macro:

-chain().waitForNotificationsUpToTip(m_last_block_processed);
+chain().waitForNotificationsUpToTip(WITH_LOCK(cs_wallet, return m_last_block_processed));
//! Run code while locking a mutex.
//!
//! Examples:
//!
//!   WITH_LOCK(cs, shared_val = shared_val + 1);
//!
//!   int val = WITH_LOCK(cs, return shared_val);
//!
#define WITH_LOCK(cs, code) [&]{ LOCK(cs); code; }()

@ariard ariard force-pushed the 2019-04-is-potential-tip branch from 1bcf91d to a4c51ed Compare April 19, 2019 12:16
Copy link
Contributor

@jnewbery jnewbery left a comment

Choose a reason for hiding this comment

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

utACK a4c51ed with a couple of minor nits.

Please remove the @ryanofsky from the commit log. Github buries you in notifications if your name appears in a commit log. You can keep the ryanofsky as long as it's not prefixed by @.

Results from ryanofksy suggestion on isPotentialTip/
waitForNotifications refactoring
@ariard ariard force-pushed the 2019-04-is-potential-tip branch 2 times, most recently from 9bf61e0 to deb5f75 Compare April 20, 2019 12:21
@ariard
Copy link
Author

ariard commented Apr 20, 2019

Noted for the github trick, solved the nits on deb5f75

@jnewbery
Copy link
Contributor

Doesn't build. Please build/test locally before pushing 🙂

@ariard ariard force-pushed the 2019-04-is-potential-tip branch from deb5f75 to 57007b8 Compare April 23, 2019 13:01
@ariard
Copy link
Author

ariard commented Apr 23, 2019

Sorry for that, working on dev scripts to avoid this kind of mistake even for nits updates!

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

utACK 57007b8. This change isn't as much of a simplification as I was hoping when I wrote the TODO suggesting it, but it's good to remove this one Chain::Lock usage, just as a prerequisite for removing the entire Chain::Lock interface later.

One more suggestion would be to add GUARDED_BY(cs_wallet) annotation to:

uint256 m_last_block_processed;

because after this PR, accesses are now guarded by cs_wallet instead of cs_main.

Add GUARDED_BY(cs_wallet) annotation to m_last_block_processed, given
that its now guarded by cs_wallet instead of cs_main
@ariard ariard force-pushed the 2019-04-is-potential-tip branch from 57007b8 to 4226779 Compare April 23, 2019 18:08
@ariard
Copy link
Author

ariard commented Apr 23, 2019

Updated at 4226779 with GUARDED_BY annotation addition.

(btw @ryanofsky, I've started to work on removing bits of Chain::Lock interface, notably the GetDepthInMainChain by tracking last_block_processed_height in CWallet, hope to PR soon to get feedback)

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

utACK 4226779. Only change is adding the cs_wallet lock annotation.

I'm glad to hear you're working on removing cs_main locking from GetDepthInMainChain. This should improve performance and allow removing locked_chain variables from a swath of wallet code. I think it'll require adding something like a map from block hash to height for CMerkleTx::hashBlock blocks, but there could be other approaches.

@ariard
Copy link
Author

ariard commented Apr 24, 2019

Maybe hold on a bit on this.

While working on removing cs_main locking, it appears to me than, given wallet will be tracking chain height thanks to asynchronous updates and not direct chain state queries, it's needed to SyncWithValidationInterfaceQueue before each take of cs_wallet lock even if wallet is at the tip, because we may have BlockDisconnected in the callbacks validation interface queue and so it may cause races between RPC calls (at least spotted one thanks to mempool_resurrect)

And yes doing remove by adding m_last_block_processed_height in both CWallet and m_block_height in CMerkleTx

@ryanofsky
Copy link
Contributor

I don't think I understand the need to call SyncWithValidationInterfaceQueue unconditionally in the other PR, but even if there's no way around it, this PR doesn't prevent that because it's still possible to call waitForNotificationsIfNewBlocksConnected({})

@ariard
Copy link
Author

ariard commented Apr 24, 2019

Ah get your point, I'm going to far in locking removing (at least for now), was trying to not rely at all on Chain locking, even without '''::chainActive.Tip()->GetBlockHash()''' call, but only on callbacks hinting chain state.

@jnewbery
Copy link
Contributor

ACK 4226779

maflcko pushed a commit to maflcko/bitcoin-core that referenced this pull request May 1, 2019
…tions by higher method

4226779 refactor: replace isPotentialtip/waitForNotifications by higher method (Antoine Riard)
edfe943 Add WITH_LOCK macro: run code while locking a mutex (Antoine Riard)

Pull request description:

  In Chain interface, instead of a isPotentialTip and a WaitForNotifications method, both used only once in CWallet::BlockUntilSyncedToCurrentChain, combine them in a higher WaitForNotificationsUpToTip method. Semantic should be unchanged, wallet wait for pending notifications to be processed unless block hash points to the current chain tip or a descendant.

ACKs for commit 422677:
  jnewbery:
    ACK 4226779
  ryanofsky:
    utACK 4226779. Only change is adding the cs_wallet lock annotation.

Tree-SHA512: 2834ff0218795ef607543fae822e5cce25d759c1a9cfcb1f896a4af03071faed5276fbe0966e0c6ed65dc0e88af161899c5b2ca358a2d24fe70969a550000bf2
@maflcko maflcko merged commit 4226779 into bitcoin:master May 1, 2019
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request May 1, 2019
deadalnix pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request May 27, 2020
…s by higher method

Summary:
Add GUARDED_BY(cs_wallet) annotation to m_last_block_processed, given
that its now guarded by cs_wallet instead of cs_main
bitcoin/bitcoin@4226779

---

Add WITH_LOCK macro: run code while locking a mutex
Results from ryanofksy suggestion on isPotentialTip/
waitForNotifications refactoring
bitcoin/bitcoin@edfe943

---

Depends on D6258

Backport of Core [[bitcoin/bitcoin#15842 | PR15842]]

Test Plan:
  ninja check-all

Reviewers: #bitcoin_abc, deadalnix

Reviewed By: #bitcoin_abc, deadalnix

Differential Revision: https://reviews.bitcoinabc.org/D6260
kwvg added a commit to kwvg/dash that referenced this pull request Jun 5, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 6, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 6, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 7, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 8, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 9, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 10, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 11, 2021
UdjinM6 added a commit to dashpay/dash that referenced this pull request Jun 26, 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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants