{
 "number": 33637,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/33637",
 "title": "refactor: optimize block index comparisons (1.4-6.8x faster)",
 "author": "l0rinc",
 "author_association": "MEMBER",
 "created_at": "2025-10-16T01:54:31Z",
 "updated_at": "2026-09-15T21:59:49Z",
 "age_days": 336,
 "draft": false,
 "labels": [
  "Refactoring"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "0d1119129fd2f9e7700702766121294b6fdf9d27",
 "head_ref": "l0rinc/block_index_comparators",
 "head_repo": "l0rinc/bitcoin",
 "head_history": [
  {
   "t": "2025-10-18T05:55:41Z",
   "sha": "c15d839aefba017e64f14cd9cd2779655352f4b6"
  },
  {
   "t": "2025-10-28T23:18:41Z",
   "sha": "a5584716cb0984ba9e80007be4618391f89ccd96"
  },
  {
   "t": "2025-10-31T10:56:36Z",
   "sha": "da5eb752a8a85fb0a76284298028d110726c89d5"
  },
  {
   "t": "2025-10-31T13:10:52Z",
   "sha": "5cbb9a40873203ea5a4dd0aa7127c9756da2f607"
  },
  {
   "t": "2025-11-03T12:48:00Z",
   "sha": "237eec0f7ca095bc60e40ee94ba1a160a7064753"
  },
  {
   "t": "2025-11-25T14:52:39Z",
   "sha": "6e9061f8b7ad77df4566990121f5bebc1f9e6e15"
  },
  {
   "t": "2026-01-15T17:13:17Z",
   "sha": "a37cd53f7b689e37578c6e28ca33ec4fd2dec5d9"
  },
  {
   "t": "2026-01-15T19:19:56Z",
   "sha": "78b43065a1746c19f74fe6380d765d5922e5c541"
  },
  {
   "t": "2026-02-02T10:44:45Z",
   "sha": "80bfeaa240611401c1ffa41f6968b1f79b621938"
  },
  {
   "t": "2026-02-02T21:42:32Z",
   "sha": "5ab47892ad6328307b42c6065b51a01baf6cb600"
  },
  {
   "t": "2026-02-03T11:46:30Z",
   "sha": "703165e6d3b9fbd58b9c31ddce0e961047fc5e71"
  },
  {
   "t": "2026-08-21T19:56:28Z",
   "sha": "7dc58c2a97c5c494dd9ee93b98df2e2a6b3745f3"
  },
  {
   "t": "2026-08-21T21:37:37Z",
   "sha": "9382a8f553262a91dc3a3188b66b4ab912f81a9a"
  },
  {
   "t": "2026-08-21T23:55:42Z",
   "sha": "0d1119129fd2f9e7700702766121294b6fdf9d27"
  }
 ],
 "additions": 247,
 "deletions": 44,
 "changed_files": 12,
 "commit_count": 7,
 "size_bucket": "M",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "ack": [
     {
      "login": "optout21",
      "url": "https://github.com/bitcoin/bitcoin/pull/33637#issuecomment-5377723904"
     }
    ],
    "concept_ack": [
     {
      "login": "mzumsande",
      "url": "https://github.com/bitcoin/bitcoin/pull/33637#pullrequestreview-3401558839"
     }
    ],
    "approach_ack": [
     {
      "login": "Raimo33",
      "url": "https://github.com/bitcoin/bitcoin/pull/33637#issuecomment-3414573082"
     }
    ],
    "stale_ack": [
     {
      "login": "laanwj",
      "url": "https://github.com/bitcoin/bitcoin/pull/33637#pullrequestreview-3364368958"
     }
    ]
   },
   "conflicts": [
    {
     "number": 33324,
     "title": "blocks: add resumable reobfuscation for existing block files",
     "author": "l0rinc"
    }
   ]
  }
 },
 "acks_parsed": {
  "Raimo33": {
   "kind": "approach_ack",
   "hash": null,
   "t": "2025-10-17T09:16:18Z",
   "stale": false
  },
  "laanwj": {
   "kind": "ack",
   "hash": "c15d839aefba017e64f14cd9cd2779655352f4b6",
   "t": "2025-10-22T08:44:58Z",
   "stale": true
  },
  "mzumsande": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2025-10-30T22:08:51Z",
   "stale": false
  },
  "optout21": {
   "kind": "ack",
   "hash": "0d1119129fd2f9e7700702766121294b6fdf9d27",
   "t": "2026-08-22T03:54:39Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 1,
  "stale_ack": 1,
  "concept_ack": 1,
  "approach_ack": 1,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 1,
  "changes_requested": 0,
  "distinct_reviewers": [
   "Christewart",
   "Raimo33",
   "dergoegge",
   "laanwj",
   "maflcko",
   "mzumsande",
   "optout21",
   "sipa"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-08-21T23:55:42Z",
  "last_reviewer_activity": "2026-08-22T03:54:39Z",
  "last_reviewer": "optout21",
  "author_silent_days": 26,
  "waiting_on_author_days": 26,
  "days_since_update": 1
 },
 "refs": {
  "mentioned": [
   29640,
   33334
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 33334,
    "type": "pull",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "node: optimize CBlockIndexWorkComparator"
   },
   {
    "number": 29640,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2025-10-27",
    "title": "Fix tiebreak when loading blocks from disk (and add tests for comparing chain ties)"
   }
  ],
  "conflicts": [
   33324
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/bench/blockstorage.cpp",
  "src/node/blockstorage.h",
  "src/test/arith_uint256_tests.cpp",
  "src/test/blockchain_tests.cpp"
 ],
 "body": "**Context:** The comparator is often called either directly or for the sorting of [`setBlockIndexCandidates`](https://github.com/bitcoin/bitcoin/blob/master/src/validation.h#L637), a red-black tree-set containing valid block headers where the comparator is invoked extensively.\nBesides the sorted set usages, the comparator is used directly in `Chainstate` in `FindMostWorkChain`, `PruneBlockIndexCandidates`, `ActivateBestChain`, and `InvalidateBlock`; and in `ChainstateManager` in `LoadBlockIndex`, `CheckBlockIndex`, `ActivateSnapshot`, and `PopulateAndValidateSnapshot`.\n\nIt was profiled during the investigation of https://github.com/bitcoin/bitcoin/issues/33618#issuecomment-3402229976.\n\n**Testing:** To ensure the optimized implementations are both fast and correct, the first commit adds a dedicated benchmark to measure `CBlockIndexWorkComparator` performance, and the second commit adds deterministic sorting tests comparing the new implementation with the original one. Later commits add fuzz targets for equivalence coverage.\n\n**Results:**\n[quoted text omitted]\n\n* `CBlockIndexWorkComparator`: 100,772,511 cmp/s \u2192 656,674,205 cmp/s = 6.51x faster\n* `CheckBlockIndex`: 9,091 ops/s \u2192 14,765 ops/s = 1.62x faster\n[quoted text omitted]\n\n* `CBlockIndexWorkComparator`: 100,451,893 cmp/s \u2192 683,414,234 cmp/s = 6.8x faster\n* `CheckBlockIndex`: 10,322 ops/s \u2192 14,376 ops/s = 1.39x faster\n\nSee https://corecheck.dev/bitcoin/bitcoin/pulls/33637 for the CI's `CheckBlockIndex` performance.\n\ngcc and clang measurements\n\n[quoted text omitted]\nb60450fae8 bench: add benchmark to measure `CBlockIndexWorkComparator` performance\n\n|              ns/cmp |               cmp/s |    err% |         ins/cmp |         cyc/cmp |    IPC |        bra/cmp |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|                9.92 |      100,772,511.62 |    0.0% |           63.98 |           35.64 |  1.795 |          14.17 |    1.9% |      5.50 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|          109,996.46 |            9,091.20 |    0.2% |    1,014,421.11 |      394,979.29 |  2.568 |     313,025.11 |    0.0% |      5.50 | `CheckBlockIndex`\n\ne2e02177ba refactor: inline `arith_uint256` comparison operator\n\n|              ns/cmp |               cmp/s |    err% |         ins/cmp |         cyc/cmp |    IPC |        bra/cmp |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|                6.48 |      154,439,491.66 |    0.0% |           31.01 |           23.25 |  1.334 |           7.16 |    3.8% |      5.50 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|          105,754.86 |            9,455.83 |    0.1% |      913,130.11 |      379,588.20 |  2.406 |     276,692.11 |    0.0% |      5.50 | `CheckBlockIndex`\n\n85b74b01de refactor: optimize `arith_uint256` comparison with spaceship operator\n\n|              ns/cmp |               cmp/s |    err% |         ins/cmp |         cyc/cmp |    IPC |        bra/cmp |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|                6.37 |      156,990,488.06 |    0.0% |           28.85 |           22.87 |  1.261 |           8.61 |    3.2% |      5.50 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|           83,803.10 |           11,932.73 |    0.0% |      743,565.09 |      300,824.84 |  2.472 |     232,646.08 |    0.0% |      5.56 | `CheckBlockIndex`\n\ndeb58eea2f refactor: optimize `CBlockIndexWorkComparator` with std::tie\n\n|              ns/cmp |               cmp/s |    err% |         ins/cmp |         cyc/cmp |    IPC |        bra/cmp |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|                1.52 |      656,674,205.98 |    0.0% |           13.18 |            5.47 |  2.410 |           3.06 |    0.1% |      5.50 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|           67,726.84 |           14,765.19 |    0.2% |      585,826.07 |      243,155.90 |  2.409 |     181,920.07 |    0.0% |      5.54 | `CheckBlockIndex`\n[quoted text omitted]\n\nb60450fae8 bench: add benchmark to measure `CBlockIndexWorkComparator` performance\n\n|              ns/cmp |               cmp/s |    err% |         ins/cmp |         cyc/cmp |    IPC |        bra/cmp |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|                9.96 |      100,451,893.46 |    0.0% |           61.28 |           35.75 |  1.714 |          13.62 |    2.1% |      5.52 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|           96,878.70 |           10,322.19 |    0.1% |      802,827.10 |      347,679.01 |  2.309 |     234,823.10 |    0.0% |      5.50 | `CheckBlockIndex`\n\ne2e02177ba refactor: inline `arith_uint256` comparison operator\n\n|              ns/cmp |               cmp/s |    err% |         ins/cmp |         cyc/cmp |    IPC |        bra/cmp |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|                6.13 |      163,183,693.10 |    0.0% |           25.74 |           22.01 |  1.170 |           6.10 |    4.6% |      5.50 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|           86,307.94 |           11,586.42 |    1.2% |      646,229.09 |      309,785.33 |  2.086 |     195,119.09 |    0.0% |      5.54 | `CheckBlockIndex`\n\n85b74b01de refactor: optimize `arith_uint256` comparison with spaceship operator\n\n|              ns/cmp |               cmp/s |    err% |         ins/cmp |         cyc/cmp |    IPC |        bra/cmp |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|                6.36 |      157,330,900.16 |    1.0% |           26.20 |           22.61 |  1.159 |           6.55 |    4.4% |      5.53 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|           75,031.66 |           13,327.71 |    1.0% |      650,604.15 |      266,934.04 |  2.437 |     149,967.14 |    0.0% |      5.54 | `CheckBlockIndex`\n\ndeb58eea2f refactor: optimize `CBlockIndexWorkComparator` with std::tie\n\n|              ns/cmp |               cmp/s |    err% |         ins/cmp |         cyc/cmp |    IPC |        bra/cmp |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|                1.46 |      683,414,234.14 |    0.0% |           16.12 |            5.25 |  3.067 |           4.02 |    0.1% |      5.50 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|           69,559.70 |           14,376.14 |    0.1% |      559,208.07 |      249,654.28 |  2.240 |     132,342.07 |    0.0% |      5.51 | `CheckBlockIndex`\n\n**Reproducer:** Run the equivalence tests with:\n```bash\ncmake -B build && cmake --build build && ./build/bin/test_bitcoin --run_test=arith_uint256_tests,blockchain_tests\n```\nEach commit shows how it changes the relevant benchmarks.\n\nBenchmark script\n\n```bash\nfor compiler in gcc clang; do \\\n  if [ \"$compiler\" = \"gcc\" ]; then CC=gcc; CXX=g++; COMP_VER=$(gcc -dumpfullversion); \\\n  else CC=clang; CXX=clang++; COMP_VER=$(clang -dumpversion); fi && \\\n  echo \"> Compiler: $compiler $COMP_VER\" && \\\n  for commit in 70c6244b709fcf6a853ea44b91b9ed219609ac90 \\\n                516e05cd7d8dbb61b05854c59f5393367e502284 \\\n                d053b27c06d06cccbc6395b0aa7dc1c4193a6fc3 \\\n                8ef4ce2cb3ac80cbe58b8cf76e183f9eca6fafe4 \\\n                703165e6d3b9fbd58b9c31ddce0e961047fc5e71; do \\\n    git fetch origin $commit >/dev/null 2>&1 && git checkout $commit >/dev/null 2>&1 && git log -1 --pretty='%h %s' && \\\n    rm -rf build && \\\n    cmake -B build -DBUILD_BENCH=ON -DENABLE_IPC=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo \\\n      -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX >/dev/null 2>&1 && \\\n    cmake --build build -j$(nproc) >/dev/null 2>&1 && \\\n    for i in 1; do \\\n      build/bin/bench_bitcoin -filter='CBlockIndexWorkComparator|CheckBlockIndex' -min-time=5000; \\\n    done; \\\n  done; \\\ndone\n```\n\nNote: something similar was already started in #33334, but this is a broader optimization that doesn't use the same technique.",
 "commits": [
  {
   "sha": "9ede96fcc1ff4b0d4612d3eb2541d6fbc341585e",
   "date": "2026-08-21T19:55:28Z",
   "message": "bench: add benchmark to measure `CBlockIndexWorkComparator` performance\n\nProfiling shows this comparator consumes a significant portion of `CheckBlockIndex()`:\n... ChainstateManager::CheckBlockIndex()\n    ... std::_Rb_tree<...>::find(...)\n        ... node::CBlockIndexWorkComparator::operator()(...)\n            ... base_uint<256u>::CompareTo(...) const\n\nThis commit introduces a benchmark that performs pairwise comparisons on 1000 randomly generated block indices (with some duplicates) to establish baseline performance metrics before further optimization.\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                4.35 |      229,642,637.11 |    0.2% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           38,213.19 |           26,168.97 |    0.5% |      1.10 | `CheckBlockIndex`"
  },
  {
   "sha": "30cad89cb59fcdd8a2cb4896197c70bd9f9ecb41",
   "date": "2026-08-21T21:35:32Z",
   "message": "test: add sorting tests for `CBlockIndexWorkComparator` and `arith_uint256`\n\nThis test was added before other changes to create a baseline behavior."
  },
  {
   "sha": "0521bd53ac4245e2507ddde23cb43998554406cd",
   "date": "2026-08-21T21:35:32Z",
   "message": "move-only: inline `CBlockIndex` comparators to header\n\nMove `CBlockIndexWorkComparator::operator()` and `CBlockIndexHeightOnlyComparator::operator()` to the header to facilitate inlining.\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.87 |      348,283,873.30 |    0.2% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           36,534.37 |           27,371.49 |    0.3% |      1.10 | `CheckBlockIndex`"
  },
  {
   "sha": "164ccc5241d59df6f1bed0d2b02d196c32f9cda5",
   "date": "2026-08-21T21:35:32Z",
   "message": "fuzz: add equivalence coverage for comparison refactors\n\nAdd equivalence coverage to validate behavior while optimizing comparison operations.\nThe originals were kept exactly as the previous implementations were done.\n\nThe `arith_uint256` equivalence check is implemented as the `arith_uint256_comparison_equivalence` fuzz target.\nIt compares the refactored `operator<=>` against a snapshot of the old word-by-word comparison for all operators (<, >, <=, >=, ==, !=).\n\nThe `CBlockIndexWorkComparator` equivalence check is implemented as the `block_index_work_comparator` fuzz target.\nIt compares the refactored comparator against a snapshot of the old comparator logic (chain work, sequence ID, pointer tiebreak).\n\nAdd deterministic unit tests to lock in the expected ordering of both comparators.\n\nCo-authored-by: Martin Zumsande <mzumsande@gmail.com>"
  },
  {
   "sha": "1825dffbb4d5946c180019d12aa4a1aa8099de01",
   "date": "2026-08-21T23:55:18Z",
   "message": "refactor: optimize `CBlockIndexWorkComparator` with `std::tie`\n\nReplace manual comparison branches with a single tuple comparison, allowing the compilers to generate more efficient comparison code.\n\nMade them explicitly `noexcept`, which can enable small optimizer wins and aligns with expectations for hot-path comparators used in ordered containers.\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.00 |      499,008,850.73 |    0.2% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           32,297.54 |           30,962.11 |    0.9% |      1.10 | `CheckBlockIndex`\n\nCo-authored-by: Martin Zumsande <mzumsande@gmail.com>"
  },
  {
   "sha": "d246d8736edee5b04db8b72e0e0ba0b987a9faf2",
   "date": "2026-08-21T23:55:18Z",
   "message": "refactor: inline `arith_uint256` comparison operator\n\nRemove the `CompareTo` method and inline its logic directly into `operator<=>`, updating related comments.\nThis eliminates function call overhead in the hot path during block generation and chain selection.\n\nThe comparison algorithm remains unchanged, iterating from most significant to least significant byte, but now returns `std::strong_ordering` directly, removing an extra conversion and enabling better inlining.\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.18 |      459,159,880.91 |    0.2% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           31,780.27 |           31,466.07 |    0.5% |      1.10 | `CheckBlockIndex`"
  },
  {
   "sha": "0d1119129fd2f9e7700702766121294b6fdf9d27",
   "date": "2026-08-21T23:55:18Z",
   "message": "refactor: optimize `arith_uint256` comparison with spaceship operator\n\nReplace multiple comparisons with a single C++20 spaceship operator call directly.\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                0.68 |    1,477,110,677.23 |    0.2% |      1.06 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           27,528.11 |           36,326.51 |    0.2% |      1.10 | `CheckBlockIndex`"
  }
 ],
 "timeline": [
  {
   "t": "2025-10-17T09:16:18Z",
   "kind": "comment",
   "who": "Raimo33",
   "assoc": "CONTRIBUTOR",
   "text": "Approach ACK\n\nI have tested the new block index comparator but I\u2019ll refrain from acking the added benchmarks/tests"
  },
  {
   "t": "2025-10-17T15:00:25Z",
   "kind": "review_comment",
   "who": "sipa",
   "assoc": "MEMBER",
   "path": "src/bench/blockstorage.cpp",
   "commit": "f74572eb1d9eba95aab42cd0b98793d7dc38e2ef",
   "in_reply_to": null,
   "text": "Mind using `bench.batch(n * n).units(\"cmp\")` or so here, to put the output units in perspective?"
  },
  {
   "t": "2025-10-18T05:55:41Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "c15d839aefba017e64f14cd9cd2779655352f4b6"
  },
  {
   "t": "2025-10-18T05:55:56Z",
   "kind": "review_comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "path": "src/bench/blockstorage.cpp",
   "commit": "f74572eb1d9eba95aab42cd0b98793d7dc38e2ef",
   "in_reply_to": 2440314209,
   "text": "Done, updated the commit messages and PR descriptions as well."
  },
  {
   "t": "2025-10-18T21:34:57Z",
   "kind": "comment",
   "who": "Christewart",
   "assoc": "CONTRIBUTOR",
   "text": "I attempted to run the script, not really sure what these results indicate. Just pasting what the results were\n\n```\nDarwin Chriss-MacBook-Pro.local 24.6.0 Darwin Kernel Version 24.6.0: Mon Jul 14 11:30:55 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T6031 arm64\n```\n\n```\nApple clang version 17.0.0 (clang-1700.3.19.1)\nTarget: arm64-apple-darwin24.6.0\nThread model: posix\nInstalledDir: /Library/Developer/CommandLineTools/usr/bin\n```\n\n```\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                4.97 |      201,237,014.91 |    0.4% |      5.49 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           43,777.21 |           22,842.94 |    0.3% |      5.41 | `CheckBlockIndex`\n```\n\n```\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                1.89 |      529,694,702.31 |    0.1% |      5.50 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           38,303.87 |           26,107.02 |    0.1% |      5.35 | `CheckBlockIndex`\n```\n\n```\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.31 |      432,334,219.11 |    0.6% |      5.45 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           33,598.60 |           29,763.15 |    0.2% |      5.32 | `CheckBlockIndex`\n```\n```\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                0.78 |    1,287,258,159.19 |    0.1% |      5.46 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           31,055.32 |           32,200.61 |    0.1% |      5.30 | `CheckBlockIndex`\n```\n</details"
  },
  {
   "t": "2025-10-19T00:24:34Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "Thanks for the measurements @Christewart, this is how your measurements compare to mine (but most importantly how it compares to `master`):"
  },
  {
   "t": "2025-10-22T08:44:58Z",
   "kind": "review",
   "who": "laanwj",
   "assoc": "MEMBER",
   "state": "APPROVED",
   "commit": "c15d839aefba017e64f14cd9cd2779655352f4b6",
   "text": "Code review ACK c15d839aefba017e64f14cd9cd2779655352f4b6\ni did not run the benchmarks but the code changes look good, using `<=>` makes sense."
  },
  {
   "t": "2025-10-28T23:18:41Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "a5584716cb0984ba9e80007be4618391f89ccd96"
  },
  {
   "t": "2025-10-28T23:19:25Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "Rebased after https://github.com/bitcoin/bitcoin/pull/29640 - only change was adjusting the comment"
  },
  {
   "t": "2025-10-30T20:41:18Z",
   "kind": "review_comment",
   "who": "mzumsande",
   "assoc": "MEMBER",
   "path": "src/test/blockchain_tests.cpp",
   "commit": "a5584716cb0984ba9e80007be4618391f89ccd96",
   "in_reply_to": null,
   "text": "should take the latest comments from the old function after #29640"
  },
  {
   "t": "2025-10-30T21:13:33Z",
   "kind": "review_comment",
   "who": "mzumsande",
   "assoc": "MEMBER",
   "path": "src/test/arith_uint256_tests.cpp",
   "commit": "80bfeaa240611401c1ffa41f6968b1f79b621938",
   "in_reply_to": null,
   "text": "commit msg 08d098947aaeae67e3aeef262df1ecdbdbed744a: wway ->way"
  },
  {
   "t": "2025-10-30T21:15:27Z",
   "kind": "review_comment",
   "who": "mzumsande",
   "assoc": "MEMBER",
   "path": "src/test/blockchain_tests.cpp",
   "commit": "80bfeaa240611401c1ffa41f6968b1f79b621938",
   "in_reply_to": null,
   "text": "this looks like a fuzz test, why not make it an actual fuzz target out of this?"
  },
  {
   "t": "2025-10-30T21:18:50Z",
   "kind": "review_comment",
   "who": "mzumsande",
   "assoc": "MEMBER",
   "path": "src/test/blockchain_tests.cpp",
   "commit": "80bfeaa240611401c1ffa41f6968b1f79b621938",
   "in_reply_to": null,
   "text": "would suggest to add a bit more explanation, e.g. mentioning that old_comparator is a snapshot of an old implementation, so that people who look at this in years understand where it's coming from."
  },
  {
   "t": "2025-10-30T21:48:16Z",
   "kind": "review_comment",
   "who": "mzumsande",
   "assoc": "MEMBER",
   "path": "src/node/blockstorage.h",
   "commit": "a5584716cb0984ba9e80007be4618391f89ccd96",
   "in_reply_to": null,
   "text": "I find \"ascending/descending\" confusing here, I would have expected the opposites: \"descending work\" means most work first, but the strict weak ordering of C++ comparators would place the one with the lower work first.\n\nWould suggest something like\n\"First compare by work (less first), then by earliest activatable time (higher sequence first), then by pointer value (higher first).\""
  },
  {
   "t": "2025-10-30T22:08:51Z",
   "kind": "review",
   "who": "mzumsande",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "a5584716cb0984ba9e80007be4618391f89ccd96",
   "text": "Concept ACK\n\nNot 100% sure yet about 2dd0f2ced35a268bcab661c671e7c70271cdd91f, seems like inlining gives most of the speedup, whereas the gain of using the spaceship operator (which comes at the cost of readability)  is marginal."
  },
  {
   "t": "2025-10-31T08:37:12Z",
   "kind": "review_comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "path": "src/test/blockchain_tests.cpp",
   "commit": "a5584716cb0984ba9e80007be4618391f89ccd96",
   "in_reply_to": 2479462159,
   "text": "~I have already done that, which parts do you think I'm missing?~ Edit: ah in the tests, good point, let me update it"
  },
  {
   "t": "2025-10-31T10:56:36Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "da5eb752a8a85fb0a76284298028d110726c89d5"
  },
  {
   "t": "2025-10-31T10:56:39Z",
   "kind": "review_comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "path": "src/node/blockstorage.h",
   "commit": "a5584716cb0984ba9e80007be4618391f89ccd96",
   "in_reply_to": 2479610586,
   "text": "I wanted to use the SQL [order-by](https://www.postgresql.org/docs/current/queries-order.html#QUERIES-ORDER) terminology here\n[quoted text omitted]\nSimilarly, descending order is determined with the > operator.\n\nBut you're right, I inverted the terminology, added a dedicated test to check for hard-coded order (first param is increasing, second is decreasing), updated the comments (this is why I find comments a lazy solution, it's too easy to keep them up-to-date), added you as coauthor."
  },
  {
   "t": "2025-10-31T10:56:42Z",
   "kind": "review_comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "path": "src/test/blockchain_tests.cpp",
   "commit": "80bfeaa240611401c1ffa41f6968b1f79b621938",
   "in_reply_to": 2479555866,
   "text": "I strongly dislike code comments, I prefer explaining with live code over dead comments - and if people disagree they can always do a blame which instantly reveals the purpose since I also over-explain in commit messages usually.\nAre the names `old_comparator` in a `cblockindex_comparator_equivalence ` not enough to make it obvious that? I\nI have added a comment anyway, let me know if it helps."
  },
  {
   "t": "2025-10-31T10:56:44Z",
   "kind": "review_comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "path": "src/test/blockchain_tests.cpp",
   "commit": "80bfeaa240611401c1ffa41f6968b1f79b621938",
   "in_reply_to": 2479547609,
   "text": "I look at fuzz tests as exploratory tools that are hard to write and run and debug and do code coverage on - not trivial to maintain (see https://github.com/bitcoin/bitcoin/issues/33731), it's definitely not my go-to way to test something. This is just a randomized property based unit test - easy to debug, easy to run and understand.\nBut looking at the tests again, I can make it more deterministic so that it hits all important branches which allows me to reduce the iteration count - code coverage and debugging shows this regularly tests each branch now (green line on left side):\n\nAdded you as coauthor."
  },
  {
   "t": "2025-10-31T10:57:05Z",
   "kind": "review_comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "path": "src/test/arith_uint256_tests.cpp",
   "commit": "80bfeaa240611401c1ffa41f6968b1f79b621938",
   "in_reply_to": 2479542423,
   "text": "done"
  },
  {
   "t": "2025-10-31T13:10:52Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "5cbb9a40873203ea5a4dd0aa7127c9756da2f607"
  },
  {
   "t": "2025-10-31T13:13:33Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "Pushed, thanks for the review, you had a few good points, added you as coauthor.\n\n[quoted text omitted]\nthe spaceship might not be very familiar to us yet, but it's arguably simpler, having fewer moving parts, and some compilers prefer that over the manual comparisons."
  },
  {
   "t": "2025-11-03T12:31:02Z",
   "kind": "review_comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/arith_uint256_tests.cpp",
   "commit": "5cbb9a40873203ea5a4dd0aa7127c9756da2f607",
   "in_reply_to": null,
   "text": "nit: `--i` is preferred"
  },
  {
   "t": "2025-11-03T12:35:08Z",
   "kind": "review_comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/blockchain_tests.cpp",
   "commit": "5cbb9a40873203ea5a4dd0aa7127c9756da2f607",
   "in_reply_to": null,
   "text": "nit: indentation seems off (extra indent)"
  },
  {
   "t": "2025-11-03T12:43:17Z",
   "kind": "review_comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "path": "src/test/arith_uint256_tests.cpp",
   "commit": "5cbb9a40873203ea5a4dd0aa7127c9756da2f607",
   "in_reply_to": 2486328436,
   "text": "Generally yes, but here I wanted to copy the [original code](https://github.com/bitcoin/bitcoin/pull/33637/files#diff-2e16a7ac99a65c1617112c3c326fba499b0010fe6c48b92b59bbc9696d883585L104) as closely as possible"
  },
  {
   "t": "2025-11-03T12:44:19Z",
   "kind": "comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "text": "utACK 5cbb9a40873203ea5a4dd0aa7127c9756da2f607\n\nAn evident, localized micro-optimization in a hot-path. I haven't run measurements."
  },
  {
   "t": "2025-11-03T12:48:00Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "237eec0f7ca095bc60e40ee94ba1a160a7064753"
  },
  {
   "t": "2025-11-03T12:48:20Z",
   "kind": "review_comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "path": "src/test/arith_uint256_tests.cpp",
   "commit": "5cbb9a40873203ea5a4dd0aa7127c9756da2f607",
   "in_reply_to": 2486328436,
   "text": "Pushed anyway, thanks"
  },
  {
   "t": "2025-11-03T12:48:34Z",
   "kind": "review_comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "path": "src/test/blockchain_tests.cpp",
   "commit": "5cbb9a40873203ea5a4dd0aa7127c9756da2f607",
   "in_reply_to": 2486341559,
   "text": "done, thanks"
  },
  {
   "t": "2025-11-03T12:52:15Z",
   "kind": "comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "text": "reACK 80bfeaa240611401c1ffa41f6968b1f79b621938    Rebase.\n\nPrev:\nreACK 78b43065a1746c19f74fe6380d765d5922e5c541    Rebase, no content changes.\nreACK 6e9061f8b7ad77df4566990121f5bebc1f9e6e15\nutACK 237eec0f7ca095bc60e40ee94ba1a160a7064753\nRe-acked (after 7 mins :D ), only minor/formatting changes since last review"
  },
  {
   "t": "2025-11-06T12:43:03Z",
   "kind": "review_comment",
   "who": "dergoegge",
   "assoc": "MEMBER",
   "path": "src/test/blockchain_tests.cpp",
   "commit": "80bfeaa240611401c1ffa41f6968b1f79b621938",
   "in_reply_to": 2479547609,
   "text": "[quoted text omitted]\n\nThere is a learning curve to writing and using fuzz testing but it is 100% worth getting in to. The maintenance aspect only relates to running them using libFuzzer on macOS.\n\nOn average, coverage guided fuzzing will be magnitudes better at finding bugs than this style of unit test. For something as small as the comparator your approach is probably good enough, although you could just have a fixed list of test cases that enumerate all possibilities (for the old comparator) instead? (maybe you do already, didn't look)"
  },
  {
   "t": "2025-11-06T15:34:25Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nI don't follow here. The issue is about the additional `CWallet::WriteBestBlock` overhead? `CBlockIndexWorkComparator` seems unrelated to the issue, at least I can't see how it changed the result between 29.x and 30.x.\n\nInstead of mentioning an unrelated issue, I think it could be better to mention what real-world effect this improvement has. I think that is `-checkblockindex` (default in regtest) and possibly `LoadExternalBlockFile`/`LoadBlockIndex`?"
  },
  {
   "t": "2025-11-06T16:22:42Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nThe original issue won't be fixed since it's not exactly a bug, but we could still speed up the regression by optimizing another bottleneck.\nSince you found the etymology confusing, I have removed the details from the description, only mentioned https://github.com/bitcoin/bitcoin/issues/33618#issuecomment-3402229976 for the flame graph that show this being one of the bottlenecks. Not the biggest one, but the one we can easily optimize and clean up.\n\n[quoted text omitted]\nYes, this was mentioned in the benchmarking section.\n\n[quoted text omitted]\nYes, it's used explicitly in `Chainstate` in `FindMostWorkChain`, `PruneBlockIndexCandidates`, `ActivateBestChain` and `InvalidateBlock`.\nAnd `ChainstateManager` in `LoadBlockIndex`, `CheckBlockIndex`, `ActivateSnapshot` and `PopulateAndValidateSnapshot`.\nBut the [setBlockIndexCandidates](https://github.com/bitcoin/bitcoin/blob/master/src/validation.h#L637) usages should already suffice as motivation, I'd say:\n```bash\ngit grep 'setBlockIndexCandidates.' src/validation.cpp | wc -l\n   44\n```"
  },
  {
   "t": "2025-11-12T22:50:32Z",
   "kind": "review_comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "path": "src/node/blockstorage.h",
   "commit": "0d1119129fd2f9e7700702766121294b6fdf9d27",
   "in_reply_to": null,
   "text": "I thought of eliminating the worst case here (when `pa == pb`, where it has to do the comparison for every byte) with something like:\n```C++\nreturn pa != pb &&\n       std::tie(pa->nChainWork, pb->nSequenceId, pb)\n     < std::tie(pb->nChainWork, pa->nSequenceId, pa);\n```\n\nBut the benchmarks indicate that it's not really faster.\n\nbenchmark with pointer duplicates\n\n```C++\n// Copyright (c) 2025-present The Bitcoin Core developers\n// Distributed under the MIT software license, see the accompanying\n// file COPYING or http://www.opensource.org/licenses/mit-license.php.\n\n#include <arith_uint256.h>\n#include <bench/bench.h>\n#include <chain.h>\n#include <node/blockstorage.h>\n#include <random.h>\n#include <uint256.h>\n\n#include <algorithm>\n#include <memory>\n#include <vector>\n\nstatic void CBlockIndexWorkComparator(benchmark::Bench& bench)\n{\n    FastRandomContext rng{/*fDeterministic=*/true};\n\n    constexpr size_t n{1'000};\n    std::vector<std::shared_ptr<CBlockIndex>> blocks;\n    blocks.reserve(n);\n    for (size_t i{0}; i < n; ++i) {\n        auto block{std::make_shared<CBlockIndex>()};\n        block->nChainWork = UintToArith256(rng.rand256());\n        block->nSequenceId = int32_t(rng.rand32());\n        if (i % 10 == 1) {\n            // Have some duplicates\n            if (rng.randbool()) {\n                block = blocks.back();\n            } else {\n                if (rng.randbool()) block->nChainWork = blocks.back()->nChainWork;\n                if (rng.randbool()) block->nSequenceId = blocks.back()->nSequenceId;\n            }\n        }\n        blocks.push_back(std::move(block));\n    }\n    std::ranges::shuffle(blocks, rng);\n\n    const node::CBlockIndexWorkComparator comparator;\n    bench.batch(n * n).unit(\"cmp\").run([&] {\n        for (size_t i{0}; i < n; ++i) {\n            const auto* lhs{blocks[i].get()};\n            for (size_t j{0}; j < n; ++j) {\n                const auto* rhs{blocks[j].get()};\n                const bool result{comparator(lhs, rhs)};\n                ankerl::nanobench::doNotOptimizeAway(result);\n            }\n        }\n    });\n}\n\nBENCHMARK(CBlockIndexWorkComparator, benchmark::PriorityLevel::HIGH);\n```\n\nb17504b611 refactor: optimize `CBlockIndexWorkComparator` with `std::tie`\n\n|              ns/cmp |               cmp/s |    err% |         ins/cmp |         cyc/cmp |    IPC |        bra/cmp |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|                2.13 |      469,485,340.38 |    0.2% |           15.07 |            5.09 |  2.959 |           4.02 |    0.1% |     11.01 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|           90,265.10 |           11,078.48 |    0.1% |      637,536.00 |      215,946.18 |  2.952 |     178,844.00 |    0.0% |     10.84 | `CheckBlockIndex`\n\n2b77e567d8 refactor: short-circuit `CBlockIndex` comparator for equality\n\n|              ns/cmp |               cmp/s |    err% |         ins/cmp |         cyc/cmp |    IPC |        bra/cmp |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|                2.60 |      385,002,212.20 |    0.0% |           18.00 |            6.22 |  2.894 |           5.00 |    0.0% |     11.00 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------\n|           94,110.53 |           10,625.80 |    0.0% |      682,454.03 |      225,242.05 |  3.030 |     186,486.01 |    0.0% |     11.00 | `CheckBlockIndex`"
  },
  {
   "t": "2025-11-25T14:52:39Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "6e9061f8b7ad77df4566990121f5bebc1f9e6e15"
  },
  {
   "t": "2025-11-25T14:53:23Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "Rebased after https://github.com/bitcoin/bitcoin/commit/4f65a1c5db84426b9d814a18f63ac46632691ab2#diff-f14e9423bd43609969886b2e42751c55606344e0b71780564cdb23515802cec0R12, ready for review again."
  },
  {
   "t": "2026-01-15T17:13:16Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "Rebased to fix silent merge conflict."
  },
  {
   "t": "2026-01-15T17:13:17Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "a37cd53f7b689e37578c6e28ca33ec4fd2dec5d9"
  },
  {
   "t": "2026-01-15T19:19:56Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "78b43065a1746c19f74fe6380d765d5922e5c541"
  },
  {
   "t": "2026-02-02T10:44:43Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "Rebased after conflict with https://github.com/bitcoin/bitcoin/pull/34179/changes#diff-ed3f90693a242b38b9719af171de8f55183576957676dfa358945bea22276bd5R139, ready for review again."
  },
  {
   "t": "2026-02-02T10:44:45Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "80bfeaa240611401c1ffa41f6968b1f79b621938"
  },
  {
   "t": "2026-02-02T17:16:04Z",
   "kind": "comment",
   "who": "sipa",
   "assoc": "MEMBER",
   "text": "You should really add a fuzz test here to compare old and new behavior as suggested [before](https://github.com/bitcoin/bitcoin/pull/33637#discussion_r2479547609); it's the perfect use case for it, as it avoids the need for putting presumed knowledge about potential bugs in the unit tests you create."
  },
  {
   "t": "2026-02-02T21:42:32Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "5ab47892ad6328307b42c6065b51a01baf6cb600"
  },
  {
   "t": "2026-02-02T21:46:26Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nThanks for the hint, I've split the differential fuzzer and kept the simple unit tests o lock in the expected ordering of both comparators.\nAfter a while (if fuzzers can't find any difference) we should be able to remove the fuzzers while keeping only the unit tests."
  },
  {
   "t": "2026-02-03T07:07:59Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "As pointed out earlier, most of the speedup comes from a move-only inline (https://github.com/bitcoin/bitcoin/pull/33637#pullrequestreview-3401558839)?\n\nI think it would be better to just submit a trivial to review move-only change stand-alone, which wouldn't need in-depth review and dedicated differential unit/fuzz tests. Or at least the move-only change should be the first change. This way, it is easier to see if the other changes are worth it to review/test at all."
  },
  {
   "t": "2026-02-03T11:44:47Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nThat's actually what enables the other ones to shine, but I don't mind reordering the commits to make it obvious.\nThe biggest optimization is the spaceship (with inline), it's now the last commit.\n\nMeasurements\n\n```bash\nfor commit in 8b54cc2e71b015b651d7dcbfc3033c1f76c37e4e 9304b3b225f4dcc06b007d073035a586e1806951 0473240b4f8d29016778ebd73745c610c2b437e8 d64d9432a06879e57702f8188a764eb3fc8f2751 c2f69e78ba69ee4232c5190a41509e142b039e8b 7cb0c5f1fc70d57277689d114ab2da14af2a0696 df0153a846036f94e51ab70b7c91491b138d3569; do \\\n    git fetch origin $commit >/dev/null 2>&1 && git checkout $commit >/dev/null 2>&1 && echo \"\" && git log -1 --pretty='%h %s' && \\\n    rm -rfd build >/dev/null 2>&1 && cmake -B build -DBUILD_BENCH=ON -DCMAKE_BUILD_TYPE=Release >/dev/null 2>&1 && \\\n    cmake --build build -j$(nproc) >/dev/null 2>&1 && \\\n    for _ in $(seq 3); do \\\n      sleep 5; \\\n      sudo taskpolicy -t 5 -l 5 nice -n -20 ./build/bin/bench_bitcoin -filter='CBlockIndexWorkComparator|CheckBlockIndex' -min-time=1000; \\\n    done; \\\ndone\n\n8b54cc2e71 bench: add benchmark to measure `CBlockIndexWorkComparator` performance\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                4.41 |      226,584,742.96 |    0.8% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           38,253.37 |           26,141.49 |    0.9% |      1.09 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                4.35 |      229,642,637.11 |    0.2% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           38,213.19 |           26,168.97 |    0.5% |      1.10 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                4.37 |      228,881,057.73 |    0.3% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           38,287.78 |           26,117.99 |    0.4% |      1.10 | `CheckBlockIndex`\n\n9304b3b225 test: add sorting tests for `CBlockIndexWorkComparator` and `arith_uint256`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                4.39 |      227,961,262.13 |    0.5% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           38,333.93 |           26,086.55 |    0.2% |      1.10 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                4.39 |      227,728,690.97 |    0.7% |      1.11 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           39,671.02 |           25,207.32 |    0.3% |      1.10 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                4.40 |      227,294,352.21 |    0.5% |      1.09 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           38,971.06 |           25,660.07 |    1.1% |      1.10 | `CheckBlockIndex`\n\n0473240b4f move-only: inline `CBlockIndex` comparators to header\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.88 |      347,302,616.35 |    0.3% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           36,701.33 |           27,246.97 |    0.3% |      1.10 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.87 |      348,283,873.30 |    0.2% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           36,790.73 |           27,180.76 |    0.6% |      1.10 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.87 |      348,095,671.92 |    0.2% |      1.09 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           36,534.37 |           27,371.49 |    0.3% |      1.10 | `CheckBlockIndex`\n\nd64d9432a0 test/fuzz: add equivalence coverage for comparison refactors\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.88 |      347,680,941.08 |    0.5% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           37,044.83 |           26,994.32 |    1.1% |      1.08 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.90 |      345,339,421.65 |    0.6% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           37,174.31 |           26,900.30 |    1.4% |      1.09 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.88 |      346,925,394.89 |    0.3% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           37,287.05 |           26,818.96 |    1.6% |      1.09 | `CheckBlockIndex`\n\nc2f69e78ba refactor: optimize `CBlockIndexWorkComparator` with `std::tie`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.00 |      499,008,850.73 |    0.2% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           33,476.29 |           29,871.88 |    1.0% |      1.10 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.03 |      493,360,414.53 |    0.5% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           33,342.34 |           29,991.90 |    0.6% |      1.10 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.01 |      498,514,389.19 |    0.5% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           32,297.54 |           30,962.11 |    0.9% |      1.10 | `CheckBlockIndex`\n\n7cb0c5f1fc refactor: inline `arith_uint256` comparison operator\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.18 |      459,159,880.91 |    0.2% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           32,006.20 |           31,243.95 |    0.7% |      1.10 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.18 |      458,414,231.91 |    0.3% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           31,780.27 |           31,466.07 |    0.5% |      1.10 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                2.19 |      457,429,572.18 |    0.2% |      1.10 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           32,536.14 |           30,735.06 |    1.2% |      1.09 | `CheckBlockIndex`\n\ndf0153a846 refactor: optimize `arith_uint256` comparison with spaceship operator\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                0.68 |    1,473,011,136.06 |    0.5% |      1.06 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           27,528.11 |           36,326.51 |    0.2% |      1.10 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                0.69 |    1,451,170,702.42 |    1.0% |      1.07 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           27,875.27 |           35,874.09 |    0.4% |      1.10 | `CheckBlockIndex`\n\n|              ns/cmp |               cmp/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|                0.68 |    1,477,110,677.23 |    0.2% |      1.06 | `CBlockIndexWorkComparator`\n\n|               ns/op |                op/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|           29,059.25 |           34,412.45 |    0.7% |      1.12 | `CheckBlockIndex`\n```\n\nBesides moving the inlines earlier, [I also added `noexcept` to `operator<=>(const base_uint`](https://github.com/bitcoin/bitcoin/compare/5ab47892ad6328307b42c6065b51a01baf6cb600..703165e6d3b9fbd58b9c31ddce0e961047fc5e71#diff-23dc0fd9eb060143f0899dc7c7df087a79e1eb2a6600fcd4539b4ff31fe22fb9R202) and split the general unit test (which we should have regardless of the upcoming changes, they set the baseline to document current behavior) and the fuzz tests which probe and compare against the old code.\nAdded the best measurements of 3 from above to the non-test commit messages for reference."
  },
  {
   "t": "2026-02-03T11:46:30Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "703165e6d3b9fbd58b9c31ddce0e961047fc5e71"
  },
  {
   "t": "2026-08-21T13:02:21Z",
   "kind": "comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "text": "reACK 703165e6d3b9fbd58b9c31ddce0e961047fc5e71\nNo significant new changes, no remarks.\nP.S.: I'm aware this PR needs a rebase currently."
  },
  {
   "t": "2026-08-21T19:56:28Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "7dc58c2a97c5c494dd9ee93b98df2e2a6b3745f3"
  },
  {
   "t": "2026-08-21T21:37:37Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "9382a8f553262a91dc3a3188b66b4ab912f81a9a"
  },
  {
   "t": "2026-08-21T23:55:42Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "0d1119129fd2f9e7700702766121294b6fdf9d27"
  },
  {
   "t": "2026-08-22T03:54:39Z",
   "kind": "comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "text": "reACK 0d1119129fd2f9e7700702766121294b6fdf9d27\nRebased; no relevant changes, no remarks."
  }
 ],
 "labels_log": [
  {
   "t": "2025-10-16T01:54:35Z",
   "action": "labeled",
   "label": "Refactoring",
   "who": "DrahtBot"
  },
  {
   "t": "2025-10-27T17:00:56Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-10-28T23:47:17Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-11-25T14:49:17Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-11-25T17:05:29Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-01-15T19:13:39Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-01-15T20:41:36Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-02-02T09:56:13Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-02-02T12:22:28Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-21T08:42:40Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-21T21:19:51Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-21T21:53:17Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-22T01:18:03Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2025-10-18T05:56:23Z",
   "kind": "renamed",
   "who": "l0rinc",
   "from": "refactor: optimize block index comparisons (1.4-7.7x faster)",
   "to": "refactor: optimize block index comparisons (1.4-6.8x faster)"
  }
 ],
 "text_chars": 43798,
 "text_tokens_estimate": 10949,
 "changed_paths": [
  "src/arith_uint256.cpp",
  "src/arith_uint256.h",
  "src/bench/CMakeLists.txt",
  "src/bench/blockstorage.cpp",
  "src/node/blockstorage.cpp",
  "src/node/blockstorage.h",
  "src/test/arith_uint256_tests.cpp",
  "src/test/blockchain_tests.cpp",
  "src/test/fuzz/CMakeLists.txt",
  "src/test/fuzz/arith_uint256_comparison_equivalence.cpp",
  "src/test/fuzz/block_index_work_comparator.cpp",
  "src/uint256.h"
 ],
 "files": [
  {
   "path": "src/arith_uint256.cpp",
   "add": 0,
   "del": 12
  },
  {
   "path": "src/arith_uint256.h",
   "add": 9,
   "del": 3
  },
  {
   "path": "src/bench/CMakeLists.txt",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/bench/blockstorage.cpp",
   "add": 53,
   "del": 0
  },
  {
   "path": "src/node/blockstorage.cpp",
   "add": 0,
   "del": 25
  },
  {
   "path": "src/node/blockstorage.h",
   "add": 16,
   "del": 3
  },
  {
   "path": "src/test/arith_uint256_tests.cpp",
   "add": 19,
   "del": 0
  },
  {
   "path": "src/test/blockchain_tests.cpp",
   "add": 29,
   "del": 0
  },
  {
   "path": "src/test/fuzz/CMakeLists.txt",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/test/fuzz/arith_uint256_comparison_equivalence.cpp",
   "add": 56,
   "del": 0
  },
  {
   "path": "src/test/fuzz/block_index_work_comparator.cpp",
   "add": 61,
   "del": 0
  },
  {
   "path": "src/uint256.h",
   "add": 1,
   "del": 1
  }
 ],
 "test_lines": 221,
 "git": {
  "head": "0d1119129fd2f9e7700702766121294b6fdf9d27",
  "head_matches_backup": true,
  "base": "58a7869f860f022e6163dc3fae3106a0599830c5",
  "commits": [
   {
    "sha": "9ede96fcc1",
    "subject": "bench: add benchmark to measure `CBlockIndexWorkComparator` performance",
    "files": 2,
    "add": 51,
    "del": 0
   },
   {
    "sha": "30cad89cb5",
    "subject": "test: add sorting tests for `CBlockIndexWorkComparator` and `arith_uint256`",
    "files": 2,
    "add": 48,
    "del": 0
   },
   {
    "sha": "0521bd53ac",
    "subject": "move-only: inline `CBlockIndex` comparators to header",
    "files": 2,
    "add": 28,
    "del": 28
   },
   {
    "sha": "164ccc5241",
    "subject": "fuzz: add equivalence coverage for comparison refactors",
    "files": 3,
    "add": 119,
    "del": 0
   },
   {
    "sha": "1825dffbb4",
    "subject": "refactor: optimize `CBlockIndexWorkComparator` with `std::tie`",
    "files": 2,
    "add": 11,
    "del": 20
   },
   {
    "sha": "d246d8736e",
    "subject": "refactor: inline `arith_uint256` comparison operator",
    "files": 3,
    "add": 11,
    "del": 16
   },
   {
    "sha": "0d1119129f",
    "subject": "refactor: optimize `arith_uint256` comparison with spaceship operator",
    "files": 1,
    "add": 3,
    "del": 4
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "93986b513104d2ea",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}