{
 "number": 36494,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/36494",
 "title": "wallet: reject unknown options in sendall",
 "author": "thomasbuilds",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-10-10T14:01:06Z",
 "updated_at": "2026-10-29T06:18:50Z",
 "description_hash": "7b7c36c59e2043c8",
 "age_days": 22,
 "draft": false,
 "labels": [
  "Wallet"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "702ec9d40f84dfd0ca9bf73e37052c36f3802702",
 "head_ref": "patch-1",
 "head_repo": "thomasbuilds/bitcoin",
 "head_history": [
  {
   "t": "2026-10-10T17:22:09Z",
   "sha": "4a65a755b004a903244a281c4f7215aa68baf40e"
  },
  {
   "t": "2026-10-16T09:08:46Z",
   "sha": "cb00b6e670a84655a020b79245800364aa9d2d26"
  },
  {
   "t": "2026-10-16T12:19:22Z",
   "sha": "1617c80e7a9dff15f53bed2b46049a6869531e0b"
  },
  {
   "t": "2026-10-16T12:35:43Z",
   "sha": "b688b6dcdc22222d9208b1e28adfe0beab61bb09"
  },
  {
   "t": "2026-10-16T14:17:03Z",
   "sha": "702ec9d40f84dfd0ca9bf73e37052c36f3802702"
  }
 ],
 "additions": 37,
 "deletions": 1,
 "changed_files": 3,
 "commit_count": 1,
 "size_bucket": "S",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "ack": [
     {
      "login": "maflcko",
      "url": "https://github.com/bitcoin/bitcoin/pull/36494#issuecomment-6217508907"
     },
     {
      "login": "Zippo76",
      "url": "https://github.com/bitcoin/bitcoin/pull/36494#issuecomment-6488985127"
     }
    ],
    "concept_nack": [
     {
      "login": "polespinasa",
      "url": "https://github.com/bitcoin/bitcoin/pull/36494#pullrequestreview-5529096215"
     }
    ],
    "concept_ack": [
     {
      "login": "Conradgabe",
      "url": "https://github.com/bitcoin/bitcoin/pull/36494#issuecomment-6144024347"
     },
     {
      "login": "vicjuma",
      "url": "https://github.com/bitcoin/bitcoin/pull/36494#pullrequestreview-5518448164"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "Conradgabe": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-10-13T10:57:43Z",
   "stale": false
  },
  "vicjuma": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-10-14T14:17:18Z",
   "stale": false
  },
  "polespinasa": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-10-15T06:33:54Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 3,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 1,
  "changes_requested": 0,
  "distinct_reviewers": [
   "Conradgabe",
   "Zippo76",
   "kevkevinpal",
   "maflcko",
   "polespinasa",
   "vicjuma"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-10-16T14:18:11Z",
  "last_reviewer_activity": "2026-10-29T05:41:32Z",
  "last_reviewer": "Zippo76",
  "author_silent_days": 16,
  "waiting_on_author_days": 3,
  "days_since_update": 3
 },
 "refs": {
  "mentioned": [],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "doc/release-notes-36494.md",
  "src/wallet/rpc/spend.cpp",
  "test/functional/wallet_sendall.py"
 ],
 "body": "`sendall` silently ignores unknown keys in its `options` object, including misspelled ones: `input` instead of `inputs` spends all available UTXOs rather than the given ones, and a misspelled `add_to_wallet` or `psbt` can broadcast a transaction the caller asked not to broadcast.\n\nReject unknown options, like `send`, `fundrawtransaction`, `walletcreatefundedpsbt` and `bumpfee` already do.",
 "commits": [
  {
   "sha": "702ec9d40f84dfd0ca9bf73e37052c36f3802702",
   "date": "2026-10-16T14:10:29Z",
   "message": "wallet: reject unknown options in sendall\n\nUnknown keys in the options object were silently ignored, so a typo\nsuch as \"input\" for \"inputs\" spent all available UTXOs rather than the\ngiven ones. The options are checked before the fee arguments are merged\ninto them, so that a misspelled estimate_mode is reported as an\nunexpected key. The check also rejects the outdated camelCase names, so\nsendall no longer needs PreventOutdatedOptions."
  }
 ],
 "timeline": [
  {
   "t": "2026-10-10T17:11:54Z",
   "kind": "comment",
   "who": "kevkevinpal",
   "assoc": "CONTRIBUTOR",
   "text": "This should have a release note if `sendall` now rejects unknown options",
   "id": "c:6100093019",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#issuecomment-6100093019",
   "hash": "88596e479113f315",
   "edited": null
  },
  {
   "t": "2026-10-10T17:22:09Z",
   "kind": "force_push",
   "who": "thomasbuilds",
   "commit": "4a65a755b004a903244a281c4f7215aa68baf40e",
   "id": "push:4a65a755b004a903244a281c4f7215aa68baf40e"
  },
  {
   "t": "2026-10-13T10:57:43Z",
   "kind": "comment",
   "who": "Conradgabe",
   "assoc": "NONE",
   "text": "Concept ACK",
   "id": "c:6144024347",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#issuecomment-6144024347",
   "hash": "e8334cc43879b73c",
   "edited": null
  },
  {
   "t": "2026-10-14T14:17:18Z",
   "kind": "review",
   "who": "vicjuma",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "4a65a755b004a903244a281c4f7215aa68baf40e",
   "text": "Concept ACK",
   "id": "r:5518448164",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#pullrequestreview-5518448164",
   "hash": "e8334cc43879b73c",
   "edited": null
  },
  {
   "t": "2026-10-14T14:18:41Z",
   "kind": "review_comment",
   "who": "vicjuma",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "702ec9d40f84dfd0ca9bf73e37052c36f3802702",
   "in_reply_to": null,
   "text": "Works as expected\n\n**Before**:\n\n**After**:",
   "id": "rc:4271982674",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#discussion_r4271982674",
   "hash": "e6d13aaf45f72ed1",
   "edited": "2026-10-14T14:20:33Z"
  },
  {
   "t": "2026-10-14T14:20:24Z",
   "kind": "review_comment",
   "who": "vicjuma",
   "assoc": "CONTRIBUTOR",
   "path": "doc/release-notes-36494.md",
   "commit": "4a65a755b004a903244a281c4f7215aa68baf40e",
   "in_reply_to": null,
   "text": "[quoted text omitted]\n  `subtract_fee_from_outputs`\n\nMinor nit:\n`unknown` (or `unsupported`) options seem enough, probably?",
   "id": "rc:4272001980",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#discussion_r4272001980",
   "hash": "8232cdfb09fca983",
   "edited": "2026-10-14T14:20:33Z"
  },
  {
   "t": "2026-10-15T06:33:54Z",
   "kind": "review",
   "who": "polespinasa",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "4a65a755b004a903244a281c4f7215aa68baf40e",
   "text": "concept ACK on adding the options check.\n\nNACK on removing `solving_data`. Although it is not used it is a breaking change that should be documented and follow the deprecation process. See https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#feature-deprecation-and-removal-process",
   "id": "r:5529096215",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#pullrequestreview-5529096215",
   "hash": "c20f095d7e0c5c2e",
   "edited": null
  },
  {
   "t": "2026-10-16T09:08:46Z",
   "kind": "force_push",
   "who": "thomasbuilds",
   "commit": "cb00b6e670a84655a020b79245800364aa9d2d26",
   "id": "push:cb00b6e670a84655a020b79245800364aa9d2d26"
  },
  {
   "t": "2026-10-16T09:15:49Z",
   "kind": "comment",
   "who": "thomasbuilds",
   "assoc": "CONTRIBUTOR",
   "text": "@polespinasa dropped the `solving_data` removal.",
   "id": "c:6212219945",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#issuecomment-6212219945",
   "hash": "fbe5e7f5b163b90a",
   "edited": null
  },
  {
   "t": "2026-10-16T09:35:37Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "cb00b6e670a84655a020b79245800364aa9d2d26",
   "in_reply_to": null,
   "text": "This call can be removed now? Also, what about `send`?",
   "id": "rc:4293083196",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#discussion_r4293083196",
   "hash": "866355408f6ac629",
   "edited": null
  },
  {
   "t": "2026-10-16T09:35:52Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "cb00b6e670a84655a020b79245800364aa9d2d26",
   "in_reply_to": 4293083196,
   "text": "Please squash your commits according to https://github.com/bitcoin/bitcoin/blob/master/CONTRIBUTING.md#squashing-commits",
   "id": "rc:4293086296",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#discussion_r4293086296",
   "hash": "44b2f2a0331db5ad",
   "edited": "2026-10-16T09:36:01Z"
  },
  {
   "t": "2026-10-16T12:19:22Z",
   "kind": "force_push",
   "who": "thomasbuilds",
   "commit": "1617c80e7a9dff15f53bed2b46049a6869531e0b",
   "id": "push:1617c80e7a9dff15f53bed2b46049a6869531e0b"
  },
  {
   "t": "2026-10-16T12:21:46Z",
   "kind": "review_comment",
   "who": "thomasbuilds",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "cb00b6e670a84655a020b79245800364aa9d2d26",
   "in_reply_to": 4293083196,
   "text": "Removed and squashed - `send` still needs it since `FundTransaction` accepts the camelCase names for `fundrawtransaction`",
   "id": "rc:4294588799",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#discussion_r4294588799",
   "hash": "64d7539063b41cf1",
   "edited": "2026-10-16T12:21:47Z"
  },
  {
   "t": "2026-10-16T12:35:43Z",
   "kind": "force_push",
   "who": "thomasbuilds",
   "commit": "b688b6dcdc22222d9208b1e28adfe0beab61bb09",
   "id": "push:b688b6dcdc22222d9208b1e28adfe0beab61bb09"
  },
  {
   "t": "2026-10-16T13:26:46Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "cb00b6e670a84655a020b79245800364aa9d2d26",
   "in_reply_to": 4293083196,
   "text": "[quoted text omitted]\n\nhuh, `PreventOutdatedOptions` is called in `send` and it literally rejects all camelCase?\n\nUsing LLMs is fine, but you'll have to read and understand all code yourself as well.",
   "id": "rc:4295146863",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#discussion_r4295146863",
   "hash": "ea26a48ff8c1f162",
   "edited": "2026-10-16T13:26:47Z"
  },
  {
   "t": "2026-10-16T13:39:36Z",
   "kind": "review_comment",
   "who": "thomasbuilds",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "cb00b6e670a84655a020b79245800364aa9d2d26",
   "in_reply_to": 4293083196,
   "text": "I meant the call can't be dropped from `send` like it was from `sendall`. `send`'s options go through the `RPCTypeCheckObj` in `FundTransaction`, which allows the camelCase names `PreventOutdatedOptions` checks for, since they are `fundrawtransaction` options. So in `send` that call is what rejects them. The new list in `sendall` doesn't have them so the call was redundant there.",
   "id": "rc:4295266843",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#discussion_r4295266843",
   "hash": "263648554879541e",
   "edited": null
  },
  {
   "t": "2026-10-16T13:49:21Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/wallet/rpc/spend.cpp",
   "commit": "cb00b6e670a84655a020b79245800364aa9d2d26",
   "in_reply_to": 4293083196,
   "text": "ok, hmm. I was thinking to add the type and field checks right in the RPC that needs them, not through some deeper calls, which accept camelCase, and then some more extra calls which reject it again.\n\nBut maybe this would be too much of a refactor. So seems fine to leave as-is for now.\n\nI had a branch to remove all of this code anyway, but it was in tmpfs and I poured tea over my machine and lost it. Maybe I'll try to re-create it after https://github.com/bitcoin/bitcoin/pull/36489 is merged.",
   "id": "rc:4295357554",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#discussion_r4295357554",
   "hash": "c05a928303d0da57",
   "edited": null
  },
  {
   "t": "2026-10-16T14:01:09Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "test/functional/wallet_sendall.py",
   "commit": "b688b6dcdc22222d9208b1e28adfe0beab61bb09",
   "in_reply_to": null,
   "text": "I am not sure how much value there is in adding dummy tests that just check success without also checking that the conf target, estimate mode, etc are really honoured.\n\nIt would be better to remove them to avoid a false sense of coverage.",
   "id": "rc:4295470874",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#discussion_r4295470874",
   "hash": "9e5d9e92a7781a3b",
   "edited": "2026-10-16T14:05:20Z"
  },
  {
   "t": "2026-10-16T14:04:49Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "test/functional/wallet_sendall.py",
   "commit": "702ec9d40f84dfd0ca9bf73e37052c36f3802702",
   "in_reply_to": null,
   "text": "not sure about such a large test. This can be made smaller:\n\n```diff\ndiff --git a/test/functional/wallet_sendall.py b/test/functional/wallet_sendall.py\nindex f0faa9a85d..3724237513 100755\n--- a/test/functional/wallet_sendall.py\n+++ b/test/functional/wallet_sendall.py\n@@ -285,15 +285,8 @@ class SendallTest(BitcoinTestFramework):\n     @cleanup\n     def sendall_fails_on_invalid_options(self):\n         self.log.info(\"Test sendall fails on unknown options or options of the wrong type\")\n-        self.add_utxos([15, 6])\n-        utxo = self.wallet.listunspent()[0]\n-\n-        assert_raises_rpc_error(-3, \"Unexpected key input\",\n-                self.wallet.sendall, recipients=[self.remainder_target], options={\"input\": [utxo]})\n-        assert_raises_rpc_error(-3, \"Unexpected key feeRate\",\n-                self.wallet.sendall, recipients=[self.remainder_target], options={\"feeRate\": 0.0001})\n-        assert_raises_rpc_error(-3, \"Unexpected key estimate_mde\",\n-                self.wallet.sendall, recipients=[self.remainder_target], options={\"conf_target\": 6, \"estimate_mde\": \"economical\"})\n+        assert_raises_rpc_error(-3, \"Unexpected key add_to_wllt\",\n+                self.wallet.sendall, recipients=[self.remainder_target], options={\"add_to_wllt\": \"false\"})\n         assert_raises_rpc_error(-3, \"JSON value of type string for field add_to_wallet is not of expected type bool\",\n                 self.wallet.sendall, recipients=[self.remainder_target], options={\"add_to_wallet\": \"false\"})",
   "id": "rc:4295504344",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#discussion_r4295504344",
   "hash": "6d9bba142338eca3",
   "edited": "2026-10-16T14:05:20Z"
  },
  {
   "t": "2026-10-16T14:05:20Z",
   "kind": "review",
   "who": "maflcko",
   "assoc": "MEMBER",
   "state": "APPROVED",
   "commit": "b688b6dcdc22222d9208b1e28adfe0beab61bb09",
   "text": "lgtm, makes sense to reject unknown fields explicitly instead of silently ignoring them\n\nreview ACK b688b6dcdc22222d9208b1e28adfe0beab61bb09 \ud83d\udd87\n\nShow signature\n\nSignature:\n\n```\nuntrusted comment: signature from minisign secret key on empty file; verify via: minisign -Vm \"${path_to_any_empty_file}\" -P RWTRmVTMeKV5noAMqVlsMugDDCyyTSbA3Re5AkUrhvLVln0tSaFWglOw -x \"${path_to_this_whole_four_line_signature_blob}\"\nRUTRmVTMeKV5npGrKx1nqXCw5zeVHdtdYURB/KlyA/LMFgpNCs+SkW9a8N95d+U4AP1RJMi+krxU1A3Yux4bpwZNLvVBKy0wLgM=\ntrusted comment: review ACK b688b6dcdc22222d9208b1e28adfe0beab61bb09 \ud83d\udd87\nMUNdQAsCiZLs9ChYoHySAuwH9oKHch6PED2ZdR87D4HxI6uMdgg/JWKDI2t709O8n+CWerUTBWq5FLqjEe5aBw==\n```",
   "id": "r:5548828363",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#pullrequestreview-5548828363",
   "hash": "dc38a16d6875feac",
   "edited": null
  },
  {
   "t": "2026-10-16T14:17:03Z",
   "kind": "force_push",
   "who": "thomasbuilds",
   "commit": "702ec9d40f84dfd0ca9bf73e37052c36f3802702",
   "id": "push:702ec9d40f84dfd0ca9bf73e37052c36f3802702"
  },
  {
   "t": "2026-10-16T14:18:11Z",
   "kind": "review_comment",
   "who": "thomasbuilds",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_sendall.py",
   "commit": "702ec9d40f84dfd0ca9bf73e37052c36f3802702",
   "in_reply_to": 4295504344,
   "text": "done ty",
   "id": "rc:4295632431",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#discussion_r4295632431",
   "hash": "0103e02888498693",
   "edited": null
  },
  {
   "t": "2026-10-16T14:19:30Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "only change is slimming down the test\n\nreview ACK 702ec9d40f84dfd0ca9bf73e37052c36f3802702 \ud83d\udc00\n\nShow signature\n\nSignature:\n\n```\nuntrusted comment: signature from minisign secret key on empty file; verify via: minisign -Vm \"${path_to_any_empty_file}\" -P RWTRmVTMeKV5noAMqVlsMugDDCyyTSbA3Re5AkUrhvLVln0tSaFWglOw -x \"${path_to_this_whole_four_line_signature_blob}\"\nRUTRmVTMeKV5npGrKx1nqXCw5zeVHdtdYURB/KlyA/LMFgpNCs+SkW9a8N95d+U4AP1RJMi+krxU1A3Yux4bpwZNLvVBKy0wLgM=\ntrusted comment: review ACK 702ec9d40f84dfd0ca9bf73e37052c36f3802702 \ud83d\udc00\nZIsQXc3hPnteVdmhWFAzzktVar1SyUDVNj8lE0Qq3N6nbWGFfqfsstktLDuMykhI4c1yMR+c5EZdy6EOkA/qBQ==\n```",
   "id": "c:6217508907",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#issuecomment-6217508907",
   "hash": "53a5366bf4a3ebc6",
   "edited": null
  },
  {
   "t": "2026-10-29T05:41:32Z",
   "kind": "comment",
   "who": "Zippo76",
   "assoc": "NONE",
   "text": "tACK 702ec9d40f\n\nTested on macOS 27 (Apple Silicon).\nThe new case in wallet_sendall.py fails on master, where the unknown option is ignored and the call reaches coin selection; it passes with this PR.\n\nManually checked options={\"add_to_wllt\": false} in regtest: on master, the transaction was accepted into the mempool.\nWith this PR, the same call returned Unexpected key add_to_wllt and the mempool remained empty.\nReviewed the diff and confirmed that the strict options check runs before the fee arguments are copied into options.",
   "id": "c:6488985127",
   "url": "https://github.com/bitcoin/bitcoin/pull/36494#issuecomment-6488985127",
   "hash": "f8acff934757677d",
   "edited": null
  }
 ],
 "labels_log": [
  {
   "t": "2026-10-10T14:01:10Z",
   "action": "labeled",
   "label": "Wallet",
   "who": "DrahtBot"
  },
  {
   "t": "2026-10-16T12:37:18Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-10-16T13:22:56Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 6444,
 "text_tokens_estimate": 1611,
 "changed_paths": [
  "doc/release-notes-36494.md",
  "src/wallet/rpc/spend.cpp",
  "test/functional/wallet_sendall.py"
 ],
 "files": [
  {
   "path": "doc/release-notes-36494.md",
   "add": 7,
   "del": 0
  },
  {
   "path": "src/wallet/rpc/spend.cpp",
   "add": 19,
   "del": 1
  },
  {
   "path": "test/functional/wallet_sendall.py",
   "add": 11,
   "del": 0
  }
 ],
 "test_lines": 11,
 "git": {
  "head": "702ec9d40f84dfd0ca9bf73e37052c36f3802702",
  "head_matches_backup": true,
  "base": "228877d7836a55c1d6fde90b0b7ba2d4c90248ab",
  "patch_id": "eb785404d82e8a14",
  "commits": [
   {
    "sha": "702ec9d40f",
    "subject": "wallet: reject unknown options in sendall",
    "files": 3,
    "add": 37,
    "del": 1
   }
  ],
  "patch_truncated": false
 },
 "patch_id": "eb785404d82e8a14",
 "input_hash": "61411de5163a9cd9",
 "extracted_at": "2026-11-02T01:09:49+00:00"
}