{
 "number": 36393,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/36393",
 "title": "wallet: enforce max_tx_weight for preset inputs",
 "author": "gjija",
 "author_association": "FIRST_TIME_CONTRIBUTOR",
 "created_at": "2026-09-30T14:47:06Z",
 "updated_at": "2026-10-19T14:42:27Z",
 "description_hash": "e1483c67ce541782",
 "age_days": 32,
 "draft": false,
 "labels": [
  "Wallet"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "37f3c7da4e9f00f24bce2aca57f454207fe08875",
 "head_ref": "wallet-preset-input-weight-limit",
 "head_repo": "gjija/bitcoin",
 "head_history": [
  {
   "t": "2026-10-19T13:18:19Z",
   "sha": "37f3c7da4e9f00f24bce2aca57f454207fe08875"
  }
 ],
 "additions": 19,
 "deletions": 3,
 "changed_files": 2,
 "commit_count": 1,
 "size_bucket": "S",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "vicjuma",
      "url": "https://github.com/bitcoin/bitcoin/pull/36393#pullrequestreview-5553688144"
     }
    ],
    "stale_ack": [
     {
      "login": "jcastros",
      "url": "https://github.com/bitcoin/bitcoin/pull/36393#issuecomment-5972098738"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "vicjuma": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-10-16T21:05:09Z",
   "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": [
   "jcastros",
   "vicjuma"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-10-19T14:42:27Z",
  "last_reviewer_activity": "2026-10-16T21:05:09Z",
  "last_reviewer": "vicjuma",
  "author_silent_days": 13,
  "waiting_on_author_days": 0,
  "days_since_update": 13
 },
 "refs": {
  "mentioned": [],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/wallet/spend.cpp",
  "test/functional/wallet_fundrawtransaction.py"
 ],
 "body": "`fundrawtransaction` was not respecting `max_tx_weight` in one case.\n\nIf the provided inputs were already enough to fund the transaction, coin selection returned early. The final weight check then used the standard 400,000 WU ceiling instead of the requested `max_tx_weight`.\n\nI reproduced this with 10 legacy inputs and `max_tx_weight=4000`. Funding succeeded even though the transaction was 6,168 WU after signing. Same result with both `add_inputs=false` and `add_inputs=true`.\n\nThe fix is to use the configured max weight in the final check.\n\nFor signed transactions, it checks the actual transaction weight. For unsigned transactions, it checks the estimated signed weight.\n\nI added a regression test for both `add_inputs` settings:\n\n- `4000 WU` must fail\n- `8000 WU` must fund successfully\n- after signing, the transaction must still be within the limit\n\nThe test fails before the fix and passes after it.\n\nTested on macOS arm64:\n\n- `wallet_fundrawtransaction.py`\n- `wallet_send.py`\n- `wallet_v3_txs.py`\n- live regtest reproduction\n\nAll passed.",
 "commits": [
  {
   "sha": "37f3c7da4e9f00f24bce2aca57f454207fe08875",
   "date": "2026-10-19T13:16:15Z",
   "message": "wallet: enforce max_tx_weight for preset inputs\n\nPreset inputs can cover the target without passing coin selection's maximum\nweight checks. The final guard used MAX_STANDARD_TX_WEIGHT rather than the\nvalidated configured maximum.\n\nUse the configured maximum in the final guard for signed weights and unsigned\nsigned-weight estimates. Add a regression covering both add_inputs settings\nwith a rejecting lower limit and an accepting higher limit."
  }
 ],
 "timeline": [
  {
   "t": "2026-10-03T18:18:53Z",
   "kind": "comment",
   "who": "jcastros",
   "assoc": "CONTRIBUTOR",
   "text": "I tested 904f565306.\n\nfundrawtransaction with 10 legacy inputs and max_tx_weight=4000 comes back \"Transaction too large\". On the parent, e0f16ef9a489, the same call goes through, and after signing the weight is 6,168 WU. I saw that with add_inputs true and with it false.\n\nwallet_fundrawtransaction.py passes on this commit. With the old check restored it dies at the new assertion.\n\nA v3 child made only from preset inputs is still funded when it's over the 1000 vbyte TRUC limit. Mine spent an unconfirmed v3 parent plus those legacy coins, and testmempoolaccept rejected it. On e0f16ef9a489 it gets funded too, so this commit didn't cause it. Should this final check enforce that cap as well, or do you want it as a follow-up?\n\nACK 904f565306",
   "id": "c:5972098738",
   "url": "https://github.com/bitcoin/bitcoin/pull/36393#issuecomment-5972098738",
   "hash": "0bbd81ff6121b007",
   "edited": null
  },
  {
   "t": "2026-10-04T19:34:28Z",
   "kind": "comment",
   "who": "gjija",
   "assoc": "NONE",
   "text": "@jcastros\n\nThanks for testing. I\u2019d keep the TRUC child-limit fix as a follow-up, since it reproduces on the parent too. This PR is focused on honoring max_tx_weight when the preset inputs are sufficient.",
   "id": "c:5983627867",
   "url": "https://github.com/bitcoin/bitcoin/pull/36393#issuecomment-5983627867",
   "hash": "2e1a18dfee6de783",
   "edited": null
  },
  {
   "t": "2026-10-16T21:04:37Z",
   "kind": "review_comment",
   "who": "vicjuma",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/spend.cpp",
   "commit": "904f5653060d95dd600c8f3e99689bc45e2b15de",
   "in_reply_to": null,
   "text": "Works as expected. Tried it with ~830 weighted transactions\n\n```console\n./bitcoin-cli -rpcwallet=testwallet1 createrawtransaction   '[{\"txid\":\"3f876505716e84c4422731d3fedf0fedb48558bf2fd4aa2527c54fcd30a9d691\",\"vout\":0},\n    {\"txid\":\"f660ab3d279aac626da15b622ffaa43ad930059f1ca31ea9653137f4a79f73bd\",\"vout\":1}]'   '[{\"bcrt1qr2uwqa6q60fgsdgzyq6uehh86m3t0a06nlxzs3\":40.0}]'\n```\n2 P2WPKH inputs + 1 P2WPKH output.\n\n**After**\n\nMinor nit:\nMake the comment more precise, like `ensure...does not exceed...`",
   "id": "rc:4299335484",
   "url": "https://github.com/bitcoin/bitcoin/pull/36393#discussion_r4299335484",
   "hash": "2cfe077a0bd347cc",
   "edited": "2026-10-16T21:05:09Z"
  },
  {
   "t": "2026-10-16T21:04:43Z",
   "kind": "review_comment",
   "who": "vicjuma",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_fundrawtransaction.py",
   "commit": "37f3c7da4e9f00f24bce2aca57f454207fe08875",
   "in_reply_to": null,
   "text": "Minor nit:\nA comment on the input and output types, with their respective weights will go a long way in describing what the test is doing without making a reviewer guess that it should always be a P2PKH tx. Like the way it is cleanly laid out in `test_weight_calculation`\n\n```python\n# with 71-byte signatures we should expect following tx size\n# tx overhead (10) + 2 inputs (41 each) + 2 p2wpkh (31 each) + (segwit marker and flag (2) + 2 p2wpkh 71 byte sig witnesses (107 each)) / witness scaling factor (4)\n```",
   "id": "rc:4299336088",
   "url": "https://github.com/bitcoin/bitcoin/pull/36393#discussion_r4299336088",
   "hash": "b99e0989a6e9d15a",
   "edited": "2026-10-16T21:05:09Z"
  },
  {
   "t": "2026-10-16T21:05:09Z",
   "kind": "review",
   "who": "vicjuma",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "904f5653060d95dd600c8f3e99689bc45e2b15de",
   "text": "Concept ACK",
   "id": "r:5553688144",
   "url": "https://github.com/bitcoin/bitcoin/pull/36393#pullrequestreview-5553688144",
   "hash": "e8334cc43879b73c",
   "edited": null
  },
  {
   "t": "2026-10-19T13:18:19Z",
   "kind": "force_push",
   "who": "gjija",
   "commit": "37f3c7da4e9f00f24bce2aca57f454207fe08875",
   "id": "push:37f3c7da4e9f00f24bce2aca57f454207fe08875"
  },
  {
   "t": "2026-10-19T14:40:13Z",
   "kind": "review_comment",
   "who": "gjija",
   "assoc": "NONE",
   "path": "src/wallet/spend.cpp",
   "commit": "904f5653060d95dd600c8f3e99689bc45e2b15de",
   "in_reply_to": 4299335484,
   "text": "Thanks for testing. Reworded it to the \"ensure ... does not exceed\" form you suggested, and added a sentence on why the check is needed here.",
   "id": "rc:4315149782",
   "url": "https://github.com/bitcoin/bitcoin/pull/36393#discussion_r4315149782",
   "hash": "1bac0630f8bed460",
   "edited": null
  },
  {
   "t": "2026-10-19T14:40:57Z",
   "kind": "review_comment",
   "who": "gjija",
   "assoc": "NONE",
   "path": "test/functional/wallet_fundrawtransaction.py",
   "commit": "37f3c7da4e9f00f24bce2aca57f454207fe08875",
   "in_reply_to": 4299336088,
   "text": "Done, added the types and sizes to the case 4 comment with the total weight, same layout as `test_weight_calculation`. The inputs are p2pkh because the parent tx in this test pays to legacy addresses.",
   "id": "rc:4315158456",
   "url": "https://github.com/bitcoin/bitcoin/pull/36393#discussion_r4315158456",
   "hash": "07c7f47cd82a5d1c",
   "edited": null
  },
  {
   "t": "2026-10-19T14:42:27Z",
   "kind": "comment",
   "who": "gjija",
   "assoc": "NONE",
   "text": "Addressed both nits from @vicjuma , comment-only change.\n\n`git range-diff e0f16ef 904f565 37f3c7d`",
   "id": "c:6269938953",
   "url": "https://github.com/bitcoin/bitcoin/pull/36393#issuecomment-6269938953",
   "hash": "8ef45caade5c4f10",
   "edited": null
  }
 ],
 "labels_log": [
  {
   "t": "2026-09-30T14:47:10Z",
   "action": "labeled",
   "label": "Wallet",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2026-09-30T15:04:37Z",
   "kind": "ready_for_review",
   "who": "gjija"
  }
 ],
 "text_chars": 3959,
 "text_tokens_estimate": 989,
 "changed_paths": [
  "src/wallet/spend.cpp",
  "test/functional/wallet_fundrawtransaction.py"
 ],
 "files": [
  {
   "path": "src/wallet/spend.cpp",
   "add": 5,
   "del": 3
  },
  {
   "path": "test/functional/wallet_fundrawtransaction.py",
   "add": 14,
   "del": 0
  }
 ],
 "test_lines": 14,
 "git": {
  "head": "37f3c7da4e9f00f24bce2aca57f454207fe08875",
  "head_matches_backup": true,
  "base": "e0f16ef9a4894dd91aa7e310e27f7423b139ef00",
  "patch_id": "f2893da6ac1d939e",
  "commits": [
   {
    "sha": "37f3c7da4e",
    "subject": "wallet: enforce max_tx_weight for preset inputs",
    "files": 2,
    "add": 19,
    "del": 3
   }
  ],
  "patch_truncated": false
 },
 "patch_id": "f2893da6ac1d939e",
 "input_hash": "a1ac1314d8d14f7f",
 "extracted_at": "2026-11-02T01:09:49+00:00"
}