wallet: [bugfix] Mark CNoDestination and PubKeyDestination constructor explicit #28728

pull maflcko wants to merge 2 commits into bitcoin:master from maflcko:2310-explicit-CNoDestination- changing 7 files +26 −19
  1. maflcko commented at 11:25 am on October 25, 2023: member

    It seems confusing to allow any script, even one with a corresponding address, to silently convert to CNoDestination.

    Make the converstion explicit in the code, and fix any bugs that were previously introduced.

    In a follow-up, the class can be renamed, or the documentation can be updated to better reflect what the code does.

  2. iwyu: Export prevector.h from script.h
    This should cut some include bloat and seems fine to do, because
    prevector exists primarily to represent scripts.
    
    Also, add missing includes to script.h and addresstype.h
    fa5ccc4137
  3. DrahtBot commented at 11:25 am on October 25, 2023: contributor

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

    Code Coverage

    For detailed information about the code coverage, see the test coverage report.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK josibake, furszy, achow101

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #28690 (build: Introduce internal kernel library by TheCharlatan)
    • #28550 (Covenant tools softfork by jamesob)
    • #28400 (Make provably unsignable standard P2PK and P2MS outpoints unspendable. by russeree)

    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.

  4. DrahtBot renamed this:
    refactor: Mark CNoDestination constructor explicit
    refactor: Mark CNoDestination constructor explicit
    on Oct 25, 2023
  5. DrahtBot added the label Refactoring on Oct 25, 2023
  6. maflcko force-pushed on Oct 25, 2023
  7. DrahtBot added the label CI failed on Oct 25, 2023
  8. maflcko renamed this:
    refactor: Mark CNoDestination constructor explicit
    bugfix: Mark CNoDestination constructor explicit
    on Oct 25, 2023
  9. in src/qt/walletmodel.cpp:191 in fa5f1f054d outdated
    187@@ -188,7 +188,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
    188             ++nAddresses;
    189 
    190             CScript scriptPubKey = GetScriptForDestination(DecodeDestination(rcp.address.toStdString()));
    191-            CRecipient recipient = {scriptPubKey, rcp.amount, rcp.fSubtractFeeFromAmount};
    192+            CRecipient recipient{CNoDestination{scriptPubKey}, rcp.amount, rcp.fSubtractFeeFromAmount};
    


    furszy commented at 12:46 pm on October 25, 2023:

    We know the destination here. Otherwise we wouldn’t be able to decode it from the string (the validateAddress() check that is performed above would fail). This should be:

    0CTxDestination dest = DecodeDestination(rcp.address.toStdString());
    1CRecipient recipient = {dest, rcp.amount, rcp.fSubtractFeeFromAmount};
    

    This fixes #28246 (review).


    maflcko commented at 1:01 pm on October 25, 2023:
    Jup, already had this, but forgot to push my local commit :sweat_smile:
  10. furszy commented at 12:48 pm on October 25, 2023: member
    Nice catch
  11. in src/wallet/test/spend_tests.cpp:81 in fa5f1f054d outdated
    77@@ -78,7 +78,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_duplicated_preset_inputs_test, TestChain100Setup)
    78 
    79     // Try to create a tx that spends more than what preset inputs + wallet selected inputs are covering for.
    80     // The wallet can cover up to 200 BTC, and the tx target is 299 BTC.
    81-    std::vector<CRecipient> recipients = {{GetScriptForDestination(*Assert(wallet->GetNewDestination(OutputType::BECH32, "dummy"))),
    82+    std::vector<CRecipient> recipients{{CNoDestination{GetScriptForDestination(*Assert(wallet->GetNewDestination(OutputType::BECH32, "dummy")))},
    


    furszy commented at 12:59 pm on October 25, 2023:

    ~Same as above, can just pass GetScriptForDestination return value without passing through GetScriptForDestination. The destination was created by the wallet, thus is already known.~

    You already fixed it.

  12. maflcko force-pushed on Oct 25, 2023
  13. maflcko removed the label Refactoring on Oct 25, 2023
  14. maflcko renamed this:
    bugfix: Mark CNoDestination constructor explicit
    wallet: [bugfix] Mark CNoDestination constructor explicit
    on Oct 25, 2023
  15. in src/qt/walletmodel.cpp:190 in fa7184cff5 outdated
    186@@ -187,8 +187,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
    187             setAddress.insert(rcp.address);
    188             ++nAddresses;
    189 
    190-            CScript scriptPubKey = GetScriptForDestination(DecodeDestination(rcp.address.toStdString()));
    191-            CRecipient recipient = {scriptPubKey, rcp.amount, rcp.fSubtractFeeFromAmount};
    192+            CRecipient recipient{DecodeDestination(rcp.address.toStdString()), rcp.amount, rcp.fSubtractFeeFromAmount};
    


    josibake commented at 2:12 pm on October 25, 2023:

    To check my understanding:

    The bug was introduced by not updating this line in #28246 to use the CTxDestination returned by DecodeDestination directly in the CRecipient object. Instead, it was converting to a CScript and silently converting to a CNoDestination, since CRecipient now expects a CTxDestination. So if we had marked the CNoDestination constructor as explicit, the compiler would have warned us here.

    I changed it back to try and use the CScript directly in the CRecipient and confirmed I got a compiler warning:

    0qt/walletmodel.cpp:192:34: error: could not convert spk from const CScript to CTxDestination
    

    maflcko commented at 2:28 pm on October 25, 2023:
    Yes, sounds correct.
  16. josibake approved
  17. josibake commented at 2:19 pm on October 25, 2023: member

    tACK https://github.com/bitcoin/bitcoin/commit/fa7184cff5e03e7f5a54f616630f181737093ebf

    Good catch! Reviewed the code and tested and it looks good. There is a typo in the https://github.com/bitcoin/bitcoin/commit/fa7184cff5e03e7f5a54f616630f181737093ebf commit message (destiantion -> destination) and a typo in the description (Make the confusion -> Make the conversion). Not a big deal, but happy to re-ack if you end up re-pushing to fix the commit message typo.

  18. maflcko commented at 2:29 pm on October 25, 2023: member
    Thanks, fixed the typo in the pull request description.
  19. achow101 added the label Needs backport (26.x) on Oct 25, 2023
  20. achow101 added this to the milestone 26.0 on Oct 25, 2023
  21. in src/bench/wallet_create_tx.cpp:103 in fa7184cff5 outdated
    100     // Generate chain; each coinbase will have two outputs to fill-up the wallet
    101     const auto& params = Params();
    102     unsigned int chain_size = 5000; // 5k blocks means 10k UTXO for the wallet (minus 200 due COINBASE_MATURITY)
    103     for (unsigned int i = 0; i < chain_size; ++i) {
    104-        generateFakeBlock(params, test_setup->m_node, wallet, dest);
    105+        generateFakeBlock(params, test_setup->m_node, wallet, GetScriptForDestination(dest));
    


    furszy commented at 7:59 pm on October 25, 2023:
    This will call GetScriptForDestination() 5000 times when dest is constant. Why not leaving GetScriptForDestination where it was before?

    maflcko commented at 8:27 pm on October 25, 2023:
    It wouldn’t compile if this file was not touched. For reference, you can also see the refactor-transformation of the same commit https://github.com/bitcoin/bitcoin/commit/fa5f1f054d7daf2d295b44786b61868aad89898b#diff-e9fe86a6cb5a18f8bf472c45e9d02cca8aea5dac8e3d2a0b81ce25a734458139

    furszy commented at 8:37 pm on October 25, 2023:

    Yeah, needs another variable:

     0diff --git a/src/bench/wallet_create_tx.cpp b/src/bench/wallet_create_tx.cpp
     1--- a/src/bench/wallet_create_tx.cpp	(revision d53400e75e2a4573229dba7f1a0da88eb936811c)
     2+++ b/src/bench/wallet_create_tx.cpp	(date 1698266114002)
     3@@ -94,13 +94,14 @@
     4     }
     5 
     6     // Generate destinations
     7-    CScript dest = GetScriptForDestination(getNewDestination(wallet, output_type));
     8+    CTxDestination dest{getNewDestination(wallet, output_type)};
     9+    CScript out_script{GetScriptForDestination(dest)};
    10 
    11     // Generate chain; each coinbase will have two outputs to fill-up the wallet
    12     const auto& params = Params();
    13     unsigned int chain_size = 5000; // 5k blocks means 10k UTXO for the wallet (minus 200 due COINBASE_MATURITY)
    14     for (unsigned int i = 0; i < chain_size; ++i) {
    15-        generateFakeBlock(params, test_setup->m_node, wallet, dest);
    16+        generateFakeBlock(params, test_setup->m_node, wallet, out_script);
    17     }
    18 
    19     // Check available balance
    

    maflcko commented at 8:49 pm on October 25, 2023:

    I don’t think it matters, because generateFakeBlock is likely more expensive than shuffling a few bytes.

    Either way, done in the last push.

  22. in src/wallet/test/wallet_tests.cpp:608 in fa7184cff5 outdated
    604@@ -605,7 +605,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoinsTest, ListCoinsTestingSetup)
    605     // returns the coin associated with the change address underneath the
    606     // coinbaseKey pubkey, even though the change address has a different
    607     // pubkey.
    608-    AddTx(CRecipient{GetScriptForRawPubKey({}), 1 * COIN, /*subtract_fee=*/false});
    609+    AddTx(CRecipient{CPubKey{}, 1 * COIN, /*subtract_fee=*/false});
    


    furszy commented at 8:10 pm on October 25, 2023:

    Not for this PR but based on this recent not so good experience, I think we should make all destinations constructors explicit.

    Here, we are providing a CPubKey to implicitly construct a PubKeyDestination, which is not very intuitive. There is a PKHash constructor (the CTxDestination type of a p2pkh) that also accepts a CPubKey as argument.


    maflcko commented at 8:50 pm on October 25, 2023:
    Thanks, done in the last push. I missed that CPubKey was also ambiguous.
  23. furszy commented at 8:18 pm on October 25, 2023: member
    Aside from the two comments, do you think that mixing the bug fix with some code styling improvements and the iwyu commit is really desirable? I know that those are small, good and easy reviewable changes but.. it might be better for backporting and historical context to leave this PR only with the bug fix.
  24. maflcko renamed this:
    wallet: [bugfix] Mark CNoDestination constructor explicit
    wallet: [bugfix] Mark CNoDestination and PubKeyDestination constructor explicit
    on Oct 25, 2023
  25. bugfix: Mark CNoDestination and PubKeyDestination constructor explicit
    This should fix the bug reported in
    https://github.com/bitcoin/bitcoin/pull/28246#discussion_r1371640502,
    which caused the GUI to not detect the destination type of recipients,
    thus picking the wrong change destination type.
    
    Also, add missing lifetimebound attribute to a getter method.
    1111475b41
  26. maflcko force-pushed on Oct 25, 2023
  27. maflcko commented at 8:53 pm on October 25, 2023: member

    iwyu commit is really desirable?

    Missing includes have been a source for compile failures in the past. Though, I couldn’t care less whether it is backported or not. I think it is up to the person doing the backport to decide what commits to backport, if any at all.

  28. DrahtBot removed the label CI failed on Oct 25, 2023
  29. josibake commented at 10:20 am on October 26, 2023: member

    ACK https://github.com/bitcoin/bitcoin/commit/1111475b41698260cda0f25a96c051fd18d66129

    Nice to see changing PubKeyDestination to explicit didn’t surface any surprises.

  30. furszy commented at 1:33 pm on October 26, 2023: member

    Missing includes have been a source for compile failures in the past.

    Hard to disagree with it.

    Though, I couldn’t care less whether it is backported or not. I think it is up to the person doing the backport to decide what commits to backport, if any at all.

    This PR is simple enough. I just would have preferred to not add the code styling fixes within the bugfix commit, even when they are tempting small things to tackle.

    About the conceptual discussion In general, I believe we all care about not releasing a new version with broken code. And, we can support this goal by making any post-branch-off pre-release bugfix as simple as possible.

  31. furszy commented at 1:35 pm on October 26, 2023: member
    Code review ACK 1111475
  32. maflcko commented at 1:51 pm on October 26, 2023: member

    I just would have preferred to not add the code styling fixes within the bugfix commit, even when they are tempting small things to tackle.

    If you are referring to the missing newline at the end of the file, this is not something I do on purpose. This is done automatically by most vanilla editors when saving the file. A missing trailing newline will cause problems with those editors and git, so I think it makes sense to add a linter for this to prevent people from adding such a file in the first place?

  33. achow101 commented at 2:56 pm on October 26, 2023: member
    ACK 1111475b41698260cda0f25a96c051fd18d66129
  34. furszy commented at 2:58 pm on October 26, 2023: member

    I just would have preferred to not add the code styling fixes within the bugfix commit, even when they are tempting small things to tackle.

    If you are referring to the missing newline at the end of the file, this is not something I do on purpose. This is done automatically by most vanilla editors when saving the file. A missing trailing newline will cause problems with those editors and git, so I think it makes sense to add a linter for this to prevent people from adding such a file in the first place?

    yeah, that would be nice.

  35. achow101 merged this on Oct 26, 2023
  36. achow101 closed this on Oct 26, 2023

  37. maflcko deleted the branch on Oct 26, 2023
  38. maflcko commented at 3:33 pm on October 26, 2023: member

    Unrelated from this bugfix, I also wondered if there should be a “true” “no destiantion” type. Currently, a non-standard empty script is mapped to the same value like a default constructed CNoDestination{}.

    I guess this is fine, but if in the future there is a need to have a “real null”, CNoDestination can be renamed to mean “non-standard”. That is:

     09e5f699969f85a31e229cf89558f2bc59b64e8df
     1    scripted-diff: Rename CNoDestination to NonStandardDestination
     2    
     3    Generally it is a good idea to change the name of a class when the
     4    meaning of the class changes. This ensures that a compilation failure
     5    will be emitted when a developer uses the old name (and meaning) of the
     6    class.
     7    
     8    Since CNoDestination changed its meaning from "holding no destination"
     9    to "holding a nonstandard destination", rename it to that.
    10    
    11    -BEGIN VERIFY SCRIPT-
    12     sed -i 's/CNoDestination/NonStandardDestination/g' $( git grep -l CNoDestination )
    13    -END VERIFY SCRIPT-
    
  39. achow101 commented at 3:35 pm on October 26, 2023: member

    Unrelated from this bugfix, I also wondered if there should be a “true” “no destiantion” type. Currently, a non-standard empty script is mapped to the same value like a default constructed CNoDestination{}.

    I don’t think it is all that useful to have an actual “no destination”. It could easily be served by using a std::optional<CTxDestination>. I’ve got an unfinished branch that does that.

  40. jarolrod commented at 2:57 am on October 27, 2023: member
    post merge ack
  41. fanquake referenced this in commit 6772a62721 on Oct 30, 2023
  42. fanquake removed the label Needs backport (26.x) on Oct 30, 2023
  43. DrahtBot added the label Wallet on Oct 30, 2023
  44. fanquake commented at 1:25 pm on October 30, 2023: member
    Backported in #28754.

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-09-28 22:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me