8000 wallet: avoid double keypool TopUp() call on descriptor wallets by furszy · Pull Request #25526 · bitcoin/bitcoin · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

wallet: avoid double keypool TopUp() call on descriptor wallets #25526

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

Merged
merged 3 commits into from
Oct 13, 2022

Conversation

furszy
Copy link
Member
@furszy furszy commented Jul 1, 2022

Found it while was digging over a getnewaddress timeout on the functional test suite.

Context:

We are calling TopUp() twice in the following flows for descriptor wallets:

A) CWallet::GetNewDestination:

  1. Calls spk_man->TopUp()
  2. Calls spk_man->GetNewDestination() --> which, after the basic script checks, calls TopUp() again.

B) CWallet::GetReservedDestination:

  1. Calls spk_man->TopUp()
  2. Calls spk_man->GetReservedDestination() --> which calls to GetNewDestination (which calls to TopUp again).

Changes:

Move TopUp() responsibility from the wallet class to each scriptpubkeyman.
So each spkm can decide to call it or not after perform the basic checks
for the new destination request.

Aside from that, remove the unused nAccountingEntryNumber wallet field. And a duplicated descriptor type check in GetNewDestination

@DrahtBot DrahtBot added the Wallet label Jul 1, 2022
@DrahtBot
Copy link
Contributor
DrahtBot commented Jul 1, 2022

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

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #25881 (wallet: remove unused DummySignTx and CKeyPool from GetReservedDestination by furszy)
  • #24897 ([Draft / POC] Silent Payments by w0xlt)

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.

Copy link
Contributor
@aureleoules aureleoules left a comment

Choose a reason for hiding this comment

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

ACK 616a54b.
Looks good!
I verified that TopUp calls and type checking are not duplicated anymore.

Side note, can't these two be merged in a single if?

if (m_wallet_descriptor.range_end <= m_max_cached_index && !TopUp(1)) {
// We can't generate anymore keys
error = _("Error: Keypool ran out, please call keypoolrefill first");
return false;
}
if (!m_wallet_descriptor.descriptor->ExpandFromCache(m_wallet_descriptor.next_index, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
// We can't generate anymore keys
error = _("Error: Keypool ran out, please call keypoolrefill first");
return false;
}

Copy link
Contributor
@w0xlt w0xlt left a comment

Choose a reason for hiding this comment

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

ACK 616a54b

It is better that only one base class (ScriptPubKeyMan) has the responsibility of calling TopUp().

@furszy furszy force-pushed the 2022_wallet_remove_extra_topup branch from 616a54b to cba0cb9 Compare July 14, 2022 19:46
@furszy
Copy link
Member Author
furszy commented Jul 14, 2022

Thanks for the feedback!

Rebased on master, conflict solved. Ready to go.


ACK 616a54b. Looks good! I verified that TopUp calls and type checking are not duplicated anymore.

Side note, can't these two be merged in a single if?

Good eye @aureleoules.
Actually, the second error message isn't accurate, ExpandFromCache can only fail if the derivation fails or due some internal failure like a not matching xpub.

furszy added 3 commits August 12, 2022 12:36
Move TopUp() responsibility from the wallet class to each scriptpubkeyman.
So each spkm can decide to call it or not after perform the basic checks
for the new destination request.

Reason:

We were calling it twice in the following flows for descriptor wallets:

A) CWallet::GetNewDestination:
   1) Calls spk_man->TopUp()
   2) Calls spk_man->GetNewDestination() --> which, after the basic script checks, calls TopUp() again.

B) CWallet::GetReservedDestination:
   1) Calls spk_man->TopUp()
   2) Calls spk_man->GetReservedDestination() --> which calls to GetNewDestination (which calls to TopUp again).
@furszy furszy force-pushed the 2022_wallet_remove_extra_topup branch from cba0cb9 to bfb9b94 Compare August 12, 2022 15:47
@furszy
Copy link
Member Author
furszy commented Aug 12, 2022

rebased, conflicts solved.

@furszy furszy changed the title wallet: avoid double keypool TopUp() calls on descriptor wallets wallet: avoid double keypool TopUp() call on descriptor wallets Aug 16, 2022
@aureleoules
Copy link
Contributor

re-ACK bfb9b94.

Copy link
Contributor
@theStack theStack left a comment

Choose a reason for hiding this comment

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

Code-review ACK bfb9b94

} else {
throw std::runtime_error(std::string(__func__) + ": Types are inconsistent. Stored type does not match type of newly generated address");
if (!ExtractDestination(scripts_temp[0], dest)) {
return util::Error{_("Error: Cannot extract destination from the generated scriptpubkey")}; // shouldn't happen
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: To be consistent with other internal errors that should never happen (e.g. "types are inconsistent" above), could also throw std::runtime_error here:

Suggested change
return util::Error{_("Error: Cannot extract destination from the generated scriptpubkey")}; // shouldn't happen
throw std::runtime_error(std::string(__func__) + "Cannot extract destination from the generated scriptpubkey"); // shouldn't happen

Copy link
Member Author
@furszy furszy Sep 19, 2022

Choose a reason for hiding this comment

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

Did this change on purpose:
As we are not catching the runtime error at the GUI level. If this happens, the process will crash abruptly. No message, nor error description for the user.

With this change, the user will (1) receive the proper error message on a dialog, and (2) be able to continue using the node and wallet (up to a certain point).
Plus, sometimes abrupt shutdowns can corrupt the db. So, safer to not crash abruptly if can be avoided.

Copy link
Contributor

Choose a reason for hiding this comment

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

Following that logic, we should either

  • get rid of literally all runtime error throws that could happen in the GUI (alone in ./src/wallet there are 75 instances of those, according to $ git grep "throw std::runtime_error" ./src/wallet | wc -l), or
  • simply catch runtime errors in the GUI, with a clear error message with dialog to the user and a clean shutdown to avoid db corruption

The second option seems to be the more obvious solution to me, rather than avoiding std::runtime_error (which seems a perfect candidate for internal errors that should never happen) at all.
(Of course, this is potential material for follow-ups and not directly related to this PR)

@achow101
Copy link
Member

ACK bfb9b94

@achow101 achow101 merged commit 1dec90d into bitcoin:master Oct 13, 2022
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Oct 23, 2022
…criptor wallets

bfb9b94 wallet: remove duplicate descriptor type check in GetNewDestination (furszy)
76b982a wallet: remove unused `nAccountingEntryNumber` field (furszy)
599ff5a wallet: avoid double TopUp() calls on descriptor wallets (furszy)

Pull request description:

  Found it while was digging over a `getnewaddress` timeout on the functional test suite.

  ### Context:

  We are calling `TopUp()` twice in the following flows for descriptor wallets:

  A) `CWallet::GetNewDestination`:
     1) Calls spk_man->TopUp()
     2) Calls spk_man->GetNewDestination() --> which, after the basic script checks, calls TopUp() again.

  B) `CWallet::GetReservedDestination`:
     1) Calls spk_man->TopUp()
     2) Calls spk_man->GetReservedDestination() --> which calls to GetNewDestination (which calls to TopUp again).

  ### Changes:

  Move `TopUp()` responsibility from the wallet class to each scriptpubkeyman.
  So each spkm can decide to call it or not after perform the basic checks
  for the new destination request.

  Aside from that, remove the unused `nAccountingEntryNumber` wallet field. And a duplicated descriptor type check in `GetNewDestination`

ACKs for top commit:
  aureleoules:
    re-ACK bfb9b94.
  achow101:
    ACK bfb9b94
  theStack:
    Code-review ACK bfb9b94

Tree-SHA512: 3ab73f37729e50d6c6a4434f676855bc1fb404619d63c03e5b06ce61c292c09c59d64cb1aa3bd9277b06f26988956991d62c90f9d835884f41ed500b43a12058
@furszy furszy deleted the 2022_wallet_remove_extra_topup branch May 27, 2023 01:49
@bitcoin bitcoin locked and limited conversation to collaborators May 26, 2024
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.

6 participants
0