{
 "number": 32966,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/32966",
 "title": "Silent Payments: Receiving",
 "author": "Eunovo",
 "author_association": "CONTRIBUTOR",
 "created_at": "2025-07-14T08:30:35Z",
 "updated_at": "2026-06-27T13:15:13Z",
 "age_days": 430,
 "draft": true,
 "labels": [
  "Needs rebase"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "c773e166285f085fc77203b879d64c6b541219e4",
 "head_ref": "2025-implement-bip352-receiving",
 "head_repo": "Eunovo/bitcoin",
 "head_history": [
  {
   "t": "2025-07-20T04:47:31Z",
   "sha": "cf8007c1e9d2e415409b157694793a1616fb4606"
  },
  {
   "t": "2025-07-20T08:16:21Z",
   "sha": "ec56655f73a04b56b05e97e1ca204a26b9299e61"
  },
  {
   "t": "2025-07-20T08:30:37Z",
   "sha": "3b05f60120123ce1fbfc7f4f2689c31dd5ad4d33"
  },
  {
   "t": "2025-07-21T16:32:23Z",
   "sha": "ed7f894fc0c1ed3a84f4af73ece619698cee11c0"
  },
  {
   "t": "2025-07-22T12:02:12Z",
   "sha": "913d82456686a3c8e38e50230209ebbf6efcdd54"
  },
  {
   "t": "2025-07-23T16:38:17Z",
   "sha": "7f84d23c16cfa50435fd061f55bfd7865ee06c19"
  },
  {
   "t": "2025-07-23T17:01:21Z",
   "sha": "c96cc615a6e3a972e17245d1afc4640dd0d0bed3"
  },
  {
   "t": "2025-07-23T17:16:13Z",
   "sha": "3bab8e63c3082dda84ebeeed7fd6899c04c5d157"
  },
  {
   "t": "2025-07-25T04:12:06Z",
   "sha": "640a4abd10db578bce3f49db64c6f0f3c0d77f7b"
  },
  {
   "t": "2025-07-25T04:41:42Z",
   "sha": "970bef8749a6371676e7b48ecfd18153b36fe13f"
  },
  {
   "t": "2025-07-25T05:42:53Z",
   "sha": "fb185b09f2289f283e3ef3d206977e12e1f52414"
  },
  {
   "t": "2025-07-25T11:22:42Z",
   "sha": "587c63e06955ce5c5f2d64f1c1700ca8628572cf"
  },
  {
   "t": "2025-07-30T11:05:15Z",
   "sha": "1982c8f0ad812d301a4dc09fa3d05328688f0172"
  },
  {
   "t": "2025-08-04T19:42:50Z",
   "sha": "a7291beb65379b187118d2851784b60364d7d4ed"
  },
  {
   "t": "2025-08-12T15:41:26Z",
   "sha": "d543c8770511a5d7acb0b4515aaf62eb4b46101f"
  },
  {
   "t": "2025-08-13T08:39:53Z",
   "sha": "50fafd9cbec4bd7361bc74434967085d53061118"
  },
  {
   "t": "2025-08-13T11:19:27Z",
   "sha": "01e275bdcc47319d94fcd3a5ab519277d7fe3a02"
  },
  {
   "t": "2025-08-14T08:04:59Z",
   "sha": "09277cbc63907d5566f50a3a3643862cd18c568d"
  },
  {
   "t": "2025-08-18T07:22:40Z",
   "sha": "4b4970427ea51f93308eade67368f3d44e8a999d"
  },
  {
   "t": "2025-08-18T08:35:13Z",
   "sha": "f86b9d208e79e153dbc218d66c5a62ce372ee139"
  },
  {
   "t": "2025-08-19T14:08:55Z",
   "sha": "7150948e694a3ec8420a39ff9530b70e0a8d6c07"
  },
  {
   "t": "2025-09-09T05:38:49Z",
   "sha": "891b8dd679c1c0258b0f97093fcbddfdb70b2136"
  },
  {
   "t": "2025-09-11T09:34:37Z",
   "sha": "cc0b97b7879a73b9341bf88391312799be91439a"
  },
  {
   "t": "2025-09-18T14:12:24Z",
   "sha": "55485a679d70a9bba11d556df7aa8ee4b98b7157"
  },
  {
   "t": "2025-12-01T10:00:36Z",
   "sha": "fcc8b88ffd4fd565d01617f533c60beb83a3e461"
  },
  {
   "t": "2025-12-01T10:13:37Z",
   "sha": "3bfab00d166c45c37f1056abcdbee2e59a882776"
  },
  {
   "t": "2026-02-10T15:49:41Z",
   "sha": "9ecf265213b2b5aad530d1cbd34e52f659fe64b6"
  },
  {
   "t": "2026-05-14T12:01:04Z",
   "sha": "0be2272cfcc3cb5cd1d75e735b548202cb10a96e"
  },
  {
   "t": "2026-05-14T13:20:36Z",
   "sha": "8c0eb4efae8364bc1eadc9d0b2cd3b596730fb19"
  },
  {
   "t": "2026-05-15T11:44:52Z",
   "sha": "877722cf9b1838c3ccb72fe9f5794ef285327ab5"
  },
  {
   "t": "2026-05-16T03:39:15Z",
   "sha": "c773e166285f085fc77203b879d64c6b541219e4"
  }
 ],
 "additions": 18954,
 "deletions": 165,
 "changed_files": 94,
 "commit_count": 41,
 "size_bucket": "XL",
 "mergeable_state": "dirty",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {},
   "conflicts": [
    {
     "number": 35301,
     "title": "Silent Payments: Implement bip352 (take 2)",
     "author": "Eunovo"
    },
    {
     "number": 35043,
     "title": "refactor: Properly return from ThreadSafeQuestion signal + btcsignals follow-ups",
     "author": "maflcko"
    },
    {
     "number": 34909,
     "title": "wallet, refactor: modularise wallet by extracting out legacy wallet migration",
     "author": "rkrux"
    },
    {
     "number": 34861,
     "title": "wallet: Add importdescriptors interface",
     "author": "polespinasa"
    },
    {
     "number": 34806,
     "title": "refactor: logging: Various API improvements",
     "author": "ajtowns"
    },
    {
     "number": 34698,
     "title": "wallet: handle MiniMiner bump fee calculation failures",
     "author": "shuv-amp"
    },
    {
     "number": 34697,
     "title": "descriptor: fix musig duplicate checks and origin handling",
     "author": "shuv-amp"
    },
    {
     "number": 34405,
     "title": "wallet: skip APS when no partial spend exists",
     "author": "8144225309"
    },
    {
     "number": 33112,
     "title": "wallet: relax external_signer flag constraints, add musig2 test (partial)",
     "author": "Sjors"
    },
    {
     "number": 33034,
     "title": "wallet: Store transactions in a separate sqlite table",
     "author": "achow101"
    },
    {
     "number": 32763,
     "title": "wallet: Replace CWalletTx::mapValue and vOrderForm with explicit class members",
     "author": "achow101"
    },
    {
     "number": 28333,
     "title": "wallet: Construct ScriptPubKeyMans with all data rather than loaded progressively",
     "author": "achow101"
    },
    {
     "number": 27865,
     "title": "wallet: Track no-longer-spendable TXOs separately",
     "author": "achow101"
    },
    {
     "number": 27260,
     "title": "Enhanced error messages for invalid network prefix during address parsing.",
     "author": "portlandhodl"
    },
    {
     "number": 19461,
     "title": "multiprocess: Add bitcoin-gui -ipcconnect option",
     "author": "ryanofsky"
    },
    {
     "number": 19460,
     "title": "multiprocess: Add bitcoin-wallet -ipcconnect option",
     "author": "ryanofsky"
    },
    {
     "number": 10102,
     "title": "Multiprocess bitcoin",
     "author": "ryanofsky"
    }
   ]
  }
 },
 "acks_parsed": {},
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 0,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "PedroRosalba",
   "Sjors",
   "josibake",
   "macgyver13",
   "rkrux"
  ]
 },
 "signals": {
  "needs_rebase": true,
  "ci_failed": false,
  "mergeable_state": "dirty",
  "last_author_activity": "2026-05-16T03:39:15Z",
  "last_reviewer_activity": "2026-06-27T13:15:13Z",
  "last_reviewer": "rkrux",
  "author_silent_days": 124,
  "waiting_on_author_days": 82,
  "days_since_update": 82
 },
 "refs": {
  "mentioned": [
   28201
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 28201,
    "type": "pull",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "Silent Payments: sending"
   }
  ],
  "conflicts": [
   35301,
   35043,
   34909,
   34861,
   34806,
   34698,
   34697,
   34405,
   33112,
   33034,
   32763,
   28333,
   27865,
   27260,
   19461,
   19460,
   10102
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/interfaces/chain.h",
  "src/key.cpp",
  "src/key.h",
  "src/outputtype.cpp",
  "src/pubkey.cpp",
  "src/script/descriptor.cpp",
  "src/script/signingprovider.h",
  "src/wallet/rpc/wallet.cpp",
  "src/wallet/scriptpubkeyman.cpp",
  "src/wallet/spend.cpp",
  "src/wallet/test/wallet_tests.cpp",
  "src/wallet/wallet.cpp",
  "src/wallet/walletutil.cpp",
  "test/functional/wallet_silentpayments_receiving.py"
 ],
 "body": "This PR is part of integrating silent payments into Bitcoin Core. Status and tracking for the project is managed in https://github.com/bitcoin/bitcoin/issues/28536\n\nPrerequisite PRs:\n- [ ] https://github.com/bitcoin/bitcoin/pull/35301\n- [ ] https://github.com/bitcoin/bitcoin/pull/35302\n\nThis PR:\n- Adds a Silent Payments descriptor implemenation\n- Adds a `SilentPaymentsDescriptorScriptPubKeyMan` Impl that is a subclass of `DescriptorScriptPubKeyMan`\n- Implements Silent Payments scanning for the wallet\n- Updates sending logic to use `silent-payments` destination for change when sending to `silent-payments` destination\n- Adds unit and functional tests for silent payments-related functionality\n\n**Follow-ups**\n- Silent Payments Label functionality is incomplete in this PR and will be added as a follow-up PR.",
 "commits": [
  {
   "sha": "bb1bce36cf8b9292a65f0f03ab855e7133357b9f",
   "date": "2026-05-16T03:20:27Z",
   "message": "Squashed 'src/secp256k1/' changes from 7262adb4b4..14be7f2abe\n\n14be7f2abe silentpayments: skip slow benchmarks for low iters count (<= 2)\nea46d6502e docs: update README\n8587aeb029 ci: enable silentpayments module\n1375d38a32 tests: add sha256 tag test\neb3748dab1 tests: add constant time tests\ne1674f389a tests: add BIP-352 test vectors\n9163035ab7 silentpayments: optimize scanning by using batch inversion\ndc36ff6ec3 silentpayments: add benchmarks for scanning\nb7f09f3eb5 silentpayments: add examples/silentpayments.c\n460565c662 silentpayments: respect per-group recipients protocol limit (K_max=2323)\n72658fc85e silentpayments: receiving\nc7a64d0cd8 silentpayments: recipient label support\nbe56a66992 silentpayments: sending\n7bfae739e3 build: add skeleton for new silentpayments (BIP352) module\nb11340b3ce Merge bitcoin-core/secp256k1#1849: musig: always clear out secret key in `secp256k1_musig_nonce_gen_counter`\n8479eafa57 musig: always clear out secret key in `secp256k1_musig_nonce_gen_counter`\nc1a9e4fe64 Merge bitcoin-core/secp256k1#1848: ci: Bump GCC snapshot major version to 17\n3cca6451a2 ci: Bump GCC snapshot major version to 17\nea174fe045 Merge bitcoin-core/secp256k1#1846: ci: Replace `ilammy/msvc-dev-cmd` with manual MSVC setup\n285cb788e9 ci: Replace `ilammy/msvc-dev-cmd` with manual MSVC setup\n\ngit-subtree-dir: src/secp256k1\ngit-subtree-split: 14be7f2abe4797c1a58249cb901cc6f02972cb4d"
  },
  {
   "sha": "ece2374760f3a76e8f62dc1ebc2363cccf52a426",
   "date": "2026-05-16T03:20:27Z",
   "message": "Merge commit 'bb1bce36cf8b9292a65f0f03ab855e7133357b9f' into new-sp-base"
  },
  {
   "sha": "bccfd8110591330f247e32cae0b953c923cc3e51",
   "date": "2026-05-16T03:20:44Z",
   "message": "crypto: add read-only method to KeyPair\n\nAdd a method for passing a KeyPair object to secp256k1 functions expecting a secp256k1_keypair.\nThis allows for passing a KeyPair directly to a secp256k1 function without needing to create a\ntemporary secp256k1_keypair object."
  },
  {
   "sha": "602835e08070cab981842ce4cd5065730b3e8c48",
   "date": "2026-05-16T03:20:44Z",
   "message": "Add \"sp\" HRP"
  },
  {
   "sha": "ba4b734ec89d590951574d2714867afab27d1347",
   "date": "2026-05-16T03:20:44Z",
   "message": "Add V0SilentPaymentDestination address type"
  },
  {
   "sha": "6355a904945d0d5704032e464f20a69a5d82a91b",
   "date": "2026-05-16T03:20:44Z",
   "message": "common: add bip352.{h,cpp} secp256k1 module\n\nWrap the silentpayments module from libsecp256k1. This is placed in\ncommon as it is intended to be used by:\n\n  * RPCs: for parsing addresses\n  * Wallet: for sending, receiving, spending silent payment outputs\n  * Node: for creating silent payment indexes for light clients"
  },
  {
   "sha": "e12280b9d6a4230ed1f604ebd14ec6716c65a7dd",
   "date": "2026-05-16T03:20:44Z",
   "message": "wallet: disable sending to silent payment address\n\nHave `IsValidDestination` return false for silent payment destinations\nand set an error string when decoding a silent payment address.\n\nThis prevents anyone from sending to a silent payment address before\nsending is implemented in the wallet, but also allows the functions to\nbe used in the unit testing famework."
  },
  {
   "sha": "0520567fb53b5bee8d481463de83b97b551392ef",
   "date": "2026-05-16T03:20:44Z",
   "message": "tests: add BIP352 test vectors as unit tests\n\nUse the test vectors to test sending and receiving. A few cases are not\ncovered here, namely anything that requires testing specific to the\nwallet. For example:\n\n* Taproot script path spending is not tested, as that is better tested in\n  a wallets coin selection / signing logic\n* Re-computing outputs during RBF is not tested, as that is better\n  tested in a wallets RBF logic\n\nThe unit tests are written in such a way that adding new test cases is\nas easy as updating the JSON file"
  },
  {
   "sha": "209b40626ab94d9daf280ec8b8344cd395ffb37a",
   "date": "2026-05-16T03:21:05Z",
   "message": "wallet: get serialized size for `V0SilentPayments`\n\nBIP352 v0 specifies that a silent payment output is a taproot output.\nTaproot scriptPubKeys are a fixed size, so when calculating the\nserialized size for a CRecipient with a V0SilentPayments destination,\nuse WitnessV1Taproot for the serialized txout size."
  },
  {
   "sha": "f9a10e9ea9b57f6b21a6dbfd1239c3ba60f721f8",
   "date": "2026-05-16T03:21:05Z",
   "message": "wallet: add method for retreiving a private key\n\nAdd a method for retreiving a private key for a given scriptPubKey.\nIf the scriptPubKey is a taproot output, tweak the private key with the\nmerkle root or hash of the public key, if applicable."
  },
  {
   "sha": "e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd",
   "date": "2026-05-16T03:21:05Z",
   "message": "wallet: make coin selection silent payment aware\n\nAdd a flag to the `CoinControl` object if silent payment destinations\nare provided. Before adding the flag, call a function which checks if:\n\n* The wallet has private keys\n* The wallet is unlocked\n\nWithout both of the above being true, we cannot send to a silent payment\naddress.\n\nDuring coin selection, if this flag is set, skip taproot inputs when\nscript spend data is available. This is based on the assumption that if\na user provides script spend data, they don't have access to the key\npath spend. As future improvement, we could instead check to see if we\nhave access to the key path spend, and only exclude the output when we\ndon't regardless of whether or not the user provides script spend data.\n\nAlso skip UTXOs of type `WITNESS_UNKNOWN`, although it is very unlikely\nour wallet would ever try to spend a witness unknown output."
  },
  {
   "sha": "9898826eef7b6034bffdc97b6602984f67b269ac",
   "date": "2026-05-16T03:21:05Z",
   "message": "wallet: add `IsInputForSharedSecretDerivation` function"
  },
  {
   "sha": "efbdd793f58e8b7cdd21d0de3ecd6fcee330d86f",
   "date": "2026-05-16T03:21:05Z",
   "message": "wallet: add `CreateSilentPaymentOutputs` function\n\n`CreateSilentPaymentsOutputs` gets the correct private keys, adds them\ntogether, groups the silent payment destinations and then generates the\ntaproot script pubkeys. These are then passed back to\nCreateTransactionInternal, which uses these scriptPubKeys to update\nvecSend before adding them to the transaction outputs."
  },
  {
   "sha": "334c36a2e5a7bb4e4cd9fc6d880ac735601354ea",
   "date": "2026-05-16T03:21:05Z",
   "message": "wallet: update TransactionChangeType\n\nIf sending to a silent payment destination, the change type should be taproot"
  },
  {
   "sha": "71bfa7d3ef0b6bc4a80452c16e1fbf0f5b16ef14",
   "date": "2026-05-16T03:21:05Z",
   "message": "wallet: enable sending to silent payment address\n\nTreat silent payment addresses as valid destination. Also disable using\nsilent payment addresses with the `addr()` descriptor, as this\ndescriptor expects an encoding of a scriptPubKey, whereas a silent\npayment address consists of instructions on how to generate a\nscriptPubKey for the recipient.\n\nCo-authored-by: Oghenovo Usiwoma <37949128+eunovo@users.noreply.github.com>"
  },
  {
   "sha": "03c835dbd6d78182b546713ed495373c7d07b01c",
   "date": "2026-05-16T03:21:05Z",
   "message": "tests: add sending functional tests"
  },
  {
   "sha": "cc5138cfe47c12ea8f6c4d361cb9ae363c821533",
   "date": "2026-05-16T03:21:25Z",
   "message": "Add OutputType::SILENT_PAYMENTS"
  },
  {
   "sha": "c8c6cebc60f68d181b838743e655b1ecddaeabfa",
   "date": "2026-05-16T03:21:25Z",
   "message": "descriptors: impl ScankeyPubkeyProvider\n\nWhile the scankey looks like a private key, and is represented as a `CKey` in the code,\nit is actually much closer to a public key and it needs to be treated as a public key,\nso it can be added to watch-only wallets."
  },
  {
   "sha": "afcac37e1c57c896179a8984f5c15feec20d002d",
   "date": "2026-05-16T03:21:25Z",
   "message": "descriptor: implement sp(scan, spend) desc\n\nsp() expects a scan private key and a spend key which could be a private key\nor a public key.\nThe scan key is really a \"scan entropy\" and will not be treated as an actual\nprivate key."
  },
  {
   "sha": "3e7686cac174d1002853c3c291957ff4540ed8d8",
   "date": "2026-05-16T03:21:25Z",
   "message": "descriptor: add SPDescriptor public interface\n\nCreate an SPDescriptor interface that will be used by the\n`SilentPaymentDescriptorScriptPubKeyMan`.\n\nThe interface only needs to provide a way to get the scan key,\nthe spend key can be obtained through the normal Descriptor methods.\n\nWhile the scan key is represented as a `CKey`, it will not be used\nin the signing process. This creates an argument against putting this\nin a signing provider."
  },
  {
   "sha": "155b6a72f080cd3d0ff7f507cd95539bca9ddceb",
   "date": "2026-05-16T03:21:25Z",
   "message": "key: add ComputeBIP352Key() method\n\nThis method makes it possible to tweak silent payment spend keys in later commits"
  },
  {
   "sha": "486f45b71224278b7409a9a2b0f5ba8897b549f9",
   "date": "2026-05-16T03:21:25Z",
   "message": "notifications: Add spent_coins to tx added notification\n\nThe spent_coins data will be used to scan for silent payments in later commits\n\nCo-authored-by: Ava Chow <github@achow101.com>"
  },
  {
   "sha": "3a035a4be752375e5c9a4fed682da2a47d96598e",
   "date": "2026-05-16T03:21:25Z",
   "message": "interfaces: Load block undo data\n\nThis undo data will be used to scan for silent payments in later commits\n\nCo-authored-by: Ava Chow <github@achow101.com>"
  },
  {
   "sha": "62de0f0e8f76228983f03215670118a536cf1138",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet: generate sp() descriptor\n\nThe scan key will be derived while the descriptor is parsed, so\nwe must pass the master xpriv into `GenerateWalletDescriptor`.\n\nThe spend key is expanded later so it is specified\nas an xpub and path instead."
  },
  {
   "sha": "05e32ed53e52312a6ab2460ceab0d1cc0255dfb2",
   "date": "2026-05-16T03:21:25Z",
   "message": "bip352: Make SilentPaymentOuput serializable\n\nIn future commits, a Silent Payment enabled wallet will write found SilentPaymentOutputs to the DB.\nAlthough the XOnlyPubKey can be derived from adding the Spend pubkey and the tweak,\nwe opt  to save the the found XOnlyPubKey because that removes the need for a CPubkey::TweakAdd() in the codebase"
  },
  {
   "sha": "35b5e7b2a2c3ce07b51043fbc9ce0d39f7afe591",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet: create SilentPaymentDescriptorScriptPubKeyMan\n\nCo-authored-by: Ava Chow <github@achow101.com>"
  },
  {
   "sha": "865ff19b65f6d3c70e20fd75b5b6e57428858e44",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet: scan for silent payments\n\nCo-authored-by: Ava Chow <github@achow101.com>"
  },
  {
   "sha": "7dd06e49070c1bf843daa7ec4172d144af364d89",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet/rpc: add create silent-payments wallet option\n\nCo-authored-by: Ava Chow <github@achow101.com>"
  },
  {
   "sha": "51b161fe22f7c36e49b0e6d237568db0f76fb086",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet: disable fast rescan for silent_payments wallet\n\nsilent_payments wallet needs to scan entire blocks since it doesn't know ahead of time which scriptPubKeys to use in it's fast rescan filter."
  },
  {
   "sha": "82820d18c8fed033493104adc5539251fbf85832",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet: import silent payments descriptor"
  },
  {
   "sha": "ffa0e15a8359cd1c71e74f21f157c0d6f28eedb6",
   "date": "2026-05-16T03:21:25Z",
   "message": "tests: add silent payments receiving functional tests\n\nCo-authored-by: Ava Chow <github@achow101.com>"
  },
  {
   "sha": "5c4df46bc0b73d78dd4b8c832af0f127a5e6f4ce",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet/rpc: add sp-address support to getaddressinfo"
  },
  {
   "sha": "0429f1c0c27e52b5da5b69f6cac4b2fead61352e",
   "date": "2026-05-16T03:21:25Z",
   "message": "update addressbook with found silent-payment outputs\n\ntraditionally, the receiving scripts are known to the core wallet\nbecause they are added to the addressbook at the time they are requested.\n\nin silent payments, the outputs are not known until found. its important, however,\nto have the found scripts in the addressbook so all of the change accounting can be down\nproperly.\n\nthis commits adds found outputs to the address book if they are not change. the way\nchange is determined is a bit hacky in that we just check if the found output was\nfound with a label (since this is the only label currently implemented). in the future,\nwe should specifically check for a change specific label."
  },
  {
   "sha": "7f096ee8def9a9d905b8023c9ba91693b3e149d4",
   "date": "2026-05-16T03:21:25Z",
   "message": "use silent payments change when sending\n\nThe wallet tries to match change OutputTpe to other outputs to preserve privacy.\nUse silent payment change address when sending coins to:\n- any silent payment address\n- any taproot address"
  },
  {
   "sha": "342564a27a0bdbc7affcd406cafcd1b70d11a05d",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet/spend: Filter out coins not eligible to pay sp change dest"
  },
  {
   "sha": "75ac51878fac636fd5910b4c1d33c3369cd95986",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet: retry CreateTransaction without silent_payments change\n\n`CreateTransaction` fails if change_type is set to OutputType::SILENT_PAYMENTS\nand there are no eligible inputs for the transaction. This commit modifies\n`CreateTransaction` logic to make a second attempt to\ncreate a tx without OutputType::SILENT_PAYMENTS change_type"
  },
  {
   "sha": "0d3caba2a910d677f82caaf108dc30e64a9bb664",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet: prefer silent_payments over Bech32m as fallback change type\n\nThis allows wallets with only sp descs to use sp change destination for transactions."
  },
  {
   "sha": "933622e393e7111c4f0b038e0f431ae7efb66021",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet/tests: Enable Silent Payments in wallet unit tests"
  },
  {
   "sha": "a03970ce432e38450b1ed4b686b086f2f0fd2845",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet/gui: add silent_payments option to createwalletdialog"
  },
  {
   "sha": "351242550983d74603f57882895d435391299387",
   "date": "2026-05-16T03:21:25Z",
   "message": "wallet/gui: add silent-payments to address type dropdown"
  },
  {
   "sha": "c773e166285f085fc77203b879d64c6b541219e4",
   "date": "2026-05-16T03:21:25Z",
   "message": "tests: silent-payments wallet coin control\n\nCo-authored-by: macgyver13 <4712150+macgyver13@users.noreply.github.com>"
  }
 ],
 "timeline": [
  {
   "t": "2025-07-14T11:23:42Z",
   "kind": "review_comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "path": "src/wallet/rpc/wallet.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "In 89831dace9d21456eb4a019d86164304e22f458e _wallet/rpc: add create silent-payments wallet option_: while testing I found that it doesn't disable block filters."
  },
  {
   "t": "2025-07-14T20:13:21Z",
   "kind": "comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "text": "Another thing I noticed while testing using the `send` RPC, in a wallet with _only_ an `sp()` descriptor, is that it insists on having a bech32 descriptor for change:\n\n[quoted text omitted]\nIt seems safer, for backups, to send change to the same silent payment address.\n\nWallet created by:\n\n```sh\nbitcoin rpc createwallet Silent blank=true silent_payments=true\nbitcoin rpc importdescriptors '[{\"desc\": \"sp(xprv...,xprv...)\",  \"timestamp\": \"now\", \"active\": true]\n```\n\nAlso looking forward to have labels back :-)"
  },
  {
   "t": "2025-07-15T07:30:39Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/rpc/wallet.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2204657999,
   "text": "Thanks @Sjors. I'll fix it"
  },
  {
   "t": "2025-07-15T08:53:37Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/rpc/wallet.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2204657999,
   "text": "We can disable the fast rescan for now just to keep this PR focused, but in theory we should be able to use the fast rescan regardless of whether or not the wallet is a silent payments wallet. Perhaps we can leave a comment to enable fast rescans in a follow up?"
  },
  {
   "t": "2025-07-15T09:55:08Z",
   "kind": "review_comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "cb44e3812c741e3a939a64799130bbf0787ef89a : I think we should set `bool IsRange() const override { return false; }` so we don't have to think about ranged descriptors."
  },
  {
   "t": "2025-07-15T14:14:18Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "While reviewing the PR, it seems a lot of things could be simplified by if we just treated the scan key as something that _isn't_ a `CKey`, i.e., we introduce a completely new object for holding the scan key. I think that would allow us to drop this commit and simplify other places where we are trying to work around the fact that a scan key isnt really a private key.\n\nI haven't thought this all the way through yet, but in my initial pass on the PR it seems like it should be possible."
  },
  {
   "t": "2025-07-15T14:24:40Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/outputtype.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "Would recommend splitting the output type changes into their own commit(s). Its a self-contained change, and splitting them out from the descriptor changes makes the descriptor commit easier to review."
  },
  {
   "t": "2025-07-15T14:25:43Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "Potentially another area we could simplify if we end up not treating a scan key as a `CKey`."
  },
  {
   "t": "2025-07-15T14:29:22Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "AFAICT, we only use the `sp_keys` member of the FlatSigningProvider as a way of passing around the scan key and the spend pubkey, and then also for the spend private key (for signing). It makes sense to me that we would later add the spend private key + tweaks to the FlatSigningProvider, but ideally thats the only thing we use it for and can get rid of `sp_keys`."
  },
  {
   "t": "2025-07-15T14:34:23Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "nit: unnecessary formatting change, should just be a one-line change."
  },
  {
   "t": "2025-07-15T14:35:55Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "Another place we could simplify things if we instead came up with a custom type for the scan key."
  },
  {
   "t": "2025-07-15T14:38:51Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/signingprovider.h",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "Feels like the SigningProvider should only care about the `spend_key + tweak` for signing, so another place to potentially simplify things if scan key is a custom type instead of a `CKey`."
  },
  {
   "t": "2025-07-15T14:40:04Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/test/wallet_tests.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "This could be moved into the output type commit."
  },
  {
   "t": "2025-07-15T14:40:13Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "This could be moved to the output type commit."
  },
  {
   "t": "2025-07-15T14:44:41Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "I think its more appropriate to move this commit into the PR where we first introduce `V0SilentPaymentDestination`. I'll cherry pick this out into https://github.com/bitcoin/bitcoin/pull/28122"
  },
  {
   "t": "2025-07-15T14:48:58Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/walletutil.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "If we can create a custom type for the scan key, it seems better to have a special function just for silent payments that returns this custom key type from an xpriv, rather than change `GenerateWalletDescriptor` to work on an xpriv."
  },
  {
   "t": "2025-07-15T14:51:31Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/walletutil.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "Ideally we can do this without needing an xpriv, but I vaguely remember a reason why we need the xpriv here. Will dig in a bit more to see if we can avoid this."
  },
  {
   "t": "2025-07-15T14:52:11Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/walletutil.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "Just curious, why the extra assert? Seems unrelated to the other changes."
  },
  {
   "t": "2025-07-15T14:57:43Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/walletutil.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "This is returning just the spend private key, right? IIRC, the scan private key is removed from `out.keys` as part of the Parse function. Not clear to me why we would want the spend private key in the `out_keys` out param."
  },
  {
   "t": "2025-07-15T14:59:58Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/key.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "I'm wondering if these two methods (`CKey::TweakAdd`, `CPubKey::TweakAdd`) can also be moved into https://github.com/bitcoin/bitcoin/pull/28122, as they seem a little out of place in this PR (though, admittedly its only in this PR that we actually use them)."
  },
  {
   "t": "2025-07-15T15:02:04Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "I'd remove this (and any other code) related to non-change labels from this PR. Ideally, implement just enough for labels to get change working, and then we can fully implement labels in a follow-up PR."
  },
  {
   "t": "2025-07-15T15:03:34Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "It feels strange to call the provider just to get the scan key, feels like another area we can simplify with a custom scan key type."
  },
  {
   "t": "2025-07-15T15:04:56Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "Same comment regarding moving labels related code to a follow-up PR."
  },
  {
   "t": "2025-07-15T15:09:46Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "The name TopUp here makes sense in that we are trying to match how the rest of the wallet does it, but @Sjors pointed out this can be confusing for people who think of TopUp in terms of the gap limit / key pool refresh context, which we aren't really doing here. We could just have one function called `AddTweak` and then use a boolean for writing to the database, e.g., `AddTweak(uint256& tweak, store_in_db=false)`"
  },
  {
   "t": "2025-07-15T15:11:00Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "Could be `AddTweakWithDB` (based on my previous comment)."
  },
  {
   "t": "2025-07-15T15:11:54Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "Can likely be removed if we have custom methods for storing scan/spend pubkey data, or custom methods for getting them."
  },
  {
   "t": "2025-07-15T15:14:36Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/interfaces/chain.h",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "This commit is quite long, making it difficult to focus on the main thing which is the scanning logic. I'd suggest breaking out smaller commits for just the mempool related changes, and just the undoblock related changes. Possibly more, but will need to dig into the commit a bit more."
  },
  {
   "t": "2025-07-15T15:15:54Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "Do we need the `CTransactionRef` here, as opposed to just operating on `block.data->vtx` directly?"
  },
  {
   "t": "2025-07-15T15:19:00Z",
   "kind": "review",
   "who": "josibake",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "2d443cc405574077fd6860b7d4083943d6addab8",
   "text": "Did a big overview with @Sjors , leaving the notes from our discussion as a review. In general, I think we should investigate using a custom type for the scan key since a lot of the changes seem to be hacking around the fact we represent the scan key as a private key, but then often need to use it as not a private key.\n\nStill in the process of reviewing, but leaving the initial notes for now"
  },
  {
   "t": "2025-07-15T18:56:43Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "Thanks for the reviews @josibake and @Sjors . I am currently travelling, and I will get to them later in the week."
  },
  {
   "t": "2025-07-16T08:00:26Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207792955,
   "text": "Worth mentioning, the only reason we wouldn't be able to do this is if this function (and `TopUp`) are called generically on SPKMans, e.g., in a loop. I don't think this is the case, but wanted to mention it."
  },
  {
   "t": "2025-07-16T09:55:07Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2207717440,
   "text": "Cherry-picked this commit into https://github.com/bitcoin/bitcoin/pull/28201/commits/b94934e089e70b478ea6aa535098586fedb5a12d, in #28201. I added it to the commit where we enable silent payment addresses as valid addresses, at the end of the sending PR."
  },
  {
   "t": "2025-07-20T04:31:24Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207679341,
   "text": "Without `sp_keys`, the wallet can't identify which keys are scan and spend keys from the signing provider. Do you have an alternative approach in mind?"
  },
  {
   "t": "2025-07-20T04:47:31Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "cf8007c1e9d2e415409b157694793a1616fb4606"
  },
  {
   "t": "2025-07-20T04:48:27Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/script/descriptor.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2207029910,
   "text": "Done"
  },
  {
   "t": "2025-07-20T04:48:49Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207692663,
   "text": "Fixed."
  },
  {
   "t": "2025-07-20T04:49:32Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/test/wallet_tests.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207706177,
   "text": "Done"
  },
  {
   "t": "2025-07-20T04:49:43Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/wallet.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207706515,
   "text": "Done"
  },
  {
   "t": "2025-07-20T04:50:10Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/script/descriptor.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2207717440,
   "text": "I've dropped this commit from this branch."
  },
  {
   "t": "2025-07-20T04:50:54Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/outputtype.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2207664427,
   "text": "Done"
  },
  {
   "t": "2025-07-20T05:02:00Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/key.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207755915,
   "text": "Maybe they deserve their own PR?"
  },
  {
   "t": "2025-07-20T05:03:35Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/walletutil.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207735327,
   "text": "Don't we need to derive the scan and spend keys?"
  },
  {
   "t": "2025-07-20T05:06:18Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/walletutil.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2207737007,
   "text": "In the `OutputType::SILENT_PAYMENTS` case, I set the `desc_str`, not the `desc_prefix`; I have to modify the `assert` to prevent a failure."
  },
  {
   "t": "2025-07-20T05:16:25Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/walletutil.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207750518,
   "text": "The derived spend private key must be saved to the DB by the wallet.\n\nWe can avoid this by doing what other descriptors do; the sp descriptor will then be in this form `sp(xpriv/352h/0h/0h/1h/0,xpub/352h/0h/0h/0h/0)` . The `Parse` function will then derive the scan key and save it in the descriptor. The spend key can be derived later when needed from the master key.\n\nWith this alternative method, the wallet only saves the master key to DB as it has always done."
  },
  {
   "t": "2025-07-20T05:19:10Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/wallet.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207809025,
   "text": "We only use the reference once, so it's not needed. I'll take this out as I retouch."
  },
  {
   "t": "2025-07-20T08:16:21Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "ec56655f73a04b56b05e97e1ca204a26b9299e61"
  },
  {
   "t": "2025-07-20T08:17:17Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207792955,
   "text": "Updated"
  },
  {
   "t": "2025-07-20T08:17:23Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207788108,
   "text": "Updated"
  },
  {
   "t": "2025-07-20T08:17:40Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/interfaces/chain.h",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2207805827,
   "text": "I broke this into 3 commits."
  },
  {
   "t": "2025-07-20T08:19:26Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/wallet.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207809025,
   "text": "I ended up leaving the reference and used it in 2 other locations. The code looks slightly cleaner this way."
  },
  {
   "t": "2025-07-20T08:30:37Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "3b05f60120123ce1fbfc7f4f2689c31dd5ad4d33"
  },
  {
   "t": "2025-07-20T08:33:22Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "Added @achow101 as co-author on commits with code/ideas taken from  https://github.com/bitcoin/bitcoin/pull/28453"
  },
  {
   "t": "2025-07-21T09:43:34Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/rpc/wallet.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2204657999,
   "text": "IIUC The silent payments wallet needs to scan entire blocks since it doesn't know ahead of time which `scriptPubKeys` to use in a GCS filter. Since we can't skip blocks, fast rescans shouldn't provide any advantages here.\n\nEDIT\nIt might also be possible to use fast rescan when importing descriptors if none of the descriptors are silent payment descriptors. Is this what you were referring to @josibake?"
  },
  {
   "t": "2025-07-21T12:36:41Z",
   "kind": "review_comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "path": "src/wallet/rpc/wallet.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2204657999,
   "text": "[quoted text omitted]\n\nThis makes sense. Is it documented anywhere so we don't forget by the next review round? :-)\n\n[quoted text omitted]\nIt wasn't referring to that and I wouldn't worry about this. Somewhere in the RPC documentation (createwallet and/or importdescriptors) we should warn that silent payments disables fast rescan. But `-blockfilterindex` isn't on by default and so it's probably only advanced users that will run into this."
  },
  {
   "t": "2025-07-21T12:55:04Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/rpc/wallet.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2204657999,
   "text": "[quoted text omitted]\n\nI added a separate commit that disables fast rescan and I added an explanation to the commit message. Will push soon.\n\nEDIT\nsee https://github.com/bitcoin/bitcoin/pull/32966/commits/82db7ccaa60a4e1dc0dac6b8f0368ff933303e39"
  },
  {
   "t": "2025-07-21T16:32:23Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "ed7f894fc0c1ed3a84f4af73ece619698cee11c0"
  },
  {
   "t": "2025-07-21T20:23:05Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nIn https://github.com/bitcoin/bitcoin/pull/32966/commits/ed7f894fc0c1ed3a84f4af73ece619698cee11c0 I modified the change `OutputType` determination logic to try to use silent payments if `bech32m` addresses are not available.\n\n[quoted text omitted]\nThat may be true, but the wallet tries to match the change `OutputType` to the other outputs to preserve privacy.\n\ncc @Sjors"
  },
  {
   "t": "2025-07-22T07:23:11Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/rpc/wallet.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2204657999,
   "text": "[quoted text omitted]\n\nThis is correct. I was imagining a world where we can pre-compute the scriptPubKeys, but realised we have to iterate the blocks anyways to get the tweaks so its likely faster to just check directly. In the future, if the wallet has some sort of silent payments index, then I think fast rescans would be possible (and beneficial)."
  },
  {
   "t": "2025-07-22T08:36:47Z",
   "kind": "comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "text": "@Eunovo that's an interesting trade-off, and we should probably be consistent with how the rest of the wallet behaves. Otherwise we'd leave a fingerprint of which coins were sent using silent payments.\n\nSo in that case I think the bevavior should be:\n- if coins are sent to a bech32m address, use a silent payment change address (don't use the regular bech32m descriptor)\n- otherwise, use a matching output type\n  - when there's no descriptor for it, fall back to silent payment change address"
  },
  {
   "t": "2025-07-22T12:02:12Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "913d82456686a3c8e38e50230209ebbf6efcdd54"
  },
  {
   "t": "2025-07-22T12:03:25Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nDone"
  },
  {
   "t": "2025-07-22T16:47:30Z",
   "kind": "comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "text": "Looks like the most recent change is causing a failure in the unit tests:\n\n[quoted text omitted]"
  },
  {
   "t": "2025-07-22T18:50:07Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "Yes @josibake, it's a slightly tricky problem. Rather than rush to a solution, I'd like to discuss it next meeting."
  },
  {
   "t": "2025-07-23T16:38:17Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "7f84d23c16cfa50435fd061f55bfd7865ee06c19"
  },
  {
   "t": "2025-07-23T17:01:21Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "c96cc615a6e3a972e17245d1afc4640dd0d0bed3"
  },
  {
   "t": "2025-07-23T17:16:13Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "3bab8e63c3082dda84ebeeed7fd6899c04c5d157"
  },
  {
   "t": "2025-07-25T04:12:06Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "640a4abd10db578bce3f49db64c6f0f3c0d77f7b"
  },
  {
   "t": "2025-07-25T04:41:42Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "970bef8749a6371676e7b48ecfd18153b36fe13f"
  },
  {
   "t": "2025-07-25T05:42:53Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "fb185b09f2289f283e3ef3d206977e12e1f52414"
  },
  {
   "t": "2025-07-25T09:27:33Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "I've fixed all known errors. The current failing CI is unrelated."
  },
  {
   "t": "2025-07-25T09:36:53Z",
   "kind": "comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nShould be fixed in my (just now) pushed changes for the base and sending PRs."
  },
  {
   "t": "2025-07-25T11:22:42Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "587c63e06955ce5c5f2d64f1c1700ca8628572cf"
  },
  {
   "t": "2025-07-25T13:45:36Z",
   "kind": "comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "text": "I did some more testing with 587c63e06955ce5c5f2d64f1c1700ca8628572cf, noticed improvements:\n- rescan uses the slow version (when `-blockfilterindex` is enabled), as expected\n- if I add a label to a transaction, it stores it\n\nStuff I tested that just works:\n- `listdescriptors` gives me a working scan key (tried by importing it into a watch-only wallet)\n\nNew bug:\n- when I send to a bech32m (`bcp1...`) address with change, using my wallet that only has an sp descriptor, the change output is dropped and added to fees\n  - strange, because your test in 5be304dfa50bcfd3b0a92eff52bac3d8023ce523 seems to cover exactly this scenario\n  - perhaps it's a GUI bug (yikes), because when I use the `send` RPC instead it behaves correctly\n  - _update_: now I can't reproduce it in the GUI either. It was a pretty small output, so maybe it was an edge case where it wanted to avoid a dust change output - although it was bigger than that.\n\nSome remaining issues:\n- add silent payments to \"output types\" in the receive screen (see patch below)\n- when setting a label in the Send dialog it doesn't seem to be added to the resulting transaction\n- if I don't set `silent_payments=true` at wallet creation time I can't change it later and  `importdescriptors` fails with `Cannot import silent payment descriptor into a wallet with silent-payments disabled`\n\nSome style suggestions:\n- I prefer giving `SilentPaymentDescriptorScriptPubKeyMan` in its own file, similar to `external_signer_scriptpubkeyman.{h,cpp}`\n\nPatch to add Silent Payment address to dropdown\n\n```diff\ndiff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h\nindex 94869aff5a..bbd87c075b 100644\n--- a/src/interfaces/wallet.h\n+++ b/src/interfaces/wallet.h\n@@ -268,6 +268,9 @@ public:\n     // Return whether the wallet contains a Taproot scriptPubKeyMan\n     virtual bool taprootEnabled() = 0;\n\n+    // Return whether the wallet contains a Silent Payment scriptPubKeyMan\n+    virtual bool silentPaymentsEnabled() = 0;\n+\n     // Return whether wallet uses an external signer.\n     virtual bool hasExternalSigner() = 0;\n\ndiff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp\nindex be7741e8a8..d3164eccf0 100644\n--- a/src/qt/receivecoinsdialog.cpp\n+++ b/src/qt/receivecoinsdialog.cpp\n@@ -99,6 +99,9 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model)\n         if (model->wallet().taprootEnabled()) {\n             add_address_type(OutputType::BECH32M, tr(\"Bech32m (Taproot)\"), tr(\"Bech32m (BIP-350) is an upgrade to Bech32, wallet support is still limited.\"));\n         }\n+        if (model->wallet().silentPaymentsEnabled()) {\n+            add_address_type(OutputType::SILENT_PAYMENTS, tr(\"Silent Payment\"), tr(\"A Silent Payment address (BIP-352) can safely be reused. Wallet support is still limited.\"));\n+        }\n\n         // Set the button to be enabled or disabled based on whether the wallet can give out new addresses.\n         ui->receiveButton->setEnabled(model->wallet().canGetAddresses());\ndiff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp\nindex 66b24d1ec2..ed62e21012 100644\n--- a/src/wallet/interfaces.cpp\n+++ b/src/wallet/interfaces.cpp\n@@ -505,6 +505,10 @@ public:\n         auto spk_man = m_wallet->GetScriptPubKeyMan(OutputType::BECH32M, /*internal=*/false);\n         return spk_man != nullptr;\n     }\n+    bool silentPaymentsEnabled() override {\n+        auto spk_man = m_wallet->GetScriptPubKeyMan(OutputType::SILENT_PAYMENTS, /*internal=*/false);\n+        return spk_man != nullptr;\n+    }\n     OutputType getDefaultAddressType() override { return m_wallet->m_default_address_type; }\n     CAmount getDefaultMaxTxFee() override { return m_wallet->m_default_max_tx_fee; }\n     void remove() override\n```\n\nNote there's an unrelated GUI glitch that requires you to close and reopen the wallet after importing a new descriptor to get this dropdown to update."
  },
  {
   "t": "2025-07-25T14:03:37Z",
   "kind": "review_comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "path": "test/functional/wallet_silentpayments_receiving.py",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "5be304dfa50bcfd3b0a92eff52bac3d8023ce523 nit: no need to set `next_index` during import"
  },
  {
   "t": "2025-07-25T19:39:45Z",
   "kind": "review_comment",
   "who": "macgyver13",
   "assoc": "NONE",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "I think this change is breaking the ability to import sp descriptor with private keys defined for scan and spend\nThis is the warning I receive when using importdescriptors:\n\"Not all private keys provided. Some wallet functionality may return unexpected errors\""
  },
  {
   "t": "2025-07-25T19:44:45Z",
   "kind": "review_comment",
   "who": "macgyver13",
   "assoc": "NONE",
   "path": "test/functional/wallet_silentpayments_receiving.py",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "Shouldn't the coin_type be different for regtest/signet? /352h/1h instead of /352h/0h"
  },
  {
   "t": "2025-07-25T19:45:52Z",
   "kind": "review",
   "who": "macgyver13",
   "assoc": "NONE",
   "state": "COMMENTED",
   "commit": "587c63e06955ce5c5f2d64f1c1700ca8628572cf",
   "text": "working on backup / restore testing I noticed a few issues."
  },
  {
   "t": "2025-07-27T05:38:20Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2231883781,
   "text": "@macgyver13  Did you use the same private key for scan and spend?"
  },
  {
   "t": "2025-07-27T15:32:33Z",
   "kind": "review_comment",
   "who": "macgyver13",
   "assoc": "NONE",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2231883781,
   "text": "This is the format I used to import scan and spend private keys:\nsp([fingerprint/352'/1'/0'/1'/0]WIF(private scan key),[fingerprint/352'/1'/0'/0'/0]WIF(private spend key)#checksum"
  },
  {
   "t": "2025-07-28T14:28:28Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_receiving.py",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2231890541,
   "text": "User descriptor keys do not follow any derivation specification. They can import descriptors with keys derived using any path."
  },
  {
   "t": "2025-07-28T18:26:46Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "test/functional/wallet_silentpayments_receiving.py",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2231890541,
   "text": "Per the BIP, it does specify `coin_type` (which is defined in BIP44). BIP44 does reserve `1` as a registered coin type for Bitcoin test networks (i.e., testnet, signet). Revisiting the language in the BIP, I'm realising this is not worded strongly enough and should be updated.\n\nI do think we should follow the convention of deriving mainnet keys and test keys from distinct chains in our tests. This also matches what we do in other functional tests, e.g., `wallet_descriptor.py`."
  },
  {
   "t": "2025-07-28T18:30:04Z",
   "kind": "review_comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "path": "test/functional/wallet_silentpayments_receiving.py",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2231890541,
   "text": "That's definitely a good idea. Some hardware wallets may even refuse to sign if the coin type derivation is wrong, e.g. to prevent a testnet app from moving mainnet coins."
  },
  {
   "t": "2025-07-30T11:05:15Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "1982c8f0ad812d301a4dc09fa3d05328688f0172"
  },
  {
   "t": "2025-07-30T11:12:09Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_receiving.py",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2231890541,
   "text": "I've changed this to use to `/352h/1h`. I also edited `GenerateWalletDescriptor` to use `/352h/1h` for test chain."
  },
  {
   "t": "2025-07-30T11:12:39Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_receiving.py",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2231169665,
   "text": "Done"
  },
  {
   "t": "2025-08-04T19:42:50Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "a7291beb65379b187118d2851784b60364d7d4ed"
  },
  {
   "t": "2025-08-12T15:41:26Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "d543c8770511a5d7acb0b4515aaf62eb4b46101f"
  },
  {
   "t": "2025-08-13T08:39:53Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "50fafd9cbec4bd7361bc74434967085d53061118"
  },
  {
   "t": "2025-08-13T09:04:44Z",
   "kind": "comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "text": "Rebased the base and sending PRs on master and fixed the static assert failure. Rebasing this on the sending PR should fix the CI failure."
  },
  {
   "t": "2025-08-13T11:19:27Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "01e275bdcc47319d94fcd3a5ab519277d7fe3a02"
  },
  {
   "t": "2025-08-13T11:24:07Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2231883781,
   "text": "@macgyver13 I changed the implementation and succeeded in removing the need for this code entirely"
  },
  {
   "t": "2025-08-13T16:23:03Z",
   "kind": "review_comment",
   "who": "macgyver13",
   "assoc": "NONE",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2231883781,
   "text": "I can confirm the import warning is resolved.  \ud83d\udc4f\n\nHowever when I try to generate a silent-payments address after importdescriptor I do generate an exception **Error: No silent-payments addresses available. (-12)**\n`imported_wallet.getnewaddress(address_type=\"silent-payments\")`"
  },
  {
   "t": "2025-08-14T07:58:01Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2231883781,
   "text": "I haven't been able to reproduce the error. Can you share the following information:\n- Your wallet creation parameters\n- Your `importdescriptors` parameters (without the private keys) and response\n?"
  },
  {
   "t": "2025-08-14T08:04:59Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "09277cbc63907d5566f50a3a3643862cd18c568d"
  },
  {
   "t": "2025-08-14T17:02:58Z",
   "kind": "review_comment",
   "who": "macgyver13",
   "assoc": "NONE",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2231883781,
   "text": "Great news, I was able to use dynamic descriptor creation -> export -> import using private keys and confirmed `imported_wallet.getnewaddress(address_type=\"silent-payments\")` now works as expected.\n\nStill have 1 issue when trying to use `sender.send(outputs={sp_addr: TOTAL_SPEND}, options=options)` in a different test - you can review the test [here](https://github.com/Eunovo/bitcoin/pull/2)"
  },
  {
   "t": "2025-08-15T12:26:50Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "We shouldn't need to mark this as override, considering IsRange on the DescriptorImpl is wrapping a lower IsRange call:\n\nhttps://github.com/bitcoin/bitcoin/blob/bd7e9026af484a0b0df4ef40800969860ffb5949/src/script/descriptor.cpp#L889-L898"
  },
  {
   "t": "2025-08-15T12:27:59Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207667539,
   "text": "Confirmed, considering we don't need ExpandPrivate anymore, this can remain `const final`."
  },
  {
   "t": "2025-08-15T12:47:12Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "nit: I was finding this function hard to follow while reviewing. I think something like this would be slightly more readable:\n\n```diff\ndiff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp\nindex 0bd2251e13..fb3252f398 100644\n--- a/src/script/descriptor.cpp\n+++ b/src/script/descriptor.cpp\n@@ -1674,26 +1674,28 @@ public:\n     {\n         FlatSigningProvider dummy;\n         std::string scan_key;\n-        bool has_scan_key{m_pubkey_args.at(0)->ToPrivateString(dummy, scan_key)};\n-        assert(has_scan_key); // The ScankeyPubkeyProvider always has the scan key\n-        std::string ret{m_name + \"(\" + scan_key + \",\"};\n-        auto& spend_pubkey{m_pubkey_args.at(1)};\n-        std::string tmp;\n+        // This should never fail, since the ScankeyPubkeyProvider will always contain\n+        // the scan key.\n+        //\n+        // The scan key is stored at m_pubkey_args[0], the spend key at m_pubkey_args[1]\n+        if (!m_pubkey_args.at(0)->ToPrivateString(dummy, scan_key)) return false;\n+        std::string scan_key_str{m_name + \"(\" + scan_key + \",\"};\n+        std::string spend_key_str;\n         switch (type) {\n         case StringType::NORMALIZED:\n-            if (!spend_pubkey->ToNormalizedString(*arg, tmp, cache)) return false;\n+            if (!m_pubkey_args.at(1)->ToNormalizedString(*arg, spend_key_str, cache)) return false;\n             break;\n         case StringType::PRIVATE:\n-            if (!spend_pubkey->ToPrivateString(*arg, tmp)) return false;\n+            if (!m_pubkey_args.at(1)->ToPrivateString(*arg, spend_key_str)) return false;\n             break;\n         case StringType::PUBLIC:\n-            tmp = spend_pubkey->ToString();\n+            spend_key_str = m_pubkey_args.at(1)->ToString();\n             break;\n         case StringType::COMPAT:\n-            tmp = spend_pubkey->ToString(PubkeyProvider::StringType::COMPAT);\n+            spend_key_str = m_pubkey_args.at(1)->ToString(PubkeyProvider::StringType::COMPAT);\n             break;\n         }\n-        out = std::move(ret) + std::move(tmp) + \")\";\n+        out = std::move(scan_key_str) + std::move(spend_key_str) + \")\";\n         return true;\n     }\n```"
  },
  {
   "t": "2025-08-15T12:56:41Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "Since we are creating the provider a few lines up, I think push_back is more appropriate here:\n\n```suggestion\n                ret.push_back(std::move(provider));\n```"
  },
  {
   "t": "2025-08-15T12:57:24Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "Same comment regarding push_back vs emplace_back"
  },
  {
   "t": "2025-08-15T12:59:42Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "Probably fine to leave all of these as plurals for now, e.g., `scan_pubkeys`, but I think its more appropriate to have these be `scan_pubkey` and `spend_pubkey` and have a comment explaining the silent payments descriptor does not support multipath descriptors. We could even add an assert for this, since we expect a silent payments descriptor to only ever have one scan key and one spend key."
  },
  {
   "t": "2025-08-15T13:05:11Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "I don't have a better alternative to recommend, but this feels a bit off. As discussed offline, an alternative we can look into is subclassing the Descriptor class, e.g., `SilentPaymentsDescriptor` and adding a new method just for getting the scan key.\n\nPerhaps another direction worth considering is modelling the scan key as an `ExtPubKey`, where the scan key is saved as a member (similar to how the chaincode is treated)."
  },
  {
   "t": "2025-08-15T13:07:12Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2278956651,
   "text": "Another idea: add a new method to the descriptor class , `GetPubKeyProviders` ? This avoids needing to subclass just for silent payments, and may prove to be a generally useful method. This way, we can return the ScankeyPubkeyProvider and access the scan \"private\" key directly from that."
  },
  {
   "t": "2025-08-15T13:12:11Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/interfaces/chain.h",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "I'm curious if there is another use case for undoData outside of Silent payments. If so, we could break this out into its own commit. Might be worth doing anyways, even if silent payments is (currently) the only use case."
  },
  {
   "t": "2025-08-15T13:13:37Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/walletutil.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2207750518,
   "text": "The alternative method seems preferable to me. I dont see any reason to treat the spend key differently from other keys in the wallet."
  },
  {
   "t": "2025-08-15T13:17:18Z",
   "kind": "review",
   "who": "josibake",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "09277cbc63907d5566f50a3a3643862cd18c568d",
   "text": "Looks much better now that you added `ScankeyPubkeyProvider`. We could even just call this a `SilentPaymentsPubKeyProvider`, which is perhaps a bit less confusing for reviewers who are less familiar with the details of how silent payments work. Reviewed up until the `SilentPaymentsSPKMan` commit and onward."
  },
  {
   "t": "2025-08-18T07:22:40Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "4b4970427ea51f93308eade67368f3d44e8a999d"
  },
  {
   "t": "2025-08-18T08:35:13Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "f86b9d208e79e153dbc218d66c5a62ce372ee139"
  },
  {
   "t": "2025-08-18T08:35:23Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2278902423,
   "text": "Done"
  },
  {
   "t": "2025-08-18T08:36:23Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2278930453,
   "text": "Done"
  },
  {
   "t": "2025-08-18T08:37:52Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2278944819,
   "text": "Done"
  },
  {
   "t": "2025-08-18T08:38:01Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/script/descriptor.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2278945918,
   "text": "Done"
  },
  {
   "t": "2025-08-18T12:17:45Z",
   "kind": "comment",
   "who": "macgyver13",
   "assoc": "NONE",
   "text": "@Eunovo Nice work on addressing the issues identified in previous tests.  All of those are working as expected now.\n\nI am including a patch that adds 2 more failing tests when adding silent-payments address in the transaction output:\nself.test_sendrawtransaction()\nself.test_mixed_output_types()\n\n[test_sp_receive.patch](https://github.com/user-attachments/files/21834964/test_sp_receive.patch)"
  },
  {
   "t": "2025-08-19T13:09:04Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nI think these might be more appropriate for the sending PR https://github.com/bitcoin/bitcoin/pull/28201 cc @josibake"
  },
  {
   "t": "2025-08-19T14:08:55Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "7150948e694a3ec8420a39ff9530b70e0a8d6c07"
  },
  {
   "t": "2025-08-19T14:28:12Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "Some Major Updates:\n- The `SilentPaymentDescriptorScriptPubKeyMan` now obtains the scan key through a `GetScanKey` method, only available on Silent Payment descriptors\n- The spend key is no longer derived during descriptor parsing; it now has to be \"expanded\" the same way other descriptors are expanded\n- `LoadKeysAndChangeLabel` has been replaced with an overridden `TopUpWithDB` method. The wallet calls `TopUp` when it wants the SPKMans to derive and load new keys and scripts."
  },
  {
   "t": "2025-09-05T14:23:29Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "You mention it in the commit message, but I think its worth adding a detailed comment above that:\n\n* Explains the nuance around `m_scan_key`\n* Explains why we are using a `PubKeyProvider`, e.g., getting origin information without needing to write custom code\n\nI think a comment is slightly better than a commit message as I imagine this will trip people up in the future who are looking at this code and surprised to see a private key as a member field inside a pubkey provider."
  },
  {
   "t": "2025-09-05T14:25:54Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "In `ToPrivateString` above , you omit the argument name to indicate its not used; should do the same here:\n\n```suggestion\n    void GetPrivKey(int, const SigningProvider&, FlatSigningProvider& out) const override\n```"
  },
  {
   "t": "2025-09-05T14:29:51Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2278949369,
   "text": "Revisiting this, it would be nice to if we enforce that an SP descriptor cannot be multipath. Beyond that, I think its fine to keep the plurals and for loops, since that matches the style of the rest of the wallet code."
  },
  {
   "t": "2025-09-05T14:31:40Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/script/descriptor.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "I'm still curious if we could avoid the public SpDescriptor, since its only needed for this GetScanKey function. That being said, this also seems fine and does help avoid us needing to special case and write custom code in other places."
  },
  {
   "t": "2025-09-05T14:34:37Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/pubkey.cpp",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "This is only used to recreate the silent payment taproot scriptpubkeys, i.e., $B_{spend} + tweak \\cdot G$. But since we already have the full scriptpubkey when scanning, we could just save the tweak and scriptpubkey to the database.\n\nThis means more storage, but then we can drop this `CPubKey::TweakAdd` method. This seems better to me because storage is cheap, this should make loading the wallet faster, and it removes a footgun from CPubKey (we dont really want to have a generic method for adding public keys in this codebase)."
  },
  {
   "t": "2025-09-05T14:36:15Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/key.h",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": null,
   "text": "I think we could also remove this function by introducing a `SilentPaymentsSign` function (similar to how we have a taproot sign function). I'll dig into this a bit more, but it seems better to have a special signing function that can _only_ be used for silent payments, instead of a generic `CKey::TweakAdd` function that might be abused/footgunny."
  },
  {
   "t": "2025-09-05T14:37:29Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/interfaces/chain.h",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2278966398,
   "text": "Reiterating this point. I think I've seen a few PRs related to undodata recently, seems like a good time to bundle all of them as a well motivated refactor? cc @TheCharlatan"
  },
  {
   "t": "2025-09-05T14:43:39Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/spend.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "Not quite sure why this is necessary?"
  },
  {
   "t": "2025-09-05T14:45:54Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/spend.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": null,
   "text": "Not a comment for this commit specifically, but I do think we should document either in a commit or in a commit message the entire logic and flow of using silent payments for change. Its a bit complicated and without a clear understanding of all of the cases we need to cover, these changes are a bit hard to follow."
  },
  {
   "t": "2025-09-05T14:46:25Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/wallet/spend.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2325303247,
   "text": "Even better, if we dont have one already, we can create a test case for all of the possible change scenarios and document there."
  },
  {
   "t": "2025-09-05T14:48:36Z",
   "kind": "review",
   "who": "josibake",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "7150948e694a3ec8420a39ff9530b70e0a8d6c07",
   "text": "Looking good! Really nice to see you were able to remove a lot of custom code related to how we handle the scan and spend keys. Left some comments/questions below."
  },
  {
   "t": "2025-09-05T14:51:01Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/script/descriptor.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2325267495,
   "text": "Maybe we can use a namespace?"
  },
  {
   "t": "2025-09-05T14:55:45Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/spend.cpp",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "in_reply_to": 2325296901,
   "text": "We need it to extract the `change_dest` from the results of `CreateSilentPaymentOutputs`."
  },
  {
   "t": "2025-09-09T05:38:49Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "891b8dd679c1c0258b0f97093fcbddfdb70b2136"
  },
  {
   "t": "2025-09-09T08:24:58Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/key.h",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157",
   "in_reply_to": 2325279070,
   "text": "FYI, I have a WIP commit that implements a `SilentPaymentsSign` function, I'll push the commit later today. Its a bit more code than what we have with `CKey::TweakAdd`, but I do like that its silent payments specific and can't be used as a footgun."
  },
  {
   "t": "2025-09-11T09:34:37Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "cc0b97b7879a73b9341bf88391312799be91439a"
  },
  {
   "t": "2025-09-17T16:10:40Z",
   "kind": "comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "text": "Lightly tested cc0b97b7879a73b9341bf88391312799be91439a by creating a fresh wallet in the GUI, importing my earlier silent payment descriptor and rescanning to find my funds. I managed to send some coin and checked that the change went back to the descriptor (there are no other descriptors in the wallet).\n\nWhen I tried to import it into a fresh watch-only wallet I got:\n\n[quoted text omitted]\nIt would be nicer if it just toggled the flag; I don't think anyone would accidentally perform such an import - and the flag is immutable via `setwalletflag`. Other than that the watch-only import worked fine (using the output from `listdescriptors`, which helpfully contained the scan key)."
  },
  {
   "t": "2025-09-18T13:36:00Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\n@Sjors Did you mean the flag is \"mutable\" via `setwalletflag`?\n\nI don't have anything against automatically toggling silent-payments flag when a silent payment descriptor is imported.\n@josibake WDYT?"
  },
  {
   "t": "2025-09-18T13:45:10Z",
   "kind": "comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "text": "@Eunovo when I call `setwalletflag` it fails, saying the flag is immutable. I'm fine with either solution:\n1. Make it mutable; or\n2. Set it when importing an sp descriptor"
  },
  {
   "t": "2025-09-18T14:12:24Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "55485a679d70a9bba11d556df7aa8ee4b98b7157"
  },
  {
   "t": "2025-09-18T14:17:12Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "I changed `CKey::TweakAdd()` to `CKey::ComputeBIP352Key()`"
  },
  {
   "t": "2025-09-19T12:05:33Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nIt later occurred to me that we shouldn't do this because setting the silent-payments flag also disables \"fast rescan\"; the user needs to make a conscious decision to enable silent-payments and disable \"fast rescan\" in the process.\n\nMaking it possible to toggle \"silent-payments\" via \"setwalletflag\" makes more sense to me, but then we have to also worry about what we should do when a user disables \"silent-payments\", but they have silent-payment descriptors in their wallet.\n\ncc @Sjors @josibake"
  },
  {
   "t": "2025-12-01T10:00:36Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "fcc8b88ffd4fd565d01617f533c60beb83a3e461"
  },
  {
   "t": "2025-12-01T10:13:37Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "3bfab00d166c45c37f1056abcdbee2e59a882776"
  },
  {
   "t": "2026-02-08T19:23:44Z",
   "kind": "comment",
   "who": "PedroRosalba",
   "assoc": "NONE",
   "text": "hey guys what is the status of this - is it stopped? in case it's ongoing, are there any blockers?"
  },
  {
   "t": "2026-02-09T08:35:13Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nThe major blocker is https://github.com/bitcoin-core/secp256k1/issues/1799. We need this issue to be resolved so we can get the BIP352 primitives into a libsecp256k1 release"
  },
  {
   "t": "2026-02-10T15:49:41Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "9ecf265213b2b5aad530d1cbd34e52f659fe64b6"
  },
  {
   "t": "2026-05-14T12:01:04Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "0be2272cfcc3cb5cd1d75e735b548202cb10a96e"
  },
  {
   "t": "2026-05-14T13:20:36Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "8c0eb4efae8364bc1eadc9d0b2cd3b596730fb19"
  },
  {
   "t": "2026-05-15T11:44:52Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "877722cf9b1838c3ccb72fe9f5794ef285327ab5"
  },
  {
   "t": "2026-05-16T03:39:15Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4"
  },
  {
   "t": "2026-06-27T13:08:41Z",
   "kind": "review_comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_receiving.py",
   "commit": "ffa0e15a8359cd1c71e74f21f157c0d6f28eedb6",
   "in_reply_to": null,
   "text": "In ffa0e15a8359cd1c71e74f21f157c0d6f28eedb6 \"tests: add silent payments receiving functional tests\"\n\n[quoted text omitted]\nSimilar to the suggestion in the sending PR, this should not be required."
  },
  {
   "t": "2026-06-27T13:09:24Z",
   "kind": "review_comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_receiving.py",
   "commit": "ffa0e15a8359cd1c71e74f21f157c0d6f28eedb6",
   "in_reply_to": null,
   "text": "In ffa0e15 \"tests: add silent payments receiving functional tests\"\n\nIt looks like do_nothing() is a duplicate of no_op() that's present in the testing framework?"
  },
  {
   "t": "2026-06-27T13:10:06Z",
   "kind": "review_comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_receiving.py",
   "commit": "ffa0e15a8359cd1c71e74f21f157c0d6f28eedb6",
   "in_reply_to": null,
   "text": "In ffa0e15 \"tests: add silent payments receiving functional tests\"\n\nLet's avoid hardcoding the descriptor checksum and instead use the `descsum_create` utility function."
  },
  {
   "t": "2026-06-27T13:15:13Z",
   "kind": "review",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "c773e166285f085fc77203b879d64c6b541219e4",
   "text": "Partial review of the testing commit ffa0e15 \"tests: add silent payments receiving functional tests\".\n\nSince this PR is stacked over two open PRs at the moment, this feedback can be addressed when it's rebased. I shared because these caught my attention while giving a cursory glance at the test."
  }
 ],
 "labels_log": [
  {
   "t": "2025-07-14T10:32:41Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2025-07-20T09:35:03Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2025-07-22T12:16:15Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2025-07-23T10:27:58Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-07-25T06:04:46Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-07-25T19:34:13Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2025-07-28T13:22:14Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-08-04T20:17:23Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-08-12T19:42:25Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2025-08-13T14:24:06Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2025-08-13T20:32:35Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-08-14T09:23:23Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-08-14T19:53:25Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-09-09T06:00:10Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-10-19T15:07:12Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-12-01T10:14:04Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2025-12-01T10:43:11Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-12-01T11:46:06Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2025-12-16T15:36:01Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-05-14T13:26:08Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-05-14T14:51:11Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-05-16T05:39:43Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-05-22T04:18:22Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 39167,
 "text_tokens_estimate": 9791,
 "changed_paths": [
  "src/CMakeLists.txt",
  "src/addresstype.cpp",
  "src/addresstype.h",
  "src/bech32.h",
  "src/common/bip352.cpp",
  "src/common/bip352.h",
  "src/interfaces/chain.h",
  "src/interfaces/wallet.h",
  "src/kernel/chainparams.cpp",
  "src/kernel/chainparams.h",
  "src/key.cpp",
  "src/key.h",
  "src/key_io.cpp",
  "src/node/interfaces.cpp",
  "src/outputtype.cpp",
  "src/outputtype.h",
  "src/policy/fees/block_policy_estimator.cpp",
  "src/policy/fees/block_policy_estimator.h",
  "src/pubkey.cpp",
  "src/qt/createwalletdialog.cpp",
  "src/qt/createwalletdialog.h",
  "src/qt/forms/createwalletdialog.ui",
  "src/qt/receivecoinsdialog.cpp",
  "src/qt/walletcontroller.cpp",
  "src/rpc/client.cpp",
  "src/rpc/util.cpp",
  "src/script/descriptor.cpp",
  "src/script/descriptor.h",
  "src/secp256k1/.github/workflows/ci.yml",
  "src/secp256k1/.gitignore",
  "src/secp256k1/CMakeLists.txt",
  "src/secp256k1/Makefile.am",
  "src/secp256k1/README.md",
  "src/secp256k1/ci/ci.sh",
  "src/secp256k1/ci/linux-debian.Dockerfile",
  "src/secp256k1/configure.ac",
  "src/secp256k1/examples/CMakeLists.txt",
  "src/secp256k1/examples/silentpayments.c",
  "src/secp256k1/include/secp256k1_silentpayments.h",
  "src/secp256k1/src/CMakeLists.txt",
  "src/secp256k1/src/bench.c",
  "src/secp256k1/src/bench.h",
  "src/secp256k1/src/ctime_tests.c",
  "src/secp256k1/src/modules/musig/session_impl.h",
  "src/secp256k1/src/modules/silentpayments/Makefile.am.include",
  "src/secp256k1/src/modules/silentpayments/bench_impl.h",
  "src/secp256k1/src/modules/silentpayments/bip352_send_and_receive_test_vectors.json",
  "src/secp256k1/src/modules/silentpayments/main_impl.h",
  "src/secp256k1/src/modules/silentpayments/tests_impl.h",
  "src/secp256k1/src/modules/silentpayments/vectors.h",
  "src/secp256k1/src/secp256k1.c",
  "src/secp256k1/src/tests.c",
  "src/secp256k1/tools/tests_silentpayments_generate.py",
  "src/test/CMakeLists.txt",
  "src/test/bip352_tests.cpp",
  "src/test/data/bip352_send_and_receive_vectors.json",
  "src/test/descriptor_tests.cpp",
  "src/test/fuzz/package_eval.cpp",
  "src/test/fuzz/script.cpp",
  "src/test/fuzz/tx_pool.cpp",
  "src/test/fuzz/util.cpp",
  "src/test/fuzz/util/wallet.h",
  "src/test/policyestimator_tests.cpp",
  "src/test/transaction_tests.cpp",
  "src/validation.cpp",
  "src/validationinterface.cpp",
  "src/validationinterface.h",
  "src/wallet/coincontrol.h",
  "src/wallet/interfaces.cpp",
  "src/wallet/rpc/addresses.cpp",
  "src/wallet/rpc/backup.cpp",
  "src/wallet/rpc/spend.cpp",
  "src/wallet/rpc/wallet.cpp",
  "src/wallet/scriptpubkeyman.cpp",
  "src/wallet/scriptpubkeyman.h",
  "src/wallet/spend.cpp",
  "src/wallet/spend.h",
  "src/wallet/test/util.cpp",
  "src/wallet/test/wallet_tests.cpp",
  "src/wallet/types.h",
  "src/wallet/wallet.cpp",
  "src/wallet/wallet.h",
  "src/wallet/walletdb.cpp",
  "src/wallet/walletdb.h",
  "src/wallet/walletutil.cpp",
  "src/wallet/walletutil.h",
  "src/zmq/zmqnotificationinterface.cpp",
  "src/zmq/zmqnotificationinterface.h",
  "test/functional/rpc_getdescriptorinfo.py",
  "test/functional/test_runner.py",
  "test/functional/wallet_anchor.py",
  "test/functional/wallet_fast_rescan.py",
  "test/functional/wallet_silentpayments_receiving.py",
  "test/functional/wallet_silentpayments_sending.py"
 ],
 "files": [
  {
   "path": "src/CMakeLists.txt",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/addresstype.cpp",
   "add": 5,
   "del": 0
  },
  {
   "path": "src/addresstype.h",
   "add": 20,
   "del": 1
  },
  {
   "path": "src/bech32.h",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/common/bip352.cpp",
   "add": 372,
   "del": 0
  },
  {
   "path": "src/common/bip352.h",
   "add": 161,
   "del": 0
  },
  {
   "path": "src/interfaces/chain.h",
   "add": 8,
   "del": 1
  },
  {
   "path": "src/interfaces/wallet.h",
   "add": 3,
   "del": 0
  },
  {
   "path": "src/kernel/chainparams.cpp",
   "add": 5,
   "del": 0
  },
  {
   "path": "src/kernel/chainparams.h",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/key.cpp",
   "add": 10,
   "del": 1
  },
  {
   "path": "src/key.h",
   "add": 19,
   "del": 0
  },
  {
   "path": "src/key_io.cpp",
   "add": 45,
   "del": 3
  },
  {
   "path": "src/node/interfaces.cpp",
   "add": 13,
   "del": 3
  },
  {
   "path": "src/outputtype.cpp",
   "add": 5,
   "del": 0
  },
  {
   "path": "src/outputtype.h",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/policy/fees/block_policy_estimator.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/policy/fees/block_policy_estimator.h",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/pubkey.cpp",
   "add": 0,
   "del": 1
  },
  {
   "path": "src/qt/createwalletdialog.cpp",
   "add": 9,
   "del": 0
  },
  {
   "path": "src/qt/createwalletdialog.h",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/qt/forms/createwalletdialog.ui",
   "add": 10,
   "del": 0
  },
  {
   "path": "src/qt/receivecoinsdialog.cpp",
   "add": 3,
   "del": 0
  },
  {
   "path": "src/qt/walletcontroller.cpp",
   "add": 3,
   "del": 0
  },
  {
   "path": "src/rpc/client.cpp",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/rpc/util.cpp",
   "add": 7,
   "del": 0
  },
  {
   "path": "src/script/descriptor.cpp",
   "add": 175,
   "del": 2
  },
  {
   "path": "src/script/descriptor.h",
   "add": 9,
   "del": 0
  },
  {
   "path": "src/secp256k1/.github/workflows/ci.yml",
   "add": 28,
   "del": 18
  },
  {
   "path": "src/secp256k1/.gitignore",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/secp256k1/CMakeLists.txt",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/secp256k1/Makefile.am",
   "add": 25,
   "del": 0
  },
  {
   "path": "src/secp256k1/README.md",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/secp256k1/ci/ci.sh",
   "add": 2,
   "del": 1
  },
  {
   "path": "src/secp256k1/ci/linux-debian.Dockerfile",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/secp256k1/configure.ac",
   "add": 14,
   "del": 0
  },
  {
   "path": "src/secp256k1/examples/CMakeLists.txt",
   "add": 4,
   "del": 0
  },
  {
   "path": "src/secp256k1/examples/silentpayments.c",
   "add": 463,
   "del": 0
  },
  {
   "path": "src/secp256k1/include/secp256k1_silentpayments.h",
   "add": 400,
   "del": 0
  },
  {
   "path": "src/secp256k1/src/CMakeLists.txt",
   "add": 9,
   "del": 0
  },
  {
   "path": "src/secp256k1/src/bench.c",
   "add": 47,
   "del": 17
  },
  {
   "path": "src/secp256k1/src/bench.h",
   "add": 3,
   "del": 3
  },
  {
   "path": "src/secp256k1/src/ctime_tests.c",
   "add": 78,
   "del": 0
  },
  {
   "path": "src/secp256k1/src/modules/musig/session_impl.h",
   "add": 2,
   "del": 4
  },
  {
   "path": "src/secp256k1/src/modules/silentpayments/Makefile.am.include",
   "add": 5,
   "del": 0
  },
  {
   "path": "src/secp256k1/src/modules/silentpayments/bench_impl.h",
   "add": 227,
   "del": 0
  },
  {
   "path": "src/secp256k1/src/modules/silentpayments/bip352_send_and_receive_test_vectors.json",
   "add": 5729,
   "del": 0
  },
  {
   "path": "src/secp256k1/src/modules/silentpayments/main_impl.h",
   "add": 782,
   "del": 0
  },
  {
   "path": "src/secp256k1/src/modules/silentpayments/tests_impl.h",
   "add": 844,
   "del": 0
  },
  {
   "path": "src/secp256k1/src/modules/silentpayments/vectors.h",
   "add": 4550,
   "del": 0
  },
  {
   "path": "src/secp256k1/src/secp256k1.c",
   "add": 4,
   "del": 0
  },
  {
   "path": "src/secp256k1/src/tests.c",
   "add": 7,
   "del": 0
  },
  {
   "path": "src/secp256k1/tools/tests_silentpayments_generate.py",
   "add": 301,
   "del": 0
  },
  {
   "path": "src/test/CMakeLists.txt",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/test/bip352_tests.cpp",
   "add": 202,
   "del": 0
  },
  {
   "path": "src/test/data/bip352_send_and_receive_vectors.json",
   "add": 2760,
   "del": 0
  },
  {
   "path": "src/test/descriptor_tests.cpp",
   "add": 52,
   "del": 0
  },
  {
   "path": "src/test/fuzz/package_eval.cpp",
   "add": 2,
   "del": 2
  },
  {
   "path": "src/test/fuzz/script.cpp",
   "add": 9,
   "del": 1
  },
  {
   "path": "src/test/fuzz/tx_pool.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/test/fuzz/util.cpp",
   "add": 5,
   "del": 0
  },
  {
   "path": "src/test/fuzz/util/wallet.h",
   "add": 2,
   "del": 1
  },
  {
   "path": "src/test/policyestimator_tests.cpp",
   "add": 3,
   "del": 3
  },
  {
   "path": "src/test/transaction_tests.cpp",
   "add": 2,
   "del": 2
  },
  {
   "path": "src/validation.cpp",
   "add": 9,
   "del": 3
  },
  {
   "path": "src/validationinterface.cpp",
   "add": 3,
   "del": 3
  },
  {
   "path": "src/validationinterface.h",
   "add": 3,
   "del": 2
  },
  {
   "path": "src/wallet/coincontrol.h",
   "add": 3,
   "del": 1
  },
  {
   "path": "src/wallet/interfaces.cpp",
   "add": 4,
   "del": 0
  },
  {
   "path": "src/wallet/rpc/addresses.cpp",
   "add": 2,
   "del": 1
  },
  {
   "path": "src/wallet/rpc/backup.cpp",
   "add": 5,
   "del": 1
  },
  {
   "path": "src/wallet/rpc/spend.cpp",
   "add": 29,
   "del": 1
  },
  {
   "path": "src/wallet/rpc/wallet.cpp",
   "add": 8,
   "del": 1
  },
  {
   "path": "src/wallet/scriptpubkeyman.cpp",
   "add": 249,
   "del": 2
  },
  {
   "path": "src/wallet/scriptpubkeyman.h",
   "add": 55,
   "del": 5
  },
  {
   "path": "src/wallet/spend.cpp",
   "add": 213,
   "del": 34
  },
  {
   "path": "src/wallet/spend.h",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/wallet/test/util.cpp",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/wallet/test/wallet_tests.cpp",
   "add": 21,
   "del": 0
  },
  {
   "path": "src/wallet/types.h",
   "add": 6,
   "del": 2
  },
  {
   "path": "src/wallet/wallet.cpp",
   "add": 170,
   "del": 19
  },
  {
   "path": "src/wallet/wallet.h",
   "add": 14,
   "del": 7
  },
  {
   "path": "src/wallet/walletdb.cpp",
   "add": 27,
   "del": 0
  },
  {
   "path": "src/wallet/walletdb.h",
   "add": 3,
   "del": 0
  },
  {
   "path": "src/wallet/walletutil.cpp",
   "add": 53,
   "del": 11
  },
  {
   "path": "src/wallet/walletutil.h",
   "add": 7,
   "del": 1
  },
  {
   "path": "src/zmq/zmqnotificationinterface.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/zmq/zmqnotificationinterface.h",
   "add": 1,
   "del": 1
  },
  {
   "path": "test/functional/rpc_getdescriptorinfo.py",
   "add": 2,
   "del": 0
  },
  {
   "path": "test/functional/test_runner.py",
   "add": 2,
   "del": 0
  },
  {
   "path": "test/functional/wallet_anchor.py",
   "add": 1,
   "del": 1
  },
  {
   "path": "test/functional/wallet_fast_rescan.py",
   "add": 6,
   "del": 0
  },
  {
   "path": "test/functional/wallet_silentpayments_receiving.py",
   "add": 391,
   "del": 0
  },
  {
   "path": "test/functional/wallet_silentpayments_sending.py",
   "add": 201,
   "del": 0
  }
 ],
 "test_lines": 3676,
 "git": {
  "head": "c773e166285f085fc77203b879d64c6b541219e4",
  "head_matches_backup": true,
  "base": "ed1795aa17205db6ac15fa7ea1645357740b26ac",
  "commits": [
   {
    "sha": "bb1bce36cf",
    "subject": "Squashed 'src/secp256k1/' changes from 7262adb4b4..14be7f2abe",
    "files": 25,
    "add": 13530,
    "del": 44
   },
   {
    "sha": "ece2374760",
    "subject": "Merge commit 'bb1bce36cf8b9292a65f0f03ab855e7133357b9f' into new-sp-base",
    "files": 25,
    "add": 13530,
    "del": 44
   },
   {
    "sha": "bccfd81105",
    "subject": "crypto: add read-only method to KeyPair",
    "files": 1,
    "add": 13,
    "del": 0
   },
   {
    "sha": "602835e080",
    "subject": "Add \"sp\" HRP",
    "files": 2,
    "add": 7,
    "del": 0
   },
   {
    "sha": "ba4b734ec8",
    "subject": "Add V0SilentPaymentDestination address type",
    "files": 9,
    "add": 93,
    "del": 7
   },
   {
    "sha": "6355a90494",
    "subject": "common: add bip352.{h,cpp} secp256k1 module",
    "files": 4,
    "add": 532,
    "del": 1
   },
   {
    "sha": "e12280b9d6",
    "subject": "wallet: disable sending to silent payment address",
    "files": 2,
    "add": 8,
    "del": 1
   },
   {
    "sha": "0520567fb5",
    "subject": "tests: add BIP352 test vectors as unit tests",
    "files": 3,
    "add": 2964,
    "del": 0
   },
   {
    "sha": "209b40626a",
    "subject": "wallet: get serialized size for `V0SilentPayments`",
    "files": 1,
    "add": 14,
    "del": 2
   },
   {
    "sha": "f9a10e9ea9",
    "subject": "wallet: add method for retreiving a private key",
    "files": 2,
    "add": 28,
    "del": 0
   },
   {
    "sha": "e3ef349ad5",
    "subject": "wallet: make coin selection silent payment aware",
    "files": 3,
    "add": 59,
    "del": 2
   },
   {
    "sha": "9898826eef",
    "subject": "wallet: add `IsInputForSharedSecretDerivation` function",
    "files": 1,
    "add": 45,
    "del": 0
   },
   {
    "sha": "efbdd793f5",
    "subject": "wallet: add `CreateSilentPaymentOutputs` function",
    "files": 1,
    "add": 63,
    "del": 2
   },
   {
    "sha": "334c36a2e5",
    "subject": "wallet: update TransactionChangeType",
    "files": 1,
    "add": 1,
    "del": 1
   },
   {
    "sha": "71bfa7d3ef",
    "subject": "wallet: enable sending to silent payment address",
    "files": 4,
    "add": 8,
    "del": 8
   },
   {
    "sha": "03c835dbd6",
    "subject": "tests: add sending functional tests",
    "files": 2,
    "add": 202,
    "del": 0
   },
   {
    "sha": "cc5138cfe4",
    "subject": "Add OutputType::SILENT_PAYMENTS",
    "files": 6,
    "add": 14,
    "del": 2
   },
   {
    "sha": "c8c6cebc60",
    "subject": "descriptors: impl ScankeyPubkeyProvider",
    "files": 1,
    "add": 44,
    "del": 0
   },
   {
    "sha": "afcac37e1c",
    "subject": "descriptor: implement sp(scan, spend) desc",
    "files": 2,
    "add": 168,
    "del": 2
   },
   {
    "sha": "3e7686cac1",
    "subject": "descriptor: add SPDescriptor public interface",
    "files": 2,
    "add": 25,
    "del": 8
   },
   {
    "sha": "155b6a72f0",
    "subject": "key: add ComputeBIP352Key() method",
    "files": 3,
    "add": 15,
    "del": 1
   },
   {
    "sha": "486f45b712",
    "subject": "notifications: Add spent_coins to tx added notification",
    "files": 14,
    "add": 36,
    "del": 24
   },
   {
    "sha": "3a035a4be7",
    "subject": "interfaces: Load block undo data",
    "files": 2,
    "add": 12,
    "del": 0
   },
   {
    "sha": "62de0f0e8f",
    "subject": "wallet: generate sp() descriptor",
    "files": 4,
    "add": 27,
    "del": 16
   },
   {
    "sha": "05e32ed53e",
    "subject": "bip352: Make SilentPaymentOuput serializable",
    "files": 1,
    "add": 3,
    "del": 0
   },
   {
    "sha": "35b5e7b2a2",
    "subject": "wallet: create SilentPaymentDescriptorScriptPubKeyMan",
    "files": 6,
    "add": 294,
    "del": 8
   },
   {
    "sha": "865ff19b65",
    "subject": "wallet: scan for silent payments",
    "files": 4,
    "add": 116,
    "del": 13
   },
   {
    "sha": "7dd06e4907",
    "subject": "wallet/rpc: add create silent-payments wallet option",
    "files": 3,
    "add": 14,
    "del": 3
   },
   {
    "sha": "51b161fe22",
    "subject": "wallet: disable fast rescan for silent_payments wallet",
    "files": 3,
    "add": 10,
    "del": 2
   },
   {
    "sha": "82820d18c8",
    "subject": "wallet: import silent payments descriptor",
    "files": 2,
    "add": 12,
    "del": 3
   },
   {
    "sha": "ffa0e15a83",
    "subject": "tests: add silent payments receiving functional tests",
    "files": 3,
    "add": 294,
    "del": 0
   },
   {
    "sha": "5c4df46bc0",
    "subject": "wallet/rpc: add sp-address support to getaddressinfo",
    "files": 7,
    "add": 82,
    "del": 2
   },
   {
    "sha": "0429f1c0c2",
    "subject": "update addressbook with found silent-payment outputs",
    "files": 4,
    "add": 63,
    "del": 12
   },
   {
    "sha": "7f096ee8de",
    "subject": "use silent payments change when sending",
    "files": 4,
    "add": 48,
    "del": 26
   },
   {
    "sha": "342564a27a",
    "subject": "wallet/spend: Filter out coins not eligible to pay sp change dest",
    "files": 2,
    "add": 8,
    "del": 4
   },
   {
    "sha": "75ac51878f",
    "subject": "wallet: retry CreateTransaction without silent_payments change",
    "files": 4,
    "add": 34,
    "del": 13
   },
   {
    "sha": "0d3caba2a9",
    "subject": "wallet: prefer silent_payments over Bech32m as fallback change type",
    "files": 2,
    "add": 12,
    "del": 2
   },
   {
    "sha": "933622e393",
    "subject": "wallet/tests: Enable Silent Payments in wallet unit tests",
    "files": 2,
    "add": 23,
    "del": 1
   },
   {
    "sha": "a03970ce43",
    "subject": "wallet/gui: add silent_payments option to createwalletdialog",
    "files": 4,
    "add": 23,
    "del": 0
   },
   {
    "sha": "3512425509",
    "subject": "wallet/gui: add silent-payments to address type dropdown",
    "files": 3,
    "add": 10,
    "del": 0
   },
   {
    "sha": "c773e16628",
    "subject": "tests: silent-payments wallet coin control",
    "files": 1,
    "add": 45,
    "del": 0
   }
  ],
  "patch_truncated": true
 },
 "input_hash": "4a9588831aa09450",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}