{
 "number": 35300,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35300",
 "title": "mining: add precious option to IPC block submission",
 "author": "w0xlt",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-05-16T03:23:48Z",
 "updated_at": "2026-08-14T15:42:55Z",
 "age_days": 124,
 "draft": true,
 "labels": [
  "Mining",
  "Needs rebase"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "95f62bce86d7c56ba170b3fb813f61cd9ca13aed",
 "head_ref": "ipc-submit-block-precious",
 "head_repo": "w0xlt/bitcoin",
 "head_history": [
  {
   "t": "2026-05-16T04:02:15Z",
   "sha": "a02e97d9a2771a6704f196c9d1b24f0276ee9a1f"
  },
  {
   "t": "2026-07-24T02:37:21Z",
   "sha": "95f62bce86d7c56ba170b3fb813f61cd9ca13aed"
  }
 ],
 "additions": 556,
 "deletions": 100,
 "changed_files": 20,
 "commit_count": 6,
 "size_bucket": "L",
 "mergeable_state": "dirty",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "Sjors",
      "url": "https://github.com/bitcoin/bitcoin/pull/35300#pullrequestreview-4773259302"
     },
     {
      "login": "pablomartin4btc",
      "url": "https://github.com/bitcoin/bitcoin/pull/35300#pullrequestreview-4776665286"
     }
    ]
   },
   "conflicts": [
    {
     "number": 35847,
     "title": "test: move more tests to `baseindex_tests` and run them for all indexes",
     "author": "mzumsande"
    },
    {
     "number": 35646,
     "title": "RFC: Separate out runtime errors from BlockValidationState using `util::Expected`",
     "author": "yuvicc"
    }
   ]
  }
 },
 "acks_parsed": {
  "Sjors": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-07-24T12:59:52Z",
   "stale": false
  },
  "pablomartin4btc": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-07-24T21:33:05Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 2,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "Sjors",
   "pablomartin4btc"
  ]
 },
 "signals": {
  "needs_rebase": true,
  "ci_failed": false,
  "mergeable_state": "dirty",
  "last_author_activity": "2026-07-24T02:37:21Z",
  "last_reviewer_activity": "2026-07-24T21:33:05Z",
  "last_reviewer": "pablomartin4btc",
  "author_silent_days": 55,
  "waiting_on_author_days": 54,
  "days_since_update": 34
 },
 "refs": {
  "mentioned": [
   34672
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 34672,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-07-22",
    "title": "mining: add reason/debug to `submitSolution` and unify with `submitBlock`"
   }
  ],
  "conflicts": [
   35847,
   35646
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/interfaces/mining.h",
  "src/rpc/blockchain.cpp",
  "src/test/miner_tests.cpp",
  "test/functional/interface_ipc_mining.py"
 ],
 "body": "This PR adds a `precious` flag to the IPC Mining submitBlock and submitSolution methods, as suggested in https://github.com/bitcoin/bitcoin/pull/34644#discussion_r3247072448. Built on top https://github.com/bitcoin/bitcoin/pull/34644.\n\nWith this change, IPC mining clients can submit and prefer a block in one IPC call, instead of submitting it over IPC and then using the `preciousblock` RPC separately.\n\nBy default, same-work side blocks keep the existing behavior: `submitBlock` reports duplicate/inconclusive cases as failure with a reason, while `submitSolution` continues to return true when `ProcessNewBlock` accepts or already knows the block.\n\nIncludes unit and IPC functional coverage for default behavior, precious reorgs, active-tip no-op submissions, and invalid-block rejection.",
 "commits": [
  {
   "sha": "42d48e7760b7680a4291f689fd528e800f24b19a",
   "date": "2026-07-24T02:22:30Z",
   "message": "refactor: extract ActivateBestChain_ helper\n\nMove the lock-held body of ActivateBestChain() into an internal helper without changing behavior. This allows callers that already hold m_chainstate_mutex to run activation without releasing and reacquiring it."
  },
  {
   "sha": "f7a7b39e3735615e43a7891230faeb88945da996",
   "date": "2026-07-24T02:22:51Z",
   "message": "mining: add precious IPC block submission option\n\nThread a precious flag through the Mining IPC submitBlock and submitSolution methods so callers can prefer an already-known same-work block, matching preciousblock-style behavior while preserving default duplicate handling.\n\nHave PreciousBlock report whether the requested block is connected while still holding m_chainstate_mutex. This lets SubmitBlock return an atomic success result instead of racing a concurrent chain activation after PreciousBlock returns.\n\nPrefer a captured validation failure over duplicate fallback so a known block that fails during precious activation returns its BIP22 reject reason."
  },
  {
   "sha": "a1f8966316dcd0807d0ee612327d4a822c89177f",
   "date": "2026-07-24T02:22:59Z",
   "message": "test: cover precious mining submissions\n\nAdd regtest unit coverage for the Mining interface precious flag, checking default duplicate and inconclusive behavior as well as submitBlock and submitSolution preferring a same-work side block when precious is set."
  },
  {
   "sha": "5299092c2394fddb2d9c18a4ab333d1dd67b4a62",
   "date": "2026-07-24T02:22:59Z",
   "message": "test: deduplicate proof-of-work grinding"
  },
  {
   "sha": "5d1bf44db5dd2f6f0c28dd09be0be7749687c2a9",
   "date": "2026-07-24T02:22:59Z",
   "message": "test: cover precious IPC mining submissions\n\nExtend the IPC mining functional test to exercise the new precious argument for submitBlock and submitSolution, including default same-work side-block behavior and precious reorg behavior."
  },
  {
   "sha": "95f62bce86d7c56ba170b3fb813f61cd9ca13aed",
   "date": "2026-07-24T02:22:59Z",
   "message": "doc: add IPC block submission release note"
  }
 ],
 "timeline": [
  {
   "t": "2026-05-16T04:02:15Z",
   "kind": "force_push",
   "who": "w0xlt",
   "commit": "a02e97d9a2771a6704f196c9d1b24f0276ee9a1f"
  },
  {
   "t": "2026-05-16T09:39:16Z",
   "kind": "comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "text": "Maybe do this after #34672?"
  },
  {
   "t": "2026-07-24T02:37:21Z",
   "kind": "force_push",
   "who": "w0xlt",
   "commit": "95f62bce86d7c56ba170b3fb813f61cd9ca13aed"
  },
  {
   "t": "2026-07-24T12:47:09Z",
   "kind": "review_comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "path": "src/test/miner_tests.cpp",
   "commit": "a1f8966316dcd0807d0ee612327d4a822c89177f",
   "in_reply_to": null,
   "text": "In a1f8966316dcd0807d0ee612327d4a822c89177f _test: cover precious mining submissions_: mmm, I don't think `precious` should change the behavior if the block is duplicate, so just return `duplicate`?\n\nSimilarly, if we already had it, but it wasn't the tip, and we then switch the tip over, `duplicate` still seems like the correct response."
  },
  {
   "t": "2026-07-24T12:48:51Z",
   "kind": "review_comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "path": "src/test/miner_tests.cpp",
   "commit": "a1f8966316dcd0807d0ee612327d4a822c89177f",
   "in_reply_to": null,
   "text": "In a1f8966316dcd0807d0ee612327d4a822c89177f _test: cover precious mining submissions_: this seems to be the main use case, so maybe cover it at the start of the test?\n\nIn general this test is massive, so maybe split it?"
  },
  {
   "t": "2026-07-24T12:50:20Z",
   "kind": "review_comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "path": "src/test/miner_tests.cpp",
   "commit": "a1f8966316dcd0807d0ee612327d4a822c89177f",
   "in_reply_to": null,
   "text": "In a1f8966316dcd0807d0ee612327d4a822c89177f _test: cover precious mining submissions_: since we expect more or less the same behavior as `SubmitBlock`, perhaps it's better to interleave the test? (and then have separate tests for each scenario, rather than for each method)"
  },
  {
   "t": "2026-07-24T12:59:52Z",
   "kind": "review",
   "who": "Sjors",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "95f62bce86d7c56ba170b3fb813f61cd9ca13aed",
   "text": "Concept ACK\n\nThere's some game theory miners should contemplate before using this though:\n\nIt's clearly rational to prefer your own block _for p2p relay_[^0], but it's less obvious that you should mine the next block on it.\n\nThat might be a sunk-cost fallacy. If you saw the other block first, it's a good assumption that the rest of the network also saw it first. If the majority of hash rate is mining on the other side, and if you (the miner, not the pool) can't tip that majority over, it may be a waste of hash power.\n\nIn a Job Declaration scenario, the main criterion for which block to build on should be the side of the fork the pool picked. Unfortunately afaik the sv2 protocol doesn't currently communicate that (cc @plebhash).\n\n[^0]: which could be achieved with some special handling where we briefly switch tip to validate, broadcast and then switch back to the first-seen tip."
  },
  {
   "t": "2026-07-24T20:55:30Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "test/functional/interface_ipc_mining.py",
   "commit": "95f62bce86d7c56ba170b3fb813f61cd9ca13aed",
   "in_reply_to": null,
   "text": "nit: `make_block_variant`, `assert_chain_tip`, and `assert_submit_block` none of them access self \u2014 all should be `@staticmethod`"
  },
  {
   "t": "2026-07-24T21:05:42Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/rpc/blockchain.cpp",
   "commit": "95f62bce86d7c56ba170b3fb813f61cd9ca13aed",
   "in_reply_to": null,
   "text": "nit: `connected` is silently unused. A` [[maybe_unused]]` attribute or a brief comment `(// RPC callers don't need to distinguish connected vs not`) would help the next reader I think..."
  },
  {
   "t": "2026-07-24T21:29:20Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/interfaces/mining.h",
   "commit": "95f62bce86d7c56ba170b3fb813f61cd9ca13aed",
   "in_reply_to": null,
   "text": "nit: perhaps worth clarifying that this includes blocks that are ancestors of the active tip, not just the tip itself, so callers don't assume `result=true` implies a reorg occurred? (If I understand it correctly)"
  },
  {
   "t": "2026-07-24T21:29:33Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/interfaces/mining.h",
   "commit": "95f62bce86d7c56ba170b3fb813f61cd9ca13aed",
   "in_reply_to": null,
   "text": "nit: same as the [above](https://github.com/bitcoin/bitcoin/pull/35300/changes#r3648263045)."
  },
  {
   "t": "2026-07-24T21:33:05Z",
   "kind": "review",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "95f62bce86d7c56ba170b3fb813f61cd9ca13aed",
   "text": "Concept ACK\n\nAdding `precious=true` to submitBlock and submitSolution, allows IPC mining clients atomically submit and prefer a same-work block in one go instead of a separate `preciousblock` RPC call.\n\nThe `ActivateBestChain_` refactor is a clean prerequisite (so in commit 2 `PreciousBlock` can call it directly).\n\nLeft some nits (none blocking)."
  }
 ],
 "labels_log": [
  {
   "t": "2026-05-16T03:23:51Z",
   "action": "labeled",
   "label": "Mining",
   "who": "DrahtBot"
  },
  {
   "t": "2026-05-16T04:02:40Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-05-16T05:23:13Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-05-17T18:04:57Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-24T03:45:32Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-14T15:42:54Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2026-05-16T03:23:55Z",
   "kind": "convert_to_draft",
   "who": "w0xlt"
  }
 ],
 "text_chars": 5066,
 "text_tokens_estimate": 1266,
 "changed_paths": [
  "doc/release-notes-35300.md",
  "src/interfaces/mining.h",
  "src/ipc/capnp/mining.capnp",
  "src/node/interfaces.cpp",
  "src/node/miner.cpp",
  "src/node/miner.h",
  "src/rpc/blockchain.cpp",
  "src/test/blockencodings_tests.cpp",
  "src/test/blockfilter_index_tests.cpp",
  "src/test/fuzz/util.h",
  "src/test/headers_sync_chainwork_tests.cpp",
  "src/test/miner_tests.cpp",
  "src/test/peerman_tests.cpp",
  "src/test/util/mining.cpp",
  "src/test/util/mining.h",
  "src/test/util/setup_common.cpp",
  "src/test/validation_block_tests.cpp",
  "src/validation.cpp",
  "src/validation.h",
  "test/functional/interface_ipc_mining.py"
 ],
 "files": [
  {
   "path": "doc/release-notes-35300.md",
   "add": 20,
   "del": 0
  },
  {
   "path": "src/interfaces/mining.h",
   "add": 15,
   "del": 8
  },
  {
   "path": "src/ipc/capnp/mining.capnp",
   "add": 2,
   "del": 2
  },
  {
   "path": "src/node/interfaces.cpp",
   "add": 4,
   "del": 4
  },
  {
   "path": "src/node/miner.cpp",
   "add": 47,
   "del": 23
  },
  {
   "path": "src/node/miner.h",
   "add": 3,
   "del": 2
  },
  {
   "path": "src/rpc/blockchain.cpp",
   "add": 2,
   "del": 1
  },
  {
   "path": "src/test/blockencodings_tests.cpp",
   "add": 4,
   "del": 4
  },
  {
   "path": "src/test/blockfilter_index_tests.cpp",
   "add": 2,
   "del": 2
  },
  {
   "path": "src/test/fuzz/util.h",
   "add": 2,
   "del": 4
  },
  {
   "path": "src/test/headers_sync_chainwork_tests.cpp",
   "add": 2,
   "del": 11
  },
  {
   "path": "src/test/miner_tests.cpp",
   "add": 252,
   "del": 11
  },
  {
   "path": "src/test/peerman_tests.cpp",
   "add": 2,
   "del": 2
  },
  {
   "path": "src/test/util/mining.cpp",
   "add": 10,
   "del": 8
  },
  {
   "path": "src/test/util/mining.h",
   "add": 7,
   "del": 0
  },
  {
   "path": "src/test/util/setup_common.cpp",
   "add": 2,
   "del": 2
  },
  {
   "path": "src/test/validation_block_tests.cpp",
   "add": 2,
   "del": 4
  },
  {
   "path": "src/validation.cpp",
   "add": 18,
   "del": 7
  },
  {
   "path": "src/validation.h",
   "add": 14,
   "del": 3
  },
  {
   "path": "test/functional/interface_ipc_mining.py",
   "add": 146,
   "del": 2
  }
 ],
 "test_lines": 481,
 "git": {
  "head": "95f62bce86d7c56ba170b3fb813f61cd9ca13aed",
  "head_matches_backup": true,
  "base": "290cb2f17ef6ba9198934bbaec53fa962a1dfa18",
  "commits": [
   {
    "sha": "42d48e7760",
    "subject": "refactor: extract ActivateBestChain_ helper",
    "files": 2,
    "add": 19,
    "del": 5
   },
   {
    "sha": "f7a7b39e37",
    "subject": "mining: add precious IPC block submission option",
    "files": 9,
    "add": 89,
    "del": 48
   },
   {
    "sha": "a1f8966316",
    "subject": "test: cover precious mining submissions",
    "files": 1,
    "add": 257,
    "del": 8
   },
   {
    "sha": "5299092c23",
    "subject": "test: deduplicate proof-of-work grinding",
    "files": 10,
    "add": 34,
    "del": 46
   },
   {
    "sha": "5d1bf44db5",
    "subject": "test: cover precious IPC mining submissions",
    "files": 1,
    "add": 146,
    "del": 2
   },
   {
    "sha": "95f62bce86",
    "subject": "doc: add IPC block submission release note",
    "files": 1,
    "add": 20,
    "del": 0
   }
  ],
  "patch_truncated": true
 },
 "input_hash": "a989dc183f41143f",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}