{
 "number": 35302,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35302",
 "title": "Silent Payments:  Sending (take 2)",
 "author": "Eunovo",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-05-16T04:16:08Z",
 "updated_at": "2026-08-04T22:56:42Z",
 "age_days": 124,
 "draft": true,
 "labels": [
  "Needs rebase"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "4ad3cbf575b839bff1a801fcf5c1fca70b0fe939",
 "head_ref": "implement-bip352-sending",
 "head_repo": "Eunovo/bitcoin",
 "head_history": [
  {
   "t": "2026-06-07T11:07:30Z",
   "sha": "5859ac2c97a00ff9a973827237207022204aafa9"
  },
  {
   "t": "2026-06-07T11:10:23Z",
   "sha": "16f3a0bc13c8052559f3188c91424a6ff5e20ab5"
  },
  {
   "t": "2026-06-07T21:43:44Z",
   "sha": "ecd667cbad3b0bea677d055caf7b5f5d0740e859"
  },
  {
   "t": "2026-06-08T08:06:33Z",
   "sha": "b3e7ab7567960f69c9a2261975e39689c2207db6"
  },
  {
   "t": "2026-06-08T17:54:19Z",
   "sha": "dffaa357ae583735a84eb4f006e9a7cbdbe49f74"
  },
  {
   "t": "2026-06-23T14:51:35Z",
   "sha": "b5fe282fb913eb16e634cf3a49b7d6673d374be7"
  },
  {
   "t": "2026-06-24T13:12:45Z",
   "sha": "989d3548c6933a4bc31b82a6f950029440e1d232"
  },
  {
   "t": "2026-06-26T08:18:47Z",
   "sha": "57209f9ba6c3b9aa0e3489e5d84765a93f059f54"
  },
  {
   "t": "2026-06-26T09:38:01Z",
   "sha": "2616ee0424b8a26bf54ba472bf6f3fa4e62a9f97"
  },
  {
   "t": "2026-06-26T09:42:16Z",
   "sha": "05101f3f0eb9b41f4d19f4286388a1b1e7770646"
  },
  {
   "t": "2026-06-26T09:51:13Z",
   "sha": "22e42cb9b58a3406ab1870be71aa38f861fbba4d"
  },
  {
   "t": "2026-06-29T09:13:14Z",
   "sha": "9e6b4d7b7c8b3ce622d0d321c51a2c4c57803a98"
  },
  {
   "t": "2026-07-01T06:40:24Z",
   "sha": "6cc51d0ab0c9a1037662b791dab7c45039981d05"
  },
  {
   "t": "2026-07-07T12:28:56Z",
   "sha": "ebb7ba4f5d31dac9eee3eb225f0aa3778ae0d9b7"
  },
  {
   "t": "2026-07-24T15:17:21Z",
   "sha": "4ad3cbf575b839bff1a801fcf5c1fca70b0fe939"
  }
 ],
 "additions": 8745,
 "deletions": 114,
 "changed_files": 47,
 "commit_count": 18,
 "size_bucket": "XL",
 "mergeable_state": "dirty",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "rkrux",
      "url": "https://github.com/bitcoin/bitcoin/pull/35302#issuecomment-4496579793"
     }
    ]
   },
   "conflicts": [
    {
     "number": 35861,
     "title": "Testnet 5 (BIP95)",
     "author": "fjahr"
    },
    {
     "number": 35819,
     "title": "test: add coverage for untested descriptor parse error paths",
     "author": "azuchi"
    },
    {
     "number": 35793,
     "title": "Implement BIP 54 (Consensus Cleanup) without mainnet activation",
     "author": "darosior"
    },
    {
     "number": 35716,
     "title": "wallet: Replace mapWallet and wtxOrdered with a boost::multi_index",
     "author": "achow101"
    },
    {
     "number": 35569,
     "title": "Encapsulation for CTransaction",
     "author": "purpleKarrot"
    },
    {
     "number": 35501,
     "title": "wallet: store all witness variants of a transaction",
     "author": "achow101"
    },
    {
     "number": 35433,
     "title": "wallet: deprecate replaceable argument from transaction (and psbt) creation (and modification) RPCs",
     "author": "rkrux"
    },
    {
     "number": 35317,
     "title": "wallet: fix ignored subtract_fee_from_outputs option",
     "author": "stutxo"
    },
    {
     "number": 35301,
     "title": "Silent Payments: Implement bip352 (take 2)",
     "author": "Eunovo"
    },
    {
     "number": 34405,
     "title": "wallet: skip APS when no partial spend exists",
     "author": "8144225309"
    },
    {
     "number": 33034,
     "title": "wallet: Store transactions in a separate sqlite table",
     "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"
    }
   ]
  }
 },
 "acks_parsed": {
  "rkrux": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-05-20T09:11:27Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 1,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "rkrux",
   "theStack"
  ]
 },
 "signals": {
  "needs_rebase": true,
  "ci_failed": false,
  "mergeable_state": "dirty",
  "last_author_activity": "2026-07-24T15:25:50Z",
  "last_reviewer_activity": "2026-06-30T09:50:04Z",
  "last_reviewer": "rkrux",
  "author_silent_days": 55,
  "waiting_on_author_days": 0,
  "days_since_update": 43
 },
 "refs": {
  "mentioned": [
   32966,
   35433,
   35543
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 32966,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "Silent Payments: Receiving"
   },
   {
    "number": 35433,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "wallet: deprecate replaceable argument from transaction (and psbt) creation (and modification) RPCs"
   },
   {
    "number": 35543,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-06-26",
    "title": "test: introduce ExtendedPrivateKey and ExtendedPublicKey classes"
   }
  ],
  "conflicts": [
   35861,
   35819,
   35793,
   35716,
   35569,
   35501,
   35433,
   35317,
   35301,
   34405,
   33034,
   27865,
   27260
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/wallet/rpc/spend.cpp",
  "src/wallet/scriptpubkeyman.cpp",
  "test/functional/wallet_silentpayments_sending.py"
 ],
 "body": "This PR is part of integrating silent payments into Bitcoin Core. It is the second iteration of https://github.com/bitcoin/bitcoin/pull/28201. 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\n### Sending\n\n**Silent Payments logic**\nThe main focus of this PR is:\n\n- Applying the Taptweak to a taproot internal private key (this is a copy-paste of the code for applying the taptweak in the signing process)\n- Getting a private key from a given scriptPubKey\n- Creating silent payment outputs\n- Applying the created scriptPubKeys back to the vector of CRecipients\n- The functions are then used together to create silent payment outputs during CreateTransactionInternal.\n- The change output type is correctly chosen when paying to a silent payment address\n- RBF for silent payments transactions are handled correctly\n- Functional tests",
 "commits": [
  {
   "sha": "15e82f66982b96b2ddf8ba0d9488fd4b8d71f340",
   "date": "2026-07-23T21:47:27Z",
   "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": "10240e6092f77fda9ef6ccb52b9c3f5a7f345373",
   "date": "2026-07-23T21:47:27Z",
   "message": "Add \"sp\" HRP"
  },
  {
   "sha": "75950c7c4b9e802cd251b5f827b2eb76ad796479",
   "date": "2026-07-23T21:47:27Z",
   "message": "Add Silent Payments address types\n\nAdd V0SilentPaymentsDestination and UnknownSilentPaymentsDestination\nfor v1 to v30; Bip352 reserves v31 for a backwards incompatible change.\nv1 to v30 addresses are handled as specified in Bip352. The extra_data\nwill be ignored during sending.\n\nValid v0 and v1 addresses were added to key_io_valid.json for testing,\nand invalid v0 and a v31 address were added to key_io_invalid.json.\n\nV0SilentPaymentsDestination must not be formed from invalid public keys;\nthe operations that must be performed to send to a V0SilentPaymentsDestination,\nrequire valid public keys. Hence, the V0SilentPaymentsDestination struct takes\nthe following precautions to ensure that such invalid states are not possible:\n- The constructor will throw when provided with invalid public keys\n- The public keys are private and const references can be retrieved using member functions."
  },
  {
   "sha": "d7f1998fa52bb63621daa60a04707d2b75ecbfe2",
   "date": "2026-07-24T10:48:57Z",
   "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 payments outputs\n  * Node: for creating silent payments indexes for light clients"
  },
  {
   "sha": "b2ffab8f62d55680b1102bea6b76b4fe1f04eb8b",
   "date": "2026-07-24T10:49:11Z",
   "message": "wallet: disable sending to silent payments address\n\nHave `IsValidDestination` return false for silent payments destinations\nand set an error string when decoding a silent payments address.\n\nThis prevents anyone from sending to a silent payments address before\nsending is implemented in the wallet, but also allows the functions to\nbe used in the unit testing famework."
  },
  {
   "sha": "90c2898fe2206a33e71d854a8f93e2f5709e0688",
   "date": "2026-07-24T10:49:11Z",
   "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": "3892ec5ce0e3ec33d06c1e68443e4ddb60660ef3",
   "date": "2026-07-24T13:11:37Z",
   "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": "0500c3134fd05237b9bdf2f6ac10197930c3a7d0",
   "date": "2026-07-24T13:11:37Z",
   "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": "0dcfc851eab077bbebf71d772826b4b0c648e287",
   "date": "2026-07-24T13:22:20Z",
   "message": "wallet: flag silent payments transactions\n\nAdd a flag to the `CoinControl` object if silent payments 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": "dccc255471005ea2f1bf3481e2dea80c335f4f80",
   "date": "2026-07-24T13:22:27Z",
   "message": "wallet: add `IsInputForSharedSecretDerivation` function"
  },
  {
   "sha": "ac2d30fd714047a14edcb1a69df19e98cb2dd45b",
   "date": "2026-07-24T13:22:27Z",
   "message": "wallet: make coin selection silent payments aware\n\nThe coin selection algorithm wasn't guaranteed\nto return a set of coins that are eligible for silent\npayments transactions even when eligible coins\nwere available.\n\nThis commit forces coin selection to first select\neligible coins before attempting to complete\nthe result set with ineligible coins.\n\nIf the transaction cannot be fulfilled with only\neligible coins, coin selection will \"preset\" eligible\noutputs in descending order of `effective_value`\nand attempt to construct a selection from the\nremaining available coins."
  },
  {
   "sha": "2f28820cabab206d4b6b5d6140658f184d2c0048",
   "date": "2026-07-24T13:22:27Z",
   "message": "wallet: add `CreateSilentPaymentsOutputs` function\n\n`CreateSilentPaymentsOutputs` gets the correct private keys, adds them\ntogether, groups the silent payments 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": "46005f1f9080682195d584ae4f7fbb2a236e5a21",
   "date": "2026-07-24T13:22:27Z",
   "message": "wallet: update wallet change type selection logic for sp dest\n\nIf sending to a silent payments dest, the change type should be taproot\nbecause silent payments dests appear as taproot outputs on the blockchain."
  },
  {
   "sha": "2717f420e80f5528f70ec216d2e907ef2619a205",
   "date": "2026-07-24T13:22:27Z",
   "message": "wallet: enable sending to silent payments address\n\nTreat silent payments addresses as valid destination. Also disable using\nsilent payments 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: Novo <eunovo9@gmail.com>"
  },
  {
   "sha": "99e044719001d7ce3ce7e9cfb469f71bb5d543fe",
   "date": "2026-07-24T13:22:27Z",
   "message": "wallet/rpc: add sp addr support to sendall"
  },
  {
   "sha": "3192061b2c4329fe4d4c9f862306688007d458b8",
   "date": "2026-07-24T14:41:07Z",
   "message": "wallet/rbf: support addition of new sp outputs\n\nHandle sp addresses that may be supplied in the `outputs` param of `bumpfee` and `psbtbumpfee`.\n\nThe outputs must be passed as CTxDestinations rather than scriptPubKeys to `CreateRateBumpTransaction`,\nso `CreateTransaction` can properly transform the provided sp addresses to taproot scriptPubKeys."
  },
  {
   "sha": "39a705eae1b7a8c992bd43dc57de00baf543f46e",
   "date": "2026-07-24T14:41:14Z",
   "message": "rpc/util: add scantxforsilentpayments\n\nUseful in sp sending functional tests to check that the resulting taproot outputs are correct."
  },
  {
   "sha": "4ad3cbf575b839bff1a801fcf5c1fca70b0fe939",
   "date": "2026-07-24T14:41:14Z",
   "message": "tests: add sending functional tests"
  }
 ],
 "timeline": [
  {
   "t": "2026-05-20T09:11:27Z",
   "kind": "comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "text": "Concept ACK [03c835d](https://github.com/bitcoin/bitcoin/pull/35302/commits/03c835dbd6d78182b546713ed495373c7d07b01c)"
  },
  {
   "t": "2026-05-23T01:21:45Z",
   "kind": "review_comment",
   "who": "theStack",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "f9a10e9ea9b57f6b21a6dbfd1239c3ba60f721f8",
   "in_reply_to": null,
   "text": "in f9a10e9ea9b57f6b21a6dbfd1239c3ba60f721f8: I think it would be more robust to express this condition using the explicit list of relevant output script types as [specified in the BIP](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#user-content-Inputs_For_Shared_Secret_Derivation), i.e. return early if whichType is _not_ any of P2TR, P2WPKH, P2SH-P2WPKH or P2PKH. Otherwise, the condition has to be extended whenever the TxoutType enum class gets extended (e.g. P2A has been added since and is not there in the condition)."
  },
  {
   "t": "2026-05-23T01:34:58Z",
   "kind": "review_comment",
   "who": "theStack",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "f9a10e9ea9b57f6b21a6dbfd1239c3ba60f721f8",
   "in_reply_to": null,
   "text": "f9a10e9ea9b57f6b21a6dbfd1239c3ba60f721f8: nit: is this line needed? Not sure what the exact rules in C++ are about the single underscore identifier, but I haven't seen this fake-use pattern (probably with the intention to avoid warnings) in other similar places where we use it."
  },
  {
   "t": "2026-05-23T01:41:57Z",
   "kind": "review_comment",
   "who": "theStack",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd",
   "in_reply_to": null,
   "text": "in e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd: could slightly simplify by using `std::any_of` instead (returns a bool instead of an iterator)"
  },
  {
   "t": "2026-05-23T01:42:41Z",
   "kind": "review_comment",
   "who": "theStack",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd",
   "in_reply_to": null,
   "text": "in e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd: any reason why the coin_control instance got moved up?"
  },
  {
   "t": "2026-05-23T01:45:52Z",
   "kind": "review_comment",
   "who": "theStack",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd",
   "in_reply_to": null,
   "text": "in e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd: for functions starting with `Is`, I'd usually expect to return a boolean value. maybe rename with using `Ensure` as a prefix instead?"
  },
  {
   "t": "2026-05-25T11:45:40Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "@theStack I'll attend to your reviews when I rebase on https://github.com/bitcoin/bitcoin/pull/35301"
  },
  {
   "t": "2026-06-07T11:07:30Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "5859ac2c97a00ff9a973827237207022204aafa9"
  },
  {
   "t": "2026-06-07T11:07:45Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "f9a10e9ea9b57f6b21a6dbfd1239c3ba60f721f8",
   "in_reply_to": 3291817596,
   "text": "Done."
  },
  {
   "t": "2026-06-07T11:07:58Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/scriptpubkeyman.cpp",
   "commit": "f9a10e9ea9b57f6b21a6dbfd1239c3ba60f721f8",
   "in_reply_to": 3291855898,
   "text": "Removed."
  },
  {
   "t": "2026-06-07T11:08:09Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd",
   "in_reply_to": 3291864822,
   "text": "Done."
  },
  {
   "t": "2026-06-07T11:08:18Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd",
   "in_reply_to": 3291869501,
   "text": "Done."
  },
  {
   "t": "2026-06-07T11:08:43Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "e3ef349ad5ad2bc283644b5faaa1a6fa234e16bd",
   "in_reply_to": 3291865717,
   "text": "Reverted."
  },
  {
   "t": "2026-06-07T11:10:23Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "16f3a0bc13c8052559f3188c91424a6ff5e20ab5"
  },
  {
   "t": "2026-06-07T21:43:44Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "ecd667cbad3b0bea677d055caf7b5f5d0740e859"
  },
  {
   "t": "2026-06-08T08:06:33Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "b3e7ab7567960f69c9a2261975e39689c2207db6"
  },
  {
   "t": "2026-06-08T17:54:19Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "dffaa357ae583735a84eb4f006e9a7cbdbe49f74"
  },
  {
   "t": "2026-06-23T14:51:35Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "b5fe282fb913eb16e634cf3a49b7d6673d374be7"
  },
  {
   "t": "2026-06-24T13:12:45Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "989d3548c6933a4bc31b82a6f950029440e1d232"
  },
  {
   "t": "2026-06-24T13:41:52Z",
   "kind": "review_comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "989d3548c6933a4bc31b82a6f950029440e1d232",
   "in_reply_to": null,
   "text": "In 989d3548c6933a4bc31b82a6f950029440e1d232 \"tests: add sending functional tests\"\n\n[quoted text omitted]\nPlease remove all occurrences of this createwallet argument, it's not required post disallowing loading legacy wallets.\n\nI see a new SP specific wallet flag is introduced in the SP receiving PR #32966. I have not checked the implementation yet but from a pure functionality POV, the addition of that new wallet flag should not necessitate the passing of the descriptors flag now (which I assume, in all likelihood, is not happening and thus this flag should be removed from the tests)."
  },
  {
   "t": "2026-06-24T13:44:08Z",
   "kind": "review_comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "989d3548c6933a4bc31b82a6f950029440e1d232",
   "in_reply_to": null,
   "text": "In 989d354 \"tests: add sending functional tests\"\n\n[quoted text omitted]\nPlease remove all occurrences of this in transaction/psbt creation/fund/send RPCs that are being used in this test. PR #35433 seeks to deprecate it (hopefully in the upcoming release) because of prevalence of fullrbf in the network and we shouldn't encourage the use of this argument in the functional tests."
  },
  {
   "t": "2026-06-24T13:58:09Z",
   "kind": "review_comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "4ad3cbf575b839bff1a801fcf5c1fca70b0fe939",
   "in_reply_to": null,
   "text": "In 989d354 \"tests: add sending functional tests\"\n\nhttps://github.com/bitcoin/bitcoin/blob/d84fc352cbc1363df5cd6024a22e73fc63283e4f/src/wallet/rpc/spend.cpp#L1003-L1006\n\n1. There's an outputs argument in the (psbt)bumpfee RPCs that allows to add new outputs in the replacing transaction. Please add a test case covering the behaviour when this argument is passed while replacing a silent payment transaction.\n2. Please also add a test case covering the scenario where the user is able to rbf-cancel the SP transaction by sending the funds to themselves."
  },
  {
   "t": "2026-06-24T14:09:12Z",
   "kind": "review",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "989d3548c6933a4bc31b82a6f950029440e1d232",
   "text": "Reviewed only the last testing commit partially 989d354 \"tests: add sending functional tests\"."
  },
  {
   "t": "2026-06-26T08:18:47Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "57209f9ba6c3b9aa0e3489e5d84765a93f059f54"
  },
  {
   "t": "2026-06-26T09:38:01Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "2616ee0424b8a26bf54ba472bf6f3fa4e62a9f97"
  },
  {
   "t": "2026-06-26T09:38:15Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "989d3548c6933a4bc31b82a6f950029440e1d232",
   "in_reply_to": 3467532157,
   "text": "Done"
  },
  {
   "t": "2026-06-26T09:38:28Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "989d3548c6933a4bc31b82a6f950029440e1d232",
   "in_reply_to": 3467547921,
   "text": "Done"
  },
  {
   "t": "2026-06-26T09:38:59Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "4ad3cbf575b839bff1a801fcf5c1fca70b0fe939",
   "in_reply_to": 3467647494,
   "text": "Added new tests for bumpfee with the outputs replaced."
  },
  {
   "t": "2026-06-26T09:42:16Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "05101f3f0eb9b41f4d19f4286388a1b1e7770646"
  },
  {
   "t": "2026-06-26T09:51:13Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "22e42cb9b58a3406ab1870be71aa38f861fbba4d"
  },
  {
   "t": "2026-06-27T12:48:15Z",
   "kind": "review_comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "ebb7ba4f5d31dac9eee3eb225f0aa3778ae0d9b7",
   "in_reply_to": null,
   "text": "In 22e42cb9b58a3406ab1870be71aa38f861fbba4d \"tests: add sending functional tests\"\n\nAfter PR #35543 is merged, we don't need to (manually find and) hardcode xprvs and xpubs in the functional tests anymore. Something like the following can be done, similar to how `ECKey.generate()` is used:\n\n```python\nfrom test_framework.extendedkey import ExtendedPrivateKey\n...\nextended_key = ExtendedPrivateKey.generate()\nxprv, xpub = extended_key.to_string(), extended_key.pubkey().to_string()\n```"
  },
  {
   "t": "2026-06-27T12:49:59Z",
   "kind": "review_comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "22e42cb9b58a3406ab1870be71aa38f861fbba4d",
   "in_reply_to": null,
   "text": "In 22e42cb9b58a3406ab1870be71aa38f861fbba4d \"tests: add sending functional tests\"\n\nI assume it's taken from wallet_taproot.py? It's dead code and should be removed."
  },
  {
   "t": "2026-06-27T12:52:31Z",
   "kind": "review_comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "22e42cb9b58a3406ab1870be71aa38f861fbba4d",
   "in_reply_to": null,
   "text": "In 22e42cb9b58a3406ab1870be71aa38f861fbba4d \"tests: add sending functional tests\"\n\nThere are many asserts in the file of the form `assert X == Y`. Not sure why the Drahtbot has not mentioned in this PR (because it has commented on several PRs before), but the preference is to use the `assert_equal(X, Y)` utility function from the testing framework."
  },
  {
   "t": "2026-06-27T12:56:27Z",
   "kind": "review_comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "22e42cb9b58a3406ab1870be71aa38f861fbba4d",
   "in_reply_to": null,
   "text": "In 22e42cb \"tests: add sending functional tests\"\n\nSimilar to the equality: `s/assert X <= Y/assert_greater_than(Y, X)`"
  },
  {
   "t": "2026-06-27T13:04:17Z",
   "kind": "review_comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "9e6b4d7b7c8b3ce622d0d321c51a2c4c57803a98",
   "in_reply_to": null,
   "text": "In 22e42cb \"tests: add sending functional tests\"\n\nFor all these cases where the testing functionality is preceded by setup() and succeeded by cleanup(), a local context manager can be used for readability. Refer how a custom WalletUnlock context manager is used.\n\nhttps://github.com/bitcoin/bitcoin/blob/7a74f6529357cf78ee74f0316b9502664f56889e/test/functional/test_framework/wallet_util.py#L95-L112"
  },
  {
   "t": "2026-06-27T13:14:19Z",
   "kind": "review",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "22e42cb9b58a3406ab1870be71aa38f861fbba4d",
   "text": "Thanks for addressing the previous suggestions in both the source code and the tests - git range-diff 989d354...22e42cb\n\nPartial review of the test commit 22e42cb \"tests: add sending functional tests\"."
  },
  {
   "t": "2026-06-29T08:55:26Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "9e6b4d7b7c8b3ce622d0d321c51a2c4c57803a98",
   "in_reply_to": 3486042564,
   "text": "It seems a bit overkill to create a Context Manager class for this one test function. I think the current `setup-cleanup` code is better for this case"
  },
  {
   "t": "2026-06-29T09:04:21Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "ebb7ba4f5d31dac9eee3eb225f0aa3778ae0d9b7",
   "in_reply_to": 3486022088,
   "text": "Will fix when I rebase."
  },
  {
   "t": "2026-06-29T09:13:14Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "9e6b4d7b7c8b3ce622d0d321c51a2c4c57803a98"
  },
  {
   "t": "2026-06-29T09:22:17Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "22e42cb9b58a3406ab1870be71aa38f861fbba4d",
   "in_reply_to": 3486024142,
   "text": "Done."
  },
  {
   "t": "2026-06-29T09:22:25Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "22e42cb9b58a3406ab1870be71aa38f861fbba4d",
   "in_reply_to": 3486030993,
   "text": "Done."
  },
  {
   "t": "2026-06-29T09:22:44Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "22e42cb9b58a3406ab1870be71aa38f861fbba4d",
   "in_reply_to": 3486026862,
   "text": "Done."
  },
  {
   "t": "2026-06-30T09:50:04Z",
   "kind": "review_comment",
   "who": "rkrux",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "9e6b4d7b7c8b3ce622d0d321c51a2c4c57803a98",
   "in_reply_to": 3486042564,
   "text": "There is a precedent (or soon going to be) of using context managers in a single test file: https://github.com/bitcoin/bitcoin/pull/35003/changes#diff-815ba9df1be928d33d72629e1cdd6208a68493b24a4cdee0c823fb0375acd44aR34-R47\n\nI think it seems reasonable to create and use a context manager if it improves readability.\nI also feel it's a nice-to-have and not a must-have."
  },
  {
   "t": "2026-07-01T06:40:24Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "6cc51d0ab0c9a1037662b791dab7c45039981d05"
  },
  {
   "t": "2026-07-01T06:40:44Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "9e6b4d7b7c8b3ce622d0d321c51a2c4c57803a98",
   "in_reply_to": 3486042564,
   "text": "Changed the code to use the generator context manager pattern."
  },
  {
   "t": "2026-07-07T12:28:56Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "ebb7ba4f5d31dac9eee3eb225f0aa3778ae0d9b7"
  },
  {
   "t": "2026-07-07T15:09:27Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "text": "CI failure seems unrelated."
  },
  {
   "t": "2026-07-24T15:17:21Z",
   "kind": "force_push",
   "who": "Eunovo",
   "commit": "4ad3cbf575b839bff1a801fcf5c1fca70b0fe939"
  },
  {
   "t": "2026-07-24T15:25:50Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_silentpayments_sending.py",
   "commit": "ebb7ba4f5d31dac9eee3eb225f0aa3778ae0d9b7",
   "in_reply_to": 3486022088,
   "text": "Fixed."
  }
 ],
 "labels_log": [
  {
   "t": "2026-05-28T20:04:03Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-07T11:10:51Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-07T11:35:10Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-08T19:22:49Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-12T10:56:19Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-23T16:06:38Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-23T16:19:14Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-24T14:28:30Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-26T09:37:03Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-26T11:09:47Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-07T13:35:46Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-13T22:24:52Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-24T16:35:47Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-24T16:47:12Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-04T22:56:41Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 12551,
 "text_tokens_estimate": 3137,
 "changed_paths": [
  "src/CMakeLists.txt",
  "src/addresstype.cpp",
  "src/addresstype.h",
  "src/bech32.h",
  "src/common/bip352.cpp",
  "src/common/bip352.h",
  "src/kernel/chainparams.cpp",
  "src/kernel/chainparams.h",
  "src/key.h",
  "src/key_io.cpp",
  "src/rpc/output_script.cpp",
  "src/rpc/util.cpp",
  "src/script/descriptor.cpp",
  "src/test/CMakeLists.txt",
  "src/test/bip352_tests.cpp",
  "src/test/data/bip352_send_and_receive_vectors.json",
  "src/test/data/key_io_invalid.json",
  "src/test/data/key_io_valid.json",
  "src/test/descriptor_tests.cpp",
  "src/test/fuzz/rpc.cpp",
  "src/test/fuzz/script.cpp",
  "src/test/fuzz/util.cpp",
  "src/test/key_io_tests.cpp",
  "src/test/transaction_tests.cpp",
  "src/wallet/coincontrol.h",
  "src/wallet/coinselection.h",
  "src/wallet/feebumper.cpp",
  "src/wallet/feebumper.h",
  "src/wallet/interfaces.cpp",
  "src/wallet/receive.cpp",
  "src/wallet/receive.h",
  "src/wallet/rpc/addresses.cpp",
  "src/wallet/rpc/spend.cpp",
  "src/wallet/scriptpubkeyman.cpp",
  "src/wallet/scriptpubkeyman.h",
  "src/wallet/spend.cpp",
  "src/wallet/spend.h",
  "src/wallet/test/coinselector_tests.cpp",
  "src/wallet/transaction.h",
  "src/wallet/wallet.cpp",
  "src/wallet/wallet.h",
  "src/wallet/walletdb.cpp",
  "src/wallet/walletdb.h",
  "test/functional/rpc_scantxforsilentpayments.py",
  "test/functional/test_runner.py",
  "test/functional/wallet_sendall.py",
  "test/functional/wallet_silentpayments_sending.py"
 ],
 "files": [
  {
   "path": "src/CMakeLists.txt",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/addresstype.cpp",
   "add": 27,
   "del": 0
  },
  {
   "path": "src/addresstype.h",
   "add": 69,
   "del": 1
  },
  {
   "path": "src/bech32.h",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/common/bip352.cpp",
   "add": 380,
   "del": 0
  },
  {
   "path": "src/common/bip352.h",
   "add": 160,
   "del": 0
  },
  {
   "path": "src/kernel/chainparams.cpp",
   "add": 5,
   "del": 0
  },
  {
   "path": "src/kernel/chainparams.h",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/key.h",
   "add": 13,
   "del": 0
  },
  {
   "path": "src/key_io.cpp",
   "add": 77,
   "del": 3
  },
  {
   "path": "src/rpc/output_script.cpp",
   "add": 131,
   "del": 0
  },
  {
   "path": "src/rpc/util.cpp",
   "add": 5,
   "del": 0
  },
  {
   "path": "src/script/descriptor.cpp",
   "add": 4,
   "del": 0
  },
  {
   "path": "src/test/CMakeLists.txt",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/test/bip352_tests.cpp",
   "add": 282,
   "del": 0
  },
  {
   "path": "src/test/data/bip352_send_and_receive_vectors.json",
   "add": 5729,
   "del": 0
  },
  {
   "path": "src/test/data/key_io_invalid.json",
   "add": 27,
   "del": 0
  },
  {
   "path": "src/test/data/key_io_valid.json",
   "add": 51,
   "del": 0
  },
  {
   "path": "src/test/descriptor_tests.cpp",
   "add": 3,
   "del": 0
  },
  {
   "path": "src/test/fuzz/rpc.cpp",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/test/fuzz/script.cpp",
   "add": 11,
   "del": 1
  },
  {
   "path": "src/test/fuzz/util.cpp",
   "add": 20,
   "del": 0
  },
  {
   "path": "src/test/key_io_tests.cpp",
   "add": 39,
   "del": 8
  },
  {
   "path": "src/test/transaction_tests.cpp",
   "add": 2,
   "del": 2
  },
  {
   "path": "src/wallet/coincontrol.h",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/wallet/coinselection.h",
   "add": 4,
   "del": 0
  },
  {
   "path": "src/wallet/feebumper.cpp",
   "add": 69,
   "del": 14
  },
  {
   "path": "src/wallet/feebumper.h",
   "add": 3,
   "del": 1
  },
  {
   "path": "src/wallet/interfaces.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/wallet/receive.cpp",
   "add": 11,
   "del": 0
  },
  {
   "path": "src/wallet/receive.h",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/wallet/rpc/addresses.cpp",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/wallet/rpc/spend.cpp",
   "add": 90,
   "del": 18
  },
  {
   "path": "src/wallet/scriptpubkeyman.cpp",
   "add": 26,
   "del": 0
  },
  {
   "path": "src/wallet/scriptpubkeyman.h",
   "add": 4,
   "del": 0
  },
  {
   "path": "src/wallet/spend.cpp",
   "add": 278,
   "del": 4
  },
  {
   "path": "src/wallet/spend.h",
   "add": 10,
   "del": 0
  },
  {
   "path": "src/wallet/test/coinselector_tests.cpp",
   "add": 170,
   "del": 0
  },
  {
   "path": "src/wallet/transaction.h",
   "add": 43,
   "del": 0
  },
  {
   "path": "src/wallet/wallet.cpp",
   "add": 23,
   "del": 2
  },
  {
   "path": "src/wallet/wallet.h",
   "add": 4,
   "del": 1
  },
  {
   "path": "src/wallet/walletdb.cpp",
   "add": 37,
   "del": 0
  },
  {
   "path": "src/wallet/walletdb.h",
   "add": 5,
   "del": 0
  },
  {
   "path": "test/functional/rpc_scantxforsilentpayments.py",
   "add": 230,
   "del": 0
  },
  {
   "path": "test/functional/test_runner.py",
   "add": 2,
   "del": 0
  },
  {
   "path": "test/functional/wallet_sendall.py",
   "add": 101,
   "del": 58
  },
  {
   "path": "test/functional/wallet_silentpayments_sending.py",
   "add": 588,
   "del": 0
  }
 ],
 "test_lines": 7327,
 "git": {
  "head": "4ad3cbf575b839bff1a801fcf5c1fca70b0fe939",
  "head_matches_backup": true,
  "base": "afa5e46bbc6dd750bd71920b659162a945abf0ae",
  "commits": [
   {
    "sha": "15e82f6698",
    "subject": "crypto: add read-only method to KeyPair",
    "files": 1,
    "add": 13,
    "del": 0
   },
   {
    "sha": "10240e6092",
    "subject": "Add \"sp\" HRP",
    "files": 2,
    "add": 7,
    "del": 0
   },
   {
    "sha": "75950c7c4b",
    "subject": "Add Silent Payments address types",
    "files": 12,
    "add": 319,
    "del": 14
   },
   {
    "sha": "d7f1998fa5",
    "subject": "common: add bip352.{h,cpp} secp256k1 module",
    "files": 3,
    "add": 541,
    "del": 0
   },
   {
    "sha": "b2ffab8f62",
    "subject": "wallet: disable sending to silent payments address",
    "files": 3,
    "add": 10,
    "del": 3
   },
   {
    "sha": "90c2898fe2",
    "subject": "tests: add BIP352 test vectors as unit tests",
    "files": 3,
    "add": 6013,
    "del": 0
   },
   {
    "sha": "3892ec5ce0",
    "subject": "wallet: get serialized size for `V0SilentPayments`",
    "files": 3,
    "add": 24,
    "del": 2
   },
   {
    "sha": "0500c3134f",
    "subject": "wallet: add method for retreiving a private key",
    "files": 2,
    "add": 30,
    "del": 0
   },
   {
    "sha": "0dcfc851ea",
    "subject": "wallet: flag silent payments transactions",
    "files": 3,
    "add": 48,
    "del": 1
   },
   {
    "sha": "dccc255471",
    "subject": "wallet: add `IsInputForSharedSecretDerivation` function",
    "files": 1,
    "add": 45,
    "del": 0
   },
   {
    "sha": "ac2d30fd71",
    "subject": "wallet: make coin selection silent payments aware",
    "files": 3,
    "add": 303,
    "del": 0
   },
   {
    "sha": "2f28820cab",
    "subject": "wallet: add `CreateSilentPaymentsOutputs` function",
    "files": 1,
    "add": 63,
    "del": 2
   },
   {
    "sha": "46005f1f90",
    "subject": "wallet: update wallet change type selection logic for sp dest",
    "files": 1,
    "add": 1,
    "del": 1
   },
   {
    "sha": "2717f420e8",
    "subject": "wallet: enable sending to silent payments address",
    "files": 4,
    "add": 9,
    "del": 9
   },
   {
    "sha": "99e0447190",
    "subject": "wallet/rpc: add sp addr support to sendall",
    "files": 3,
    "add": 155,
    "del": 65
   },
   {
    "sha": "3192061b2c",
    "subject": "wallet/rbf: support addition of new sp outputs",
    "files": 11,
    "add": 223,
    "del": 28
   },
   {
    "sha": "39a705eae1",
    "subject": "rpc/util: add scantxforsilentpayments",
    "files": 4,
    "add": 363,
    "del": 0
   },
   {
    "sha": "4ad3cbf575",
    "subject": "tests: add sending functional tests",
    "files": 2,
    "add": 589,
    "del": 0
   }
  ],
  "patch_truncated": true
 },
 "input_hash": "96e21b02c106f4f1",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}