{
 "number": 34405,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/34405",
 "title": "wallet: skip APS when no partial spend exists",
 "author": "8144225309",
 "author_association": "NONE",
 "created_at": "2026-01-26T04:36:55Z",
 "updated_at": "2026-08-21T08:40:13Z",
 "age_days": 234,
 "draft": false,
 "labels": [
  "Wallet",
  "Needs rebase"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "b6319c62db1bb1f84b5a2255c12afe9bf6019b5e",
 "head_ref": "aps-skip-no-partial-spend",
 "head_repo": "8144225309/bitcoin",
 "head_history": [
  {
   "t": "2026-01-26T10:20:38Z",
   "sha": "d3fc88c6812ca0013dfd029eddf27e04c5e020c6"
  },
  {
   "t": "2026-01-26T10:49:09Z",
   "sha": "b686262ba7e5dbf37289b315b3b54fa330e08596"
  },
  {
   "t": "2026-01-26T10:50:58Z",
   "sha": "d6edd1565ee63145ad53abf5ca0a416a00e91ee6"
  },
  {
   "t": "2026-01-26T16:37:28Z",
   "sha": "53de94fb828ddbe61115a7ed89b86e0d9f8051fe"
  },
  {
   "t": "2026-02-03T02:53:56Z",
   "sha": "598b0618eba9c0851b689c666a8a750ca8f91b3a"
  },
  {
   "t": "2026-02-11T02:59:00Z",
   "sha": "f65dc1b07069096b56286307d84b40957de22888"
  },
  {
   "t": "2026-02-15T06:56:44Z",
   "sha": "b6319c62db1bb1f84b5a2255c12afe9bf6019b5e"
  }
 ],
 "additions": 62,
 "deletions": 16,
 "changed_files": 3,
 "commit_count": 1,
 "size_bucket": "S",
 "mergeable_state": "dirty",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {},
   "conflicts": [
    {
     "number": 34617,
     "title": "fees: wallet: remove block policy fee estimator internals from wallet",
     "author": "ismaelsadeeq"
    },
    {
     "number": 34075,
     "title": "fees: Introduce Mempool Based Fee Estimation to reduce overestimation",
     "author": "ismaelsadeeq"
    },
    {
     "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": [
   "achow101"
  ]
 },
 "signals": {
  "needs_rebase": true,
  "ci_failed": false,
  "mergeable_state": "dirty",
  "last_author_activity": "2026-02-15T06:56:44Z",
  "last_reviewer_activity": "2026-02-02T21:36:06Z",
  "last_reviewer": "achow101",
  "author_silent_days": 214,
  "waiting_on_author_days": 0,
  "days_since_update": 27
 },
 "refs": {
  "mentioned": [
   25150,
   34362
  ],
  "depends_on": [],
  "fixes": [
   25150
  ],
  "linked_issues": [
   {
    "number": 25150,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "Coin Selection tracepoint overreports use of APS"
   }
  ],
  "references": [
   {
    "number": 25150,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "Coin Selection tracepoint overreports use of APS"
   },
   {
    "number": 34362,
    "type": "pull",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "wallet: skip APS when no partial spend exists"
   }
  ],
  "conflicts": [
   34617,
   34075,
   19461,
   19460,
   10102
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/wallet/spend.cpp",
  "test/functional/interface_usdt_coinselection.py"
 ],
 "body": "Fixes #25150\n\nAPS (Avoid Partial Spends) runs a second coin selection pass to fully spend\nUTXOs sharing a scriptPubKey. This currently runs unconditionally, even when\nthe first selection has no partial spend. Running APS unnecessarily wastes\ncomputation and can produce a worse result when there was nothing to fix.\n\nDetect partial spends by comparing selected vs available UTXO counts per\nscriptPubKey, reusing available_coins. Skip APS if none found.\n\nTest updated to create partial spend scenarios so tracepoints fire.\n\n---\n\n*Supersedes #34362 which was corrupted by a shallow clone force-push.*",
 "commits": [
  {
   "sha": "b6319c62db1bb1f84b5a2255c12afe9bf6019b5e",
   "date": "2026-02-15T06:56:16Z",
   "message": "wallet: skip APS when no partial spend exists\n\nAPS runs a second coin selection to fully spend UTXOs sharing a\nscriptPubKey. Currently runs unconditionally, even when the first\nselection has no partial spend and APS cannot help.\n\nDetect partial spends by comparing selected vs available UTXO counts\nper scriptPubKey inside CreateTransactionInternal, reusing available_coins.\nAdd has_partial_spend to CreatedTransactionResult. Skip APS if false.\n\nUpdate interface_usdt_coinselection test to create partial spend scenarios\nso tracepoints fire as expected.\n\nFixes #25150"
  }
 ],
 "timeline": [
  {
   "t": "2026-01-26T10:20:38Z",
   "kind": "force_push",
   "who": "8144225309",
   "commit": "d3fc88c6812ca0013dfd029eddf27e04c5e020c6"
  },
  {
   "t": "2026-01-26T10:49:09Z",
   "kind": "force_push",
   "who": "8144225309",
   "commit": "b686262ba7e5dbf37289b315b3b54fa330e08596"
  },
  {
   "t": "2026-01-26T10:50:58Z",
   "kind": "force_push",
   "who": "8144225309",
   "commit": "d6edd1565ee63145ad53abf5ca0a416a00e91ee6"
  },
  {
   "t": "2026-01-26T16:37:28Z",
   "kind": "force_push",
   "who": "8144225309",
   "commit": "53de94fb828ddbe61115a7ed89b86e0d9f8051fe"
  },
  {
   "t": "2026-02-02T21:25:45Z",
   "kind": "review_comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "path": "src/wallet/spend.cpp",
   "commit": "53de94fb828ddbe61115a7ed89b86e0d9f8051fe",
   "in_reply_to": null,
   "text": "This condition can be grouped with the others in the line above, there's no need to separate it with it's own return statement."
  },
  {
   "t": "2026-02-02T21:36:06Z",
   "kind": "review_comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "path": "test/functional/interface_usdt_coinselection.py",
   "commit": "b6319c62db1bb1f84b5a2255c12afe9bf6019b5e",
   "in_reply_to": null,
   "text": "The default for `wallet_name` is essentially `self.default_wallet_name`, so set it to that instead of using `None`."
  },
  {
   "t": "2026-02-03T02:53:56Z",
   "kind": "force_push",
   "who": "8144225309",
   "commit": "598b0618eba9c0851b689c666a8a750ca8f91b3a"
  },
  {
   "t": "2026-02-03T02:54:52Z",
   "kind": "review_comment",
   "who": "8144225309",
   "assoc": "NONE",
   "path": "src/wallet/spend.cpp",
   "commit": "53de94fb828ddbe61115a7ed89b86e0d9f8051fe",
   "in_reply_to": 2756169390,
   "text": "Done, combined."
  },
  {
   "t": "2026-02-03T02:55:15Z",
   "kind": "review_comment",
   "who": "8144225309",
   "assoc": "NONE",
   "path": "test/functional/interface_usdt_coinselection.py",
   "commit": "b6319c62db1bb1f84b5a2255c12afe9bf6019b5e",
   "in_reply_to": 2756193765,
   "text": "`self` isn't available at function definition time in Python. The `=None` with internal check matches the pattern used elsewhere in the test framework (e.g., `extra_args` in `add_nodes()`)."
  },
  {
   "t": "2026-02-11T02:59:00Z",
   "kind": "force_push",
   "who": "8144225309",
   "commit": "f65dc1b07069096b56286307d84b40957de22888"
  },
  {
   "t": "2026-02-15T06:56:44Z",
   "kind": "force_push",
   "who": "8144225309",
   "commit": "b6319c62db1bb1f84b5a2255c12afe9bf6019b5e"
  }
 ],
 "labels_log": [
  {
   "t": "2026-01-26T04:37:00Z",
   "action": "labeled",
   "label": "Wallet",
   "who": "DrahtBot"
  },
  {
   "t": "2026-02-10T17:21:46Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-02-11T04:14:35Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-02-14T14:04:40Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-02-22T17:05:57Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-21T08:40:11Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 1668,
 "text_tokens_estimate": 417,
 "changed_paths": [],
 "files": [],
 "test_lines": null,
 "git": null,
 "input_hash": "3e133ea3b1a6fafb",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}