Silent Payments: Sending (take 2) #35302

pull Eunovo wants to merge 20 commits into bitcoin:master from Eunovo:implement-bip352-sending changing 70 files +22044 −150
  1. Eunovo commented at 4:16 AM on May 16, 2026: contributor

    This PR is part of integrating silent payments into Bitcoin Core. It is the second iteration of #28201. Status and tracking for the project is managed in #28536

    Prerequisite PRs:

    Sending

    Silent Payments logic The main focus of this PR is:

    • Applying the Taptweak to a taproot internal private key (this is a copy-paste of the code for applying the taptweak in the signing process)
    • Getting a private key from a given scriptPubKey
    • Creating silent payment outputs
    • Applying the created scriptPubKeys back to the vector of CRecipients
    • The functions are then used together to create silent payment outputs during CreateTransactionInternal.
    • The change output type is correctly chosen when paying to a silent payment address
    • RBF for silent payments transactions are handled correctly
    • Functional tests
  2. DrahtBot commented at 4:16 AM on May 16, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/35302.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK rkrux

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #bitcoin-core/gui/700 (Dialog for allowing the user to choose the change output when bumping a tx by achow101)
    • #35587 (Remove boost as a unit test runner by rustaceanrob)
    • #35569 (Encapsulation for CTransaction by purpleKarrot)
    • #35511 (RFC: consensus: Make CAmount a class by hodlinator)
    • #35501 (wallet: store all witness variants of a transaction by achow101)
    • #35444 (wallet: make descriptor SPKM mutex non-recursive by w0xlt)
    • #35433 (wallet: deprecate replaceable argument from transaction (and psbt) creation (and modification) RPCs by rkrux)
    • #35317 (wallet: fix ignored subtract_fee_from_outputs option by stutxo)
    • #34697 (descriptor: fix musig duplicate checks and origin handling by shuv-amp)
    • #34405 (wallet: skip APS when no partial spend exists by 8144225309)
    • #33034 (wallet: Store transactions in a separate sqlite table by achow101)
    • #32763 (wallet: Replace CWalletTx::mapValue and vOrderForm with explicit class members by achow101)
    • #27865 (wallet: Track no-longer-spendable TXOs separately by achow101)
    • #27260 (Enhanced error messages for invalid network prefix during address parsing. by portlandhodl)

    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.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  3. rkrux commented at 9:11 AM on May 20, 2026: contributor

    Concept ACK 03c835d

  4. in src/wallet/scriptpubkeyman.cpp:1484 in f9a10e9ea9
    1476 | @@ -1477,6 +1477,30 @@ bool DescriptorScriptPubKeyMan::AddCryptedKey(const CKeyID& key_id, const CPubKe
    1477 |      return true;
    1478 |  }
    1479 |  
    1480 | +Key DescriptorScriptPubKeyMan::GetPrivKeyForSilentPayment(const CScript& scriptPubKey) const
    1481 | +{
    1482 | +    std::vector<std::vector<unsigned char>> solutions;
    1483 | +    TxoutType whichType = Solver(scriptPubKey, solutions);
    1484 | +    if (whichType == TxoutType::NONSTANDARD || whichType == TxoutType::MULTISIG || whichType == TxoutType::WITNESS_UNKNOWN ) return {};
    


    theStack commented at 1:21 AM on May 23, 2026:

    in f9a10e9ea9b57f6b21a6dbfd1239c3ba60f721f8: I think it would be more robust to express this condition using the explicit list of relevant output script types as specified in the BIP, i.e. return early if whichType is not any of P2TR, P2WPKH, P2SH-P2WPKH or P2PKH. Otherwise, the condition has to be extended whenever the TxoutType enum class gets extended (e.g. P2A has been added since and is not there in the condition).


    Eunovo commented at 11:07 AM on June 7, 2026:

    Done.

  5. in src/wallet/scriptpubkeyman.cpp:1488 in f9a10e9ea9
    1483 | +    TxoutType whichType = Solver(scriptPubKey, solutions);
    1484 | +    if (whichType == TxoutType::NONSTANDARD || whichType == TxoutType::MULTISIG || whichType == TxoutType::WITNESS_UNKNOWN ) return {};
    1485 | +    std::unique_ptr<FlatSigningProvider> coin_keys = GetSigningProvider(scriptPubKey, true);
    1486 | +    if (!coin_keys || coin_keys->keys.size() != 1) return {};
    1487 | +    const auto& [_, key] = *coin_keys->keys.begin();
    1488 | +    (void) _;
    


    theStack commented at 1:34 AM on May 23, 2026:

    f9a10e9ea9b57f6b21a6dbfd1239c3ba60f721f8: nit: is this line needed? Not sure what the exact rules in C++ are about the single underscore identifier, but I haven't seen this fake-use pattern (probably with the intention to avoid warnings) in other similar places where we use it.


    Eunovo commented at 11:07 AM on June 7, 2026:

    Removed.

  6. in src/wallet/rpc/spend.cpp:436 in e3ef349ad5
     432 | @@ -420,6 +433,11 @@ RPCMethod sendmany()
     433 |              ParseOutputs(sendTo),
     434 |              InterpretSubtractFeeFromOutputInstructions(request.params[4], sendTo.getKeys())
     435 |      );
     436 | +    auto it = std::find_if(recipients.begin(), recipients.end(), [](const auto& r) { return std::holds_alternative<V0SilentPaymentDestination>(r.dest); });
    


    theStack commented at 1:41 AM on May 23, 2026:

    in e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd: could slightly simplify by using std::any_of instead (returns a bool instead of an iterator)


    Eunovo commented at 11:08 AM on June 7, 2026:

    Done.

  7. in src/wallet/rpc/spend.cpp:1280 in e3ef349ad5
    1294 |              outputs = NormalizeOutputs(request.params[0]);
    1295 |              std::vector<CRecipient> recipients = CreateRecipients(
    1296 |                      ParseOutputs(outputs),
    1297 |                      InterpretSubtractFeeFromOutputInstructions(options["subtract_fee_from_outputs"], outputs.getKeys())
    1298 |              );
    1299 | -            CCoinControl coin_control;
    


    theStack commented at 1:42 AM on May 23, 2026:

    in e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd: any reason why the coin_control instance got moved up?


    Eunovo commented at 11:08 AM on June 7, 2026:

    Reverted.

  8. in src/wallet/rpc/spend.cpp:171 in e3ef349ad5
     167 | @@ -168,6 +168,14 @@ static void PreventOutdatedOptions(const UniValue& options)
     168 |      }
     169 |  }
     170 |  
     171 | +static void IsSilentPaymentsEnabled(const CWallet &pwallet)
    


    theStack commented at 1:45 AM on May 23, 2026:

    in e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd: for functions starting with Is, I'd usually expect to return a boolean value. maybe rename with using Ensure as a prefix instead?


    Eunovo commented at 11:08 AM on June 7, 2026:

    Done.

  9. Eunovo commented at 11:45 AM on May 25, 2026: contributor

    @theStack I'll attend to your reviews when I rebase on https://github.com/bitcoin/bitcoin/pull/35301

  10. DrahtBot added the label Needs rebase on May 28, 2026
  11. Eunovo force-pushed on Jun 7, 2026
  12. Eunovo force-pushed on Jun 7, 2026
  13. DrahtBot added the label CI failed on Jun 7, 2026
  14. DrahtBot commented at 11:15 AM on June 7, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task lint: https://github.com/bitcoin/bitcoin/actions/runs/27090770600/job/79953877713</sub> <sub>LLM reason (✨ experimental): (empty)</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  15. DrahtBot removed the label Needs rebase on Jun 7, 2026
  16. Eunovo force-pushed on Jun 7, 2026
  17. Eunovo force-pushed on Jun 8, 2026
  18. Eunovo force-pushed on Jun 8, 2026
  19. DrahtBot removed the label CI failed on Jun 8, 2026
  20. DrahtBot added the label Needs rebase on Jun 12, 2026
  21. Squashed 'src/secp256k1/' changes from bd0287d650..eef27eb07e
    eef27eb07e silentpayments: skip slow benchmarks for low iters count (<= 2)
    53c37e4f4c docs: update README
    93a1170501 ci: enable silentpayments module
    ab849cf045 tests: add sha256 tag test
    15ee7158ee tests: add constant time tests
    da3ca4bdcb tests: add BIP-352 test vectors
    e2ead23724 silentpayments: optimize scanning by using batch inversion
    0655c15024 silentpayments: add benchmarks for scanning
    e62f412878 silentpayments: add examples/silentpayments.c
    7493c37b9f silentpayments: respect per-group recipients protocol limit (K_max=2323)
    5f90295d56 silentpayments: receiving
    9a55346925 silentpayments: recipient label support
    b97aafd655 silentpayments: sending
    8fe6ab62a2 build: add skeleton for new silentpayments (BIP352) module
    
    git-subtree-dir: src/secp256k1
    git-subtree-split: eef27eb07e6537e559d5dc4c9c98923bfc267766
    57cdd439eb
  22. Merge commit '57cdd439eb0f4860ae6d00466fc08a83b047f504' into sp-base 8f5b28a4c2
  23. crypto: add read-only method to KeyPair
    Add a method for passing a KeyPair object to secp256k1 functions expecting a secp256k1_keypair.
    This allows for passing a KeyPair directly to a secp256k1 function without needing to create a
    temporary secp256k1_keypair object.
    c107ec629a
  24. Add "sp" HRP 3fa1c29f51
  25. Add Silent Payments address types
    Add V0SilentPaymentsDestination and UnknownSilentPaymentsDestination
    for v1 to v30; Bip352 reserves v31 for a backwards incompatible change.
    v1 to v30 addresses are handled as specified in Bip352. The extra_data
    will be ignored during sending.
    
    Valid v0 and v1 addresses were added to key_io_valid.json for testing,
    and invalid v0 and a v31 address were added to key_io_invalid.json.
    
    V0SilentPaymentsDestination must not be formed from invalid public keys;
    the operations that must be performed to send to a V0SilentPaymentsDestination,
    require valid public keys. Hence, the V0SilentPaymentsDestination struct takes
    the following precautions to ensure that such invalid states are not possible:
    - The constructor will throw when provided with invalid public keys
    - The public keys are private and const references can be retrieved using member functions.
    a4771f7651
  26. Eunovo force-pushed on Jun 23, 2026
  27. DrahtBot added the label CI failed on Jun 23, 2026
  28. DrahtBot removed the label Needs rebase on Jun 23, 2026
  29. Eunovo force-pushed on Jun 24, 2026
  30. in test/functional/wallet_silentpayments_sending.py:323 in 989d3548c6
     318 | +            expected_error_fund=(-4, "No silent payment eligible inputs were found."),
     319 | +        )
     320 | +
     321 | +    def test_address_reuse(self):
     322 | +        self.log.info("Testing that two sends to the same SP address produce distinct outputs")
     323 | +        self.nodes[0].createwallet(wallet_name="address_reuse_sender", descriptors=True)
    


    rkrux commented at 1:41 PM on June 24, 2026:

    In 989d3548c6933a4bc31b82a6f950029440e1d232 "tests: add sending functional tests"

    descriptors=True

    Please remove all occurrences of this createwallet argument, it's not required post disallowing loading legacy wallets.

    I see a new SP specific wallet flag is introduced in the SP receiving PR #32966. I have not checked the implementation yet but from a pure functionality POV, the addition of that new wallet flag should not necessitate the passing of the descriptors flag now (which I assume, in all likelihood, is not happening and thus this flag should be removed from the tests).


    Eunovo commented at 9:38 AM on June 26, 2026:

    Done

  31. in test/functional/wallet_silentpayments_sending.py:403 in 989d3548c6
     398 | +            assert txid not in node.getrawmempool()
     399 | +            self.generate(node, 1)
     400 | +            assert wallet.gettransaction(new_txid)["confirmations"] == 1
     401 | +
     402 | +        def send_psbt(w):
     403 | +            psbt = w.walletcreatefundedpsbt([], [{SP_ADDR_1: 5}], 0, {"replaceable": True})["psbt"]
    


    rkrux commented at 1:44 PM on June 24, 2026:

    In 989d354 "tests: add sending functional tests"

    "replaceable": True

    Please remove all occurrences of this in transaction/psbt creation/fund/send RPCs that are being used in this test. PR #35433 seeks to deprecate it (hopefully in the upcoming release) because of prevalence of fullrbf in the network and we shouldn't encourage the use of this argument in the functional tests.


    Eunovo commented at 9:38 AM on June 26, 2026:

    Done

  32. in test/functional/wallet_silentpayments_sending.py:426 in 989d3548c6 outdated
     421 | +        self.generate(node, 1)  # rbf_sendall funding UTXO now has 2 confs; extra UTXO has 1 conf
     422 | +
     423 | +        txid = wallet.sendall(recipients=[SP_ADDR_1], options={"replaceable": True, "maxconf": 1})["txid"]
     424 | +        assert txid in node.getrawmempool()
     425 | +        original_input_count = len(node.getrawtransaction(txid, True)["vin"])
     426 | +        result = wallet.bumpfee(txid, fee_rate=500)
    


    rkrux commented at 1:58 PM on June 24, 2026:

    In 989d354 "tests: add sending functional tests"

    https://github.com/bitcoin/bitcoin/blob/d84fc352cbc1363df5cd6024a22e73fc63283e4f/src/wallet/rpc/spend.cpp#L1003-L1006

    1. There's an outputs argument in the (psbt)bumpfee RPCs that allows to add new outputs in the replacing transaction. Please add a test case covering the behaviour when this argument is passed while replacing a silent payment transaction.
    2. Please also add a test case covering the scenario where the user is able to rbf-cancel the SP transaction by sending the funds to themselves.

    Eunovo commented at 9:38 AM on June 26, 2026:

    Added new tests for bumpfee with the outputs replaced.

  33. rkrux commented at 2:09 PM on June 24, 2026: contributor

    Reviewed only the last testing commit partially 989d354 "tests: add sending functional tests".

  34. DrahtBot removed the label CI failed on Jun 24, 2026
  35. common: add bip352.{h,cpp} secp256k1 module
    Wrap the silentpayments module from libsecp256k1. This is placed in
    common as it is intended to be used by:
    
      * RPCs: for parsing addresses
      * Wallet: for sending, receiving, spending silent payments outputs
      * Node: for creating silent payments indexes for light clients
    8de4f67123
  36. wallet: disable sending to silent payments address
    Have `IsValidDestination` return false for silent payments destinations
    and set an error string when decoding a silent payments address.
    
    This prevents anyone from sending to a silent payments address before
    sending is implemented in the wallet, but also allows the functions to
    be used in the unit testing famework.
    e860a4f748
  37. tests: add BIP352 test vectors as unit tests
    Use the test vectors to test sending and receiving. A few cases are not
    covered here, namely anything that requires testing specific to the
    wallet. For example:
    
    * Taproot script path spending is not tested, as that is better tested in
      a wallets coin selection / signing logic
    * Re-computing outputs during RBF is not tested, as that is better
      tested in a wallets RBF logic
    
    The unit tests are written in such a way that adding new test cases is
    as easy as updating the JSON file
    30f6396c7d
  38. wallet: get serialized size for `V0SilentPayments`
    BIP352 v0 specifies that a silent payment output is a taproot output.
    Taproot scriptPubKeys are a fixed size, so when calculating the
    serialized size for a CRecipient with a V0SilentPayments destination,
    use WitnessV1Taproot for the serialized txout size.
    d6b2e53a93
  39. wallet: add method for retreiving a private key
    Add a method for retreiving a private key for a given scriptPubKey.
    If the scriptPubKey is a taproot output, tweak the private key with the
    merkle root or hash of the public key, if applicable.
    94c037f417
  40. wallet: flag silent payments transactions
    Add a flag to the `CoinControl` object if silent payments destinations
    are provided. Before adding the flag, call a function which checks if:
    
    * The wallet has private keys
    * The wallet is unlocked
    
    Without both of the above being true, we cannot send to a silent payment
    address.
    
    During coin selection, if this flag is set, skip taproot inputs when
    script spend data is available. This is based on the assumption that if
    a user provides script spend data, they don't have access to the key
    path spend. As future improvement, we could instead check to see if we
    have access to the key path spend, and only exclude the output when we
    don't regardless of whether or not the user provides script spend data.
    
    Also skip UTXOs of type `WITNESS_UNKNOWN`, although it is very unlikely
    our wallet would ever try to spend a witness unknown output.
    3c9680863e
  41. wallet: add `IsInputForSharedSecretDerivation` function f5c1cbf99b
  42. wallet: make coin selection silent payments aware
    The coin selection algorithm wasn't guaranteed
    to return a set of coins that are eligible for silent
    payments transactions even when eligible coins
    were available.
    
    This commit forces coin selection to first select
    eligible coins before attempting to complete
    the result set with ineligible coins.
    
    If the transaction cannot be fulfilled with only
    eligible coins, coin selection will "preset" eligible
    outputs in descending order of `effective_value`
    and attempt to construct a selection from the
    remaining available coins.
    8c53101bbc
  43. wallet: add `CreateSilentPaymentsOutputs` function
    `CreateSilentPaymentsOutputs` gets the correct private keys, adds them
    together, groups the silent payments destinations and then generates the
    taproot script pubkeys. These are then passed back to
    CreateTransactionInternal, which uses these scriptPubKeys to update
    vecSend before adding them to the transaction outputs.
    fb51da1a00
  44. wallet: update wallet change type selection logic for sp dest
    If sending to a silent payments dest, the change type should be taproot
    because silent payments dests appear as taproot outputs on the blockchain.
    4e4fe396e5
  45. wallet: enable sending to silent payments address
    Treat silent payments addresses as valid destination. Also disable using
    silent payments addresses with the `addr()` descriptor, as this
    descriptor expects an encoding of a scriptPubKey, whereas a silent
    payment address consists of instructions on how to generate a
    scriptPubKey for the recipient.
    
    Co-authored-by: Novo <eunovo9@gmail.com>
    f84beeef7d
  46. wallet/rpc: add sp addr support to sendall b6d4b2b64f
  47. wallet/rbf: support addition of new sp outputs
    Handle sp addresses that may be supplied in the `outputs` param of `bumpfee` and `psbtbumpfee`.
    
    The outputs must be passed as CTxDestinations rather than scriptPubKeys to `CreateRateBumpTransaction`,
    so `CreateTransaction` can properly transform the provided sp addresses to taproot scriptPubKeys.
    2ff2de3e2c
  48. Eunovo force-pushed on Jun 26, 2026
  49. DrahtBot added the label CI failed on Jun 26, 2026
  50. DrahtBot commented at 9:37 AM on June 26, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task Windows native, fuzz, VS: https://github.com/bitcoin/bitcoin/actions/runs/28226175984/job/83618564020</sub> <sub>LLM reason (✨ experimental): CI failed because the fuzz RPC target errored out: scantxforsilentpayments RPC command is missing from rpc.cpp’s RPC_COMMANDS_SAFE_FOR_FUZZING/RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  51. Eunovo force-pushed on Jun 26, 2026
  52. Eunovo force-pushed on Jun 26, 2026
  53. rpc/util: add scantxforsilentpayments
    Useful in sp sending functional tests to check that the resulting taproot outputs are correct.
    ee27c74b26
  54. Eunovo force-pushed on Jun 26, 2026
  55. DrahtBot removed the label CI failed on Jun 26, 2026
  56. in test/functional/wallet_silentpayments_sending.py:10 in 22e42cb9b5 outdated
       5 | +from test_framework.segwit_addr import bech32_encode, convertbits, Encoding
       6 | +from test_framework.test_framework import BitcoinTestFramework
       7 | +from test_framework.util import assert_equal, assert_raises_rpc_error
       8 | +
       9 | +XPRV = "tprv8ZgxMBicQKsPevADjDCWsa6DfhkVXicu8NQUzfibwX2MexVwW4tCec5mXdCW8kJwkzBRRmAay1KZya4WsehVvjTGVW6JLqiqd8DdZ4xSg52"
      10 | +XPUB = "tpubD6NzVbkrYhZ4YNXVQbNhMK1WqguFsUXceaVJKbmno2aZ3B6QfbMeraaYvnBSGpV3vxLyTTK9DYT1yoEck4XUScMzXoQ2U2oSmE2JyMedq3H"
    


    rkrux commented at 12:48 PM on June 27, 2026:

    In 22e42cb9b58a3406ab1870be71aa38f861fbba4d "tests: add sending functional tests"

    After PR #35543 is merged, we don't need to (manually find and) hardcode xprvs and xpubs in the functional tests anymore. Something like the following can be done, similar to how ECKey.generate() is used:

    from test_framework.extendedkey import ExtendedPrivateKey
    ...
    extended_key = ExtendedPrivateKey.generate()
    xprv, xpub = extended_key.to_string(), extended_key.pubkey().to_string()
    

    Eunovo commented at 9:04 AM on June 29, 2026:

    Will fix when I rebase.

  57. in test/functional/wallet_silentpayments_sending.py:50 in 22e42cb9b5
      45 | +
      46 | +    def skip_test_if_missing_module(self):
      47 | +        self.skip_if_no_wallet()
      48 | +
      49 | +    def init_wallet(self, *, node):
      50 | +        pass
    


    rkrux commented at 12:49 PM on June 27, 2026:

    In 22e42cb9b58a3406ab1870be71aa38f861fbba4d "tests: add sending functional tests"

    I assume it's taken from wallet_taproot.py? It's dead code and should be removed.


    Eunovo commented at 9:22 AM on June 29, 2026:

    Done.

  58. in test/functional/wallet_silentpayments_sending.py:112 in 22e42cb9b5
     107 | +            return {}
     108 | +
     109 | +        if single:
     110 | +            txid = wallet.sendtoaddress(addr0, amt0)
     111 | +            assert txid in node.getrawmempool()
     112 | +            assert wallet.gettransaction(txid)["confirmations"] == 0
    


    rkrux commented at 12:52 PM on June 27, 2026:

    In 22e42cb9b58a3406ab1870be71aa38f861fbba4d "tests: add sending functional tests"

    There are many asserts in the file of the form assert X == Y. Not sure why the Drahtbot has not mentioned in this PR (because it has commented on several PRs before), but the preference is to use the assert_equal(X, Y) utility function from the testing framework.


    Eunovo commented at 9:22 AM on June 29, 2026:

    Done.

  59. in test/functional/wallet_silentpayments_sending.py:538 in 22e42cb9b5
     533 | +        for _ in range(3):
     534 | +            self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
     535 | +        self.nodes[0].syncwithvalidationinterfacequeue()
     536 | +
     537 | +        for txid in txids:
     538 | +            assert wallet.gettransaction(txid)["confirmations"] <= 0
    


    rkrux commented at 12:56 PM on June 27, 2026:

    In 22e42cb "tests: add sending functional tests"

    Similar to the equality: s/assert X <= Y/assert_greater_than(Y, X)


    Eunovo commented at 9:22 AM on June 29, 2026:

    Done.

  60. in test/functional/wallet_silentpayments_sending.py:327 in 22e42cb9b5 outdated
     322 | +        assert finalized["complete"]
     323 | +        txid = self.nodes[0].sendrawtransaction(finalized["hex"])
     324 | +        verify_inputs(txid)
     325 | +        self.generate(self.nodes[0], 1)
     326 | +        self.assert_sp_outputs(txid, (self.scan_key_1, self.spend_key_1, 1))
     327 | +        cleanup()
    


    rkrux commented at 1:04 PM on June 27, 2026:

    In 22e42cb "tests: add sending functional tests"

    For all these cases where the testing functionality is preceded by setup() and succeeded by cleanup(), a local context manager can be used for readability. Refer how a custom WalletUnlock context manager is used.

    https://github.com/bitcoin/bitcoin/blob/7a74f6529357cf78ee74f0316b9502664f56889e/test/functional/test_framework/wallet_util.py#L95-L112


    Eunovo commented at 8:55 AM on June 29, 2026:

    It seems a bit overkill to create a Context Manager class for this one test function. I think the current setup-cleanup code is better for this case


    rkrux commented at 9:50 AM on June 30, 2026:

    There is a precedent (or soon going to be) of using context managers in a single test file: https://github.com/bitcoin/bitcoin/pull/35003/changes#diff-815ba9df1be928d33d72629e1cdd6208a68493b24a4cdee0c823fb0375acd44aR34-R47

    I think it seems reasonable to create and use a context manager if it improves readability. I also feel it's a nice-to-have and not a must-have.


    Eunovo commented at 6:40 AM on July 1, 2026:

    Changed the code to use the generator context manager pattern.

  61. rkrux commented at 1:14 PM on June 27, 2026: contributor

    Thanks for addressing the previous suggestions in both the source code and the tests - git range-diff 989d354...22e42cb

    Partial review of the test commit 22e42cb "tests: add sending functional tests".

  62. Eunovo force-pushed on Jun 29, 2026
  63. tests: add sending functional tests 6cc51d0ab0
  64. Eunovo force-pushed on Jul 1, 2026

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: 2026-07-01 08:51 UTC

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