{
 "number": 35591,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35591",
 "title": "[DO NOT MERGE] Erlay: bandwidth-efficient transaction relay protocol (Full implementation)",
 "author": "sr-gi",
 "author_association": "MEMBER",
 "created_at": "2026-06-23T12:40:28Z",
 "updated_at": "2026-09-14T15:51:34Z",
 "age_days": 86,
 "draft": false,
 "labels": [
  "Needs rebase"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "37912ec1789ab2384982a3a045f9e864fdccf722",
 "head_ref": "2026-05-erlay-recon-only-full-impl",
 "head_repo": "sr-gi/bitcoin",
 "head_history": [
  {
   "t": "2026-06-23T13:03:39Z",
   "sha": "86d9df28e84ab04e44a17ecb356ad27367510ab6"
  },
  {
   "t": "2026-06-23T18:05:39Z",
   "sha": "58218666dfcaf41e65b2b1b87f0f51c7cc9fb112"
  },
  {
   "t": "2026-06-23T20:11:08Z",
   "sha": "65547074596b5d5be0e84bf749651a3673361c3b"
  },
  {
   "t": "2026-06-23T23:03:44Z",
   "sha": "e63db1a848feaa97626d44276507330f4594f4fd"
  },
  {
   "t": "2026-06-24T12:49:57Z",
   "sha": "23053a379fd72ef49a240e9014bed454719f8ba1"
  },
  {
   "t": "2026-06-24T14:40:18Z",
   "sha": "35bcd043b468ccb05ec3cbb5a384724cf0e47e23"
  },
  {
   "t": "2026-06-24T16:05:12Z",
   "sha": "280d603597076be8b4d1b47db737f6b293cecb7c"
  },
  {
   "t": "2026-06-24T18:51:18Z",
   "sha": "d08f127a7764e37c30ed815b0a6c4f1d37282173"
  },
  {
   "t": "2026-08-13T17:40:22Z",
   "sha": "41de5f931189563158f0b953638bcb626e65dd7d"
  },
  {
   "t": "2026-08-17T12:13:02Z",
   "sha": "948ebe3bd40b56703db20097f89665856a396661"
  },
  {
   "t": "2026-08-17T13:00:13Z",
   "sha": "816d2cd4328a060577aa7cb0e854a117faa7ca74"
  },
  {
   "t": "2026-08-17T17:01:23Z",
   "sha": "d34d7362ee554b044e3d3acb237e2be477b260c1"
  },
  {
   "t": "2026-08-18T17:47:38Z",
   "sha": "373a0ef4a8cb8143174b934ecf28668178b877b7"
  },
  {
   "t": "2026-08-18T17:48:26Z",
   "sha": "7937670255acd8c787ecaded629b621518f6306e"
  },
  {
   "t": "2026-08-19T15:27:46Z",
   "sha": "b0186aacfe054b9e4a0d1b6a2db74c59af308ffe"
  },
  {
   "t": "2026-08-19T19:23:05Z",
   "sha": "62bf7d11115d4b86cb3a8fb0de035f87e79c7ace"
  },
  {
   "t": "2026-08-19T21:16:30Z",
   "sha": "e366778976f36998a120ea3bdf397e9c456692c7"
  },
  {
   "t": "2026-08-24T11:28:40Z",
   "sha": "534a89069d594a05e6bfb15858046464b05fbc9e"
  },
  {
   "t": "2026-09-01T10:37:14Z",
   "sha": "25e545c9448a70e0080d97aac583c2869b6c5723"
  },
  {
   "t": "2026-09-01T13:52:58Z",
   "sha": "0eddbbca81d0ceceb6375ba34e2113575057e579"
  },
  {
   "t": "2026-09-04T19:05:12Z",
   "sha": "094a75a64ae6e23149e639d691092966a4ed2540"
  },
  {
   "t": "2026-09-04T19:27:19Z",
   "sha": "37912ec1789ab2384982a3a045f9e864fdccf722"
  }
 ],
 "additions": 4426,
 "deletions": 402,
 "changed_files": 30,
 "commit_count": 38,
 "size_bucket": "XL",
 "mergeable_state": "dirty",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {},
   "conflicts": [
    {
     "number": 36167,
     "title": "[RFC] Enable `-Wunused`",
     "author": "fanquake"
    },
    {
     "number": 35561,
     "title": "net: move some CNodeState fields to Peer",
     "author": "Crypt-iQ"
    },
    {
     "number": 35522,
     "title": "refactor: Extract per-message helpers from SendMessages() (move-only)",
     "author": "pablomartin4btc"
    },
    {
     "number": 34743,
     "title": "p2p: don't disconnect manual peers for block stalling",
     "author": "willcl-ark"
    },
    {
     "number": 28690,
     "title": "build: Introduce internal kernel library",
     "author": "sedited"
    },
    {
     "number": 27052,
     "title": "test: rpc: add last block announcement time to getpeerinfo result",
     "author": "LarryRuane"
    }
   ]
  }
 },
 "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": [
   "brunoerg"
  ]
 },
 "signals": {
  "needs_rebase": true,
  "ci_failed": false,
  "mergeable_state": "dirty",
  "last_author_activity": "2026-09-04T19:42:14Z",
  "last_reviewer_activity": "2026-08-31T18:12:20Z",
  "last_reviewer": "brunoerg",
  "author_silent_days": 12,
  "waiting_on_author_days": 0,
  "days_since_update": 3
 },
 "refs": {
  "mentioned": [
   30249,
   34542,
   36078
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 30249,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "Erlay Project Tracking"
   },
   {
    "number": 34542,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "RFC: Erlay Conceptual Discussion"
   },
   {
    "number": 36078,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-08-25",
    "title": "qa: Reduce `-maxconnections` in the functional test framework"
   }
  ],
  "conflicts": [
   36167,
   35561,
   35522,
   34743,
   28690,
   27052
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/init.cpp",
  "src/net_processing.cpp",
  "src/node/txreconciliation_impl.cpp"
 ],
 "body": "Erlay Project Tracking:\u00a0[#30249](https://github.com/bitcoin/bitcoin/issues/30249)\nConceptual Discussion: [#34542](https://github.com/bitcoin/bitcoin/issues/34542)\n\n---\n\nThis is a full implementation of Erlay. Its purpose is to check the integrity and correctness of the implementation against changes/additions that may originate from the review process and/or rebases on top of newer functionality.\n\nThis is not to be merged. Functionality will be spread across multiple smaller PRs to ease the review process.\n\n---\n## Approach\n\nThis approach uses Erlay as a fallback mechanism for transaction propagation. Instead of mixing fanout and reconciliation into a single connection type, the current approach leaves the existing connections as they are, and adds additional low-bandwidth connections to be used in case the node is being eclipsed. This connections should have minimal cost under normal circumstances, and only undergo real traffic in case other 8 full-outbound connections are being captured.\n\n## outbound-full-reconciliation connections\n\nFor now, we are adding 4 additional reconciliation-only connections to the node while we test it's impact on real node running the approach. Further analysis may be needed to pick a meaningful value for this. The number of inbound connections should also be scaled based on how many connections we are adding.",
 "commits": [
  {
   "sha": "312095c26b78f5b131f24c2436e82d633501738b",
   "date": "2026-09-01T13:52:46Z",
   "message": "refactor: redesigns txreconciliation file split and namespace\n\nSplits the txreconciliation logic in three files instead of two, allowing the\nTxreconciliationState to be properly tested, instead of being internal to\ntxreconciliation.cpp.\n\nAlso includes everything in the node namespace, instead of being part\nof an anonymous one."
  },
  {
   "sha": "9deab543e06c6d95101f15ddf8e991ebeeb7be44",
   "date": "2026-09-01T13:52:46Z",
   "message": "refactor: remove legacy comments\n\nThese comments became irrelevant in one of the previous code changes.\nThey simply don't make sense anymore."
  },
  {
   "sha": "0d3d5c9b24f58c2b2966c0c519f02cb2eea33554",
   "date": "2026-09-01T13:52:47Z",
   "message": "refactor: Defines generic error to be used in several reconciliation methods"
  },
  {
   "sha": "8e9fec2a2710bc1adb6daeb5224c8738ed081559",
   "date": "2026-09-01T13:52:47Z",
   "message": "refactor: add full stop in existing txreconciliation LogDebug lines"
  },
  {
   "sha": "e703cdf680c766ad583435aede6c81596e9d4a4c",
   "date": "2026-09-01T13:52:47Z",
   "message": "p2p: Allows inbound reconciliation connections up to a limit\n\nSet the current limit to 32."
  },
  {
   "sha": "3792744ae74c3e6e0972df019ccba13c149111c2",
   "date": "2026-09-04T18:13:00Z",
   "message": "net, gui, test: adds new connection type (OUTBOUND_FULL_RECONCILIATION)\n\nAdds a new connection type that will be used for reconciliation only.\n\nDefines the default max number of this type of connections to 4."
  },
  {
   "sha": "4d2cb97a860fdfb9393789c44209dbb2de15a6eb",
   "date": "2026-09-04T18:13:08Z",
   "message": "p2p: Count reconciliation connections as full outbound connections\n\nReconciliation connections relay everything a full-relay connection does\n(tx, block, addr). They only differ in how transactions are exchanged. Treat\nthem as full outbound connections. This includes:\n\n- seeding: they count towards SEED_OUTBOUND_CONNECTION_THRESHOLD, so we stop\n  querying seeds once we have enough peers, no matter their type.\n- network diversity: they count towards m_network_conn_counts, so a network\n  covered by a reconciliation peer is not picked as a preferred network, and\n  a reconciliation peer that is our only connection to a network is protected\n  from eviction.\n- chain sync: they can be protected from the bad/lagging chain logic, which\n  they are already subject to via IsOutboundOrBlockRelayConn.\n\nReconciliation peers get their own, smaller protection budget so that they\ncannot use up the protection our full-relay peers rely on."
  },
  {
   "sha": "ab8528650be36714554934946679d69247dbb719",
   "date": "2026-09-04T18:18:27Z",
   "message": "refactor: Extract EvictWorstOutboundPeer out of EvictExtraOutboundPeers\n\nMake the eviction logic into a method based on the connection type so we\ncan reuse it for OUTBOUND_FULL_RECON too."
  },
  {
   "sha": "0ce6c11e2a1c2f583a5e0b4eaed5f019c62c0dba",
   "date": "2026-09-04T19:10:27Z",
   "message": "p2p: Evict extra reconciliation peers\n\nEvict extra reconciliation peers using the same logic as we do for\nfull relay peers."
  },
  {
   "sha": "07823648d96a212d9558bb08d84f1342b32c2558",
   "date": "2026-09-04T19:22:21Z",
   "message": "p2p: send SENDTXRCNCL messages only over OUTBOUND_FULL_RECONCILIATION connection"
  },
  {
   "sha": "1a42ba6945ae530fcaad62e657be5d8d08ff965b",
   "date": "2026-09-04T19:22:22Z",
   "message": "p2p: Disconnect outbound reconciliation peers that do not negotiate\n\nReconciliation slots are reserved to peers that negotiate reconciliation.\n\nWe treat this similarly to a block-relay-only peer that sends us transactions."
  },
  {
   "sha": "c4d9ef36fcd122e45116ca6c6701ac2e997be3af",
   "date": "2026-09-04T19:22:22Z",
   "message": "p2p: Functions to add/remove wtxids to tx reconciliation sets\n\nThey will be used later on.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "9d60dee5ed2329f4e36fd461784771235431e79a",
   "date": "2026-09-04T19:22:22Z",
   "message": "p2p: Add transactions to reconciliation sets\n\nTransactions are added to the reconciliation sets of reconciling peers, and processed normally for fanout peers."
  },
  {
   "sha": "2ac2615781b7577df95f0c2c1af81b925714b615",
   "date": "2026-09-04T19:22:22Z",
   "message": "p2p: Add helper to compute reconciliation tx short ids and a cache of short ids to wtxids"
  },
  {
   "sha": "07659f3221d7d71775c3b4abcce50747424ea022",
   "date": "2026-09-04T19:22:22Z",
   "message": "p2p: Deal with shortid collisions for reconciliation sets\n\nIf a transaction to be added to a peer's recon set has a shot id collisions (a previously\nadded wtxid maps to the same short id), both transaction should be fanout, given\nour peer may have added the opposite transaction to our recon set, and these two\ntransaction won't be reconciled."
  },
  {
   "sha": "1e89a027aeb6e3ff06bec664077f0377e86b2b43",
   "date": "2026-09-04T19:22:22Z",
   "message": "p2p: Add peers to reconciliation queue on negotiation\n\nWhen we're finalizing negotiation, we should add the peers\nfor which we will initiate reconciliations to the queue.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "296266789219a9d7fadf92208f05c3fe7a4a5d26",
   "date": "2026-09-04T19:22:22Z",
   "message": "p2p: Track reconciliation requests schedule\n\nWe initiate reconciliation by looking at the queue periodically\nwith equal intervals between peers to achieve efficiency.\n\nThis will be later used to see whether it's time to initiate.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "6f0ffb61aefe039f2992c91c72f98940b4a09601",
   "date": "2026-09-04T19:22:23Z",
   "message": "p2p: Initiate reconciliation round\n\nWhen the time comes for the peer, we send a\nreconciliation request with the parameters which\nwill help the peer to construct a (hopefully) sufficient\nreconciliation sketch for us. We will then use that\nsketch to find missing transactions.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "bbfa86d2b6d98265393ec5add710cbeb7e2731fa",
   "date": "2026-09-04T19:22:23Z",
   "message": "test: Functional test for reqtxrcncl\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "9409b1807c35e9f6cadd5f8986e2d43158cbec12",
   "date": "2026-09-04T19:22:23Z",
   "message": "p2p: Handle reconciliation request\n\nStore the parameters the peer sent us inside th reconciliation request.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "c1b900ef62dbd7804004c59305f1160315171a2a",
   "date": "2026-09-04T19:22:23Z",
   "message": "p2p: Add helper to compute sketches for tx reconciliation\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "7e4c2b5edd94ccd04c23f6eb5a7b8451c7e4eba5",
   "date": "2026-09-04T19:22:23Z",
   "message": "p2p: Respond to a reconciliation request\n\nWhen the time comes, we should send a sketch of our\nlocal reconciliation set to the reconciliation initiator.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "ff227373d065aaeecf746a6fbea5670d75e7c9de",
   "date": "2026-09-04T19:22:23Z",
   "message": "p2p: Add a function to identify local/remote missing txs\n\nWhen the sketches from both sides are combined successfully,\nthe diff is produced. Then this diff can (together with the local txs)\nbe used to identified which transactions are missing locally and remotely.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "07d6c6d1fce5266b815763d69e778e0fda8c3e55",
   "date": "2026-09-04T19:22:24Z",
   "message": "refactor: Extract AnnounceTxs out of SendMessages\n\nMove the transaction announcement loop from SendMessages into its own\nmethod, so it can be reused to announce transactions after a\nreconciliation round. No behaviour change."
  },
  {
   "sha": "db3d3e10eceac1456057f1c412543098410714ad",
   "date": "2026-09-04T19:22:24Z",
   "message": "p2p: Add a function to announce transactions after reconciliation\n\nTransactions the peer is found to be missing during a reconciliation round\nneed to be announced right away, rather than waiting for the next trickle\ninterval and being added back to the reconciliation set.\n\nAdd AnnounceReconciliationTxs on top of AnnounceTxs.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "5a73d050f18333d95cc369046c742076e04439e1",
   "date": "2026-09-04T19:22:24Z",
   "message": "p2p: Handle reconciliation sketch and successful decoding\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "fad7f9c2618d5f6d73d2c99bddf8d3c0087e3fd9",
   "date": "2026-09-04T19:22:24Z",
   "message": "p2p: Request extension if decoding failed\n\nIf after decoding a reconciliation sketch it turned out\nto be insufficient to find set difference, request extension.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "6bc290a609f3b80e92b12be4e58631c88479dacc",
   "date": "2026-09-04T19:22:24Z",
   "message": "p2p: Be ready to receive sketch extension\n\nStore the initial sketches so that we are able to process\nextension sketch while avoiding transmitting the same data.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "b9ef0cce59e76cd33f3ad950609f68b803330643",
   "date": "2026-09-04T19:22:24Z",
   "message": "p2p: Prepare for sketch extension request\n\nTo be ready to respond to a sketch extension request\nfrom our peer, we should store a snapshot of our state\nand capacity of the initial sketch, so that we compute\nextension of the same size and over the exact same\ntransactions.\n\nTransactions arriving during this reconciliation will\nbe instead stored in the regular set.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "9f7f1d102b852751547ecb6a9a365911dfcaeb1d",
   "date": "2026-09-04T19:22:24Z",
   "message": "p2p: Keep track of announcements during txrcncl extension\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "fd95370940e36421b9136bbe91a6258be21df454",
   "date": "2026-09-04T19:22:25Z",
   "message": "p2p: Handle reconciliation extension request\n\nIf peer failed to reconcile based on our initial response sketch,\nthey will ask us for a sketch extension. Store this request to respond later.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "50dc0109a7af8d3049790fb2f4470882cb4d9ea5",
   "date": "2026-09-04T19:22:25Z",
   "message": "p2p: Respond to sketch extension request\n\nSending an extension may allow the peer to reconcile\ntransactions, because now the full sketch has twice\nas much capacity.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "ddfd680a0ee8106986a5d28660c4a64e95afa036",
   "date": "2026-09-04T19:22:25Z",
   "message": "p2p: Handle sketch extension\n\nIf a peer sent us an extension sketch, we should\nreconstruct a full sketch from it with the snapshot\nwe stored initially, and attempt to decode the difference.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "880bdd7430484f11cfbbe2f2d83d6372d2a141af",
   "date": "2026-09-04T19:22:25Z",
   "message": "p2p: Add a finalize incoming reconciliation function\n\nThis currently unused function is supposed to be used once\na reconciliation round is done. It cleans the state corresponding\nto the passed reconciliation.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "cf883f512b62a5e159afd56819497570d0be42b4",
   "date": "2026-09-04T19:22:25Z",
   "message": "p2p: Handle reconciliation finalization message\n\nOnce a peer tells us reconciliation is done, we should behave as follows:\n- if it was successful, just respond them with the transactions they asked\n  by short ID.\n- if it was a full failure, respond with all local transactions from the reconciliation\n  set snapshot\n- if it was a partial failure (only low or high part was failed after a bisection),\n  respond with all transactions which were asked for by short id,\n  and announce local txs which belong to the failed chunk.\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "3554b3db6295e547f97902377934bcb75b3584c1",
   "date": "2026-09-04T19:22:25Z",
   "message": "p2p, test: Add tx reconciliation functional tests\n\nWe may still need to add more tests, specially around extensions (if we keep them)\n\nCo-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>"
  },
  {
   "sha": "075285161721eed2f57371bdd7fc853fe10cc6a5",
   "date": "2026-09-04T19:22:25Z",
   "message": "p2p: Remove transactions from reconciliation sets when removed from the mempool\n\nA transaction that has left our mempool can no longer be served, but nothing\nremoved it from the reconciliation sets it had been added to. It would still be\nsketched, requested by the peer, and then dropped, wasting sketch capacity and a\nround trip after every block.\n\nPrune on both removal signals: removeUnchecked deliberately skips\nTransactionRemovedFromMempool for MemPoolRemovalReason::BLOCK, so mined\ntransactions, which are the bulk of the case, only arrive via\nMempoolTransactionsRemovedForBlock.\n\nSnapshots of an in-flight round are left untouched so that a sketch extension\nstill describes the same elements as the sketch already sent. Flagging the wtxid\ninstead keeps it out of the announcement."
  },
  {
   "sha": "37912ec1789ab2384982a3a045f9e864fdccf722",
   "date": "2026-09-04T19:22:26Z",
   "message": "bench: Adds txreconciliation benches\n\nRaises the question of whether the current sketch capacity limits are too high"
  }
 ],
 "timeline": [
  {
   "t": "2026-06-23T13:03:39Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "86d9df28e84ab04e44a17ecb356ad27367510ab6"
  },
  {
   "t": "2026-06-23T13:13:54Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "Rebased on master.\n\nOpening this so it can be tested against CI and to make sure nothing obvious is missing. Next step will be testing with real nodes (most likely in Warnet).\n\nThings to consider/add:\n\n- This is currently using [sendtxrcncl](https://github.com/bitcoin/bips/blob/master/bip-0330.mediawiki#sendtxr) as a way, for outbound nodes, to signal they want to establish a full-reconciliation connection, plus adding a limit on the number of full-reconcilition inbounds that will be accepted by a node. This is not the originally intended way of using `sendtxrcncl`. It may be worth considering an approach based on [BIP-434](https://github.com/bitcoin/bitcoin/pull/35221).\n- The extension phase was designed so peers with an ongoing reconciliation that had underpredicted the sketch capacity could still reconcile without having to directly fallback to fanout. Given reconciliation is now used as fallback, and the extra bandwidth may not be as problematic, it may be worth considering overshooting the initial sketch capacity and getting rid of the extension phase.\n- Fuzz tests are missing"
  },
  {
   "t": "2026-06-23T18:05:39Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "58218666dfcaf41e65b2b1b87f0f51c7cc9fb112"
  },
  {
   "t": "2026-06-23T20:11:08Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "65547074596b5d5be0e84bf749651a3673361c3b"
  },
  {
   "t": "2026-06-23T23:03:44Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "e63db1a848feaa97626d44276507330f4594f4fd"
  },
  {
   "t": "2026-06-23T23:04:51Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "Fixed some typos and addressed some of the linter suggestions\n\n[6554707](https://github.com/bitcoin/bitcoin/pull/35591/commits/65547074596b5d5be0e84bf749651a3673361c3b)...[e63db1a](https://github.com/bitcoin/bitcoin/pull/35591/commits/e63db1a848feaa97626d44276507330f4594f4fd)"
  },
  {
   "t": "2026-06-24T12:49:57Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "23053a379fd72ef49a240e9014bed454719f8ba1"
  },
  {
   "t": "2026-06-24T14:40:18Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "35bcd043b468ccb05ec3cbb5a384724cf0e47e23"
  },
  {
   "t": "2026-06-24T14:41:45Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "Fixed several bugs and added a new test for receiving reconciliation messages when reconciliation is not enabled.\n\n[e63db1a](https://github.com/bitcoin/bitcoin/commit/e63db1a848feaa97626d44276507330f4594f4fd)...[35bcd04](https://github.com/bitcoin/bitcoin/commit/35bcd043b468ccb05ec3cbb5a384724cf0e47e23)"
  },
  {
   "t": "2026-06-24T16:05:12Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "280d603597076be8b4d1b47db737f6b293cecb7c"
  },
  {
   "t": "2026-06-24T18:51:18Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "d08f127a7764e37c30ed815b0a6c4f1d37282173"
  },
  {
   "t": "2026-06-24T20:57:46Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "Addressed some issues pointed out by corecheck.\n\n[35bcd04](https://github.com/bitcoin/bitcoin/commit/35bcd043b468ccb05ec3cbb5a384724cf0e47e23)...[d08f127](https://github.com/bitcoin/bitcoin/commit/d08f127a7764e37c30ed815b0a6c4f1d37282173)"
  },
  {
   "t": "2026-06-29T16:23:07Z",
   "kind": "review",
   "who": "brunoerg",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "d08f127a7764e37c30ed815b0a6c4f1d37282173",
   "text": "**Testing report (LLM/experimental) based on the results of an incremental mutation testing run for this PR - full result is avaliable at: https://bitcoincore.space**\n\n-------------\n\nThe overall result is mixed. The PR already has useful coverage for the happy-path reconciliation flow, basic protocol violations, and some queue/timer behavior. However, the survivors show that the tests still leave several important behaviors only weakly specified, especially where reconciliation falls back, extends, or interacts with INV relay bookkeeping.\n\n## What the current tests do well\n\nThe existing tests cover the basic handshake and some normal flows reasonably well:\n\n- unit coverage for peer registration, queue rotation, set insertion/removal, and non-extension reconciliation in [src/test/txreconciliation_tests.cpp](/home/bruno/projects/bitcoin/src/test/txreconciliation_tests.cpp:18)\n- functional coverage for initiator/responder happy paths in [test/functional/p2p_txrecon_initiator.py](/home/bruno/projects/bitcoin/test/functional/p2p_txrecon_initiator.py:62) and [test/functional/p2p_txrecon_responder.py](/home/bruno/projects/bitcoin/test/functional/p2p_txrecon_responder.py:70)\n- protocol-violation checks for clearly invalid message ordering and unsupported peers\n\nThat baseline is good enough to kill most straightforward mutations. The survivors are mostly about what happens around the edges of the protocol, not the central flow.\n\n## Main gaps exposed by the surviving mutants\n\n### 1. Extension handling is under-tested\n\nThis is the clearest gap. Several survivors change extension behavior without being detected:\n\n- not sending `REQSKETCHEXT` after an undecodable sketch in `net_processing`\n- not snapshotting state before the extension round\n- accepting/rejecting malformed extension sizes incorrectly\n- flipping success/failure outcomes of extension decoding\n- using the wrong transaction set after extension failure\n- not clearing peer state after extension completion\n\nThis lines up with the current functional tests: both initiator and responder tests explicitly stop short of extension coverage and even leave TODOs for it in [test/functional/p2p_txrecon_initiator.py](/home/bruno/projects/bitcoin/test/functional/p2p_txrecon_initiator.py:248) and [test/functional/p2p_txrecon_responder.py](/home/bruno/projects/bitcoin/test/functional/p2p_txrecon_responder.py:268).\n\nWhat should be improved:\n\n- add end-to-end functional tests that force an extension round and assert the exact message sequence: `REQTXRCNCL -> SKETCH -> REQSKETCHEXT -> SKETCH -> RECONCILDIFF`\n- assert both extension success and extension failure behavior\n- verify that extension failure falls back to announcing the snapshotted set, not the live set\n- verify that state is cleared after extension completion and that a second reconciliation starts cleanly\n\n### 2. Boundary conditions are not pinned down tightly enough\n\nSeveral survivors change strict inequalities to inclusive ones and still pass:\n\n- `remote_sketch_capacity > MAX_SKETCH_CAPACITY` changed to `>=`\n- `extended_capacity > MAX_SKETCH_CAPACITY * 2` changed to `>=`\n- `peer_q > Q_PRECISION` changed to `>=`\n\nThis means the tests exercise invalid-above-limit cases, but not the exact boundary values that should remain valid. There is already a good example of this style for rounded `q` formatting in [src/test/txreconciliation_tests.cpp](/home/bruno/projects/bitcoin/src/test/txreconciliation_tests.cpp:381), but the same precision is missing for protocol acceptance thresholds.\n\nWhat should be improved:\n\n- add exact-boundary tests for `MAX_SKETCH_CAPACITY`, `2 * MAX_SKETCH_CAPACITY`, and `Q_PRECISION`\n- check both sides of each threshold: `limit` must pass, `limit + 1` must fail\n\n### 3. INV relay side effects are only partially asserted\n\nMany survivors in `PeerManagerImpl::AnnounceTxs()` and the send path in `SendMessages()` remove or alter important side effects without breaking tests:\n\n- skipping heap construction/pop order\n- changing `continue` to `break` when one candidate should not be sent\n- not inserting into `m_tx_inventory_known_filter`\n- not erasing from `m_tx_inventory_to_send`\n- not flushing INV batches at `MAX_INV_SZ`\n- not clearing the batch after sending\n\nThe current tests mostly check that transactions eventually arrive. They do not strongly check how they are batched, filtered, or suppressed from future re-announcement. That leaves a lot of bookkeeping mutations alive.\n\nWhat should be improved:\n\n- add tests with a mix of sendable and unsendable transactions and assert that later eligible transactions are still announced\n- assert that transactions already known to the peer are not re-announced in the next round\n- add a case above `MAX_INV_SZ` and verify the number and sizes of INV messages\n- verify that reconciliation and fanout paths do not duplicate announcements after internal state should have been cleared\n\n### 4. Some state-management behaviors are observable in principle, but not asserted\n\nSurvivors also show weak checking around reconciliation state transitions:\n\n- not clearing `m_short_id_mapping`\n- not clearing peer state after handling a result\n- always taking the \u201cremoved\u201d branch in `TryRemovingFromSet`\n- not recording `m_announced_while_reconciling`\n- returning success from queue-selection paths that should be false\n\nThese are not all equally severe, but together they indicate that the tests often validate the final external effect of a single round without checking the follow-up round that would expose stale state.\n\nWhat should be improved:\n\n- add two-step tests that perform one reconciliation round and then immediately start another to detect stale snapshots, stale mappings, or stale queue state\n- specifically verify the \u201creceived while reconciling\u201d behavior across the extension path, not just the non-extension path\n\n## Bottom line\n\nThe current tests are good at proving that the basic txreconciliation flow works. They are not yet strong enough to fully specify the extension path, the exact protocol boundaries, or the internal bookkeeping that prevents duplicate, truncated, or stale announcements.\n\nIf I had to prioritize follow-up work, I would do it in this order:\n\n1. Add full initiator/responder extension-path functional tests.\n2. Add exact boundary tests for sketch capacity and `q`.\n3. Add stronger assertions around INV batching, filtering, and duplicate suppression.\n4. Add second-round/state-cleanup tests to catch stale reconciliation state.\n\nThat would likely eliminate most of the meaningful survivors from this run and materially improve confidence in the PR\u2019s tests."
  },
  {
   "t": "2026-08-13T17:40:22Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "41de5f931189563158f0b953638bcb626e65dd7d"
  },
  {
   "t": "2026-08-13T20:05:02Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "Rebased to include the latest changes in master, including the changes introduced in [https://github.com/bitcoin/bitcoin/pull/34628](https://github.com/bitcoin/bitcoin/pull/34628).\n\nReworked the transaction announcement logic so most of it can be re-used by the trickle code path and the new post-reconciliation code path.\n\nAlso started to killing @brunoerg reported mutants.\n\n[d08f127](https://github.com/bitcoin/bitcoin/commit/d08f127a7764e37c30ed815b0a6c4f1d37282173)...[41de5f9](https://github.com/bitcoin/bitcoin/pull/35591/commits/41de5f931189563158f0b953638bcb626e65dd7d)"
  },
  {
   "t": "2026-08-17T12:13:02Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "948ebe3bd40b56703db20097f89665856a396661"
  },
  {
   "t": "2026-08-17T13:00:13Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "816d2cd4328a060577aa7cb0e854a117faa7ca74"
  },
  {
   "t": "2026-08-17T16:29:59Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "Finished covering the most relevant mutants. Left out the ones regarding extensions, as I'm still debating whether those will be part of the PR.\n\n[41de5f9](https://github.com/bitcoin/bitcoin/pull/35591/commits/41de5f931189563158f0b953638bcb626e65dd7d)...[816d2cd](https://github.com/bitcoin/bitcoin/pull/35591/commits/816d2cd4328a060577aa7cb0e854a117faa7ca74)"
  },
  {
   "t": "2026-08-17T17:01:23Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "d34d7362ee554b044e3d3acb237e2be477b260c1"
  },
  {
   "t": "2026-08-17T17:04:30Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "Rebased master to cover https://github.com/bitcoin/bitcoin/pull/35852, and applied the inline const(expr) convention introduced by the PR to cover new definitions.\n\n[816d2cd](https://github.com/bitcoin/bitcoin/pull/35591/commits/816d2cd4328a060577aa7cb0e854a117faa7ca74)...[d34d736](https://github.com/bitcoin/bitcoin/pull/35591/commits/d34d7362ee554b044e3d3acb237e2be477b260c1)"
  },
  {
   "t": "2026-08-18T17:47:38Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "373a0ef4a8cb8143174b934ecf28668178b877b7"
  },
  {
   "t": "2026-08-18T17:48:26Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "7937670255acd8c787ecaded629b621518f6306e"
  },
  {
   "t": "2026-08-19T15:27:46Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "b0186aacfe054b9e4a0d1b6a2db74c59af308ffe"
  },
  {
   "t": "2026-08-19T15:36:29Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "Fixed several uncovered edge cases.\n\n[d34d736](https://github.com/bitcoin/bitcoin/pull/35591/commits/d34d7362ee554b044e3d3acb237e2be477b260c1)...[b0186aa](https://github.com/bitcoin/bitcoin/pull/35591/commits/b0186aacfe054b9e4a0d1b6a2db74c59af308ffe)"
  },
  {
   "t": "2026-08-19T19:23:05Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "62bf7d11115d4b86cb3a8fb0de035f87e79c7ace"
  },
  {
   "t": "2026-08-19T19:23:59Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "Added benches for how long it takes to build and decode sketches based on their capacity. This may affect the max sketch capacity that we may accept to work with.\n\n|          ns/element |           element/s |    err% |     total | benchmark\n|--------------------:|--------------------:|--------:|----------:|:----------\n|            9,992.50 |          100,075.03 |    0.6% |      0.33 | `ReconcileSketchConstructReconSetMax`\n|          536,306.23 |            1,864.61 |    0.1% |     96.69 | `ReconcileSketchDecodeExtensionMax`\n|          281,615.18 |            3,550.94 |    0.1% |     25.38 | `ReconcileSketchDecodeMaxCapacity`\n|           39,963.18 |           25,023.03 |    1.1% |      1.30 | `ReconcileSketchDecodeReconSetMax`\n|            2,379.92 |          420,182.37 |    3.5% |      0.01 | `ReconcileSketchDecodeTypical`\n\nThis results in the following:\n\nbenchmark | capacity | per-decode\n-- | -- | --\nReconcileSketchDecodeTypical | 54 | 0.13 ms\nReconcileSketchDecodeReconSetMax | 3001 | 120 ms\nReconcileSketchDecodeMaxCapacity | 8192 | 2.3 s\nReconcileSketchDecodeExtensionMax | 16384 | 8.8 s\n\n- The decode for a typical/realistic round (7 tx/s, 30s, q=0.25) is in the order of tens of microseconds.\n- A round between two Core nodes (limiting their set size to `MAX_RECONSET_SIZE`) takes ~120ms\n- A peer that advertises sketches as big as they get (MAX_SKETCH_CAPACITY) can make us take ~2.3s to decode\n   - This is amplified to 8.8s in the extension case, as we allow up to double the max capacity\n\nThis applies only to outbound peers, as those are the ones that makes us decode. This bears the question, should we limit the maximum sketch size that we accept far bellow `MAX_SKETCH_CAPACITY`?\nIn the case of Core nodes, sets cannot have more than `MAX_RECONSET_SIZE` elements. So the maximum sketch sizes are 3001 for the initial sketch, 6002 for an extension.\n\n[b0186aa](https://github.com/bitcoin/bitcoin/pull/35591/commits/b0186aacfe054b9e4a0d1b6a2db74c59af308ffe)...[62bf7d1](https://github.com/bitcoin/bitcoin/pull/35591/commits/62bf7d11115d4b86cb3a8fb0de035f87e79c7ace)"
  },
  {
   "t": "2026-08-19T21:16:30Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "e366778976f36998a120ea3bdf397e9c456692c7"
  },
  {
   "t": "2026-08-20T10:22:54Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "This should be ready to review at this point, even though some details still need deciding. Happy to split the PR into smaller chunks if it makes it easier.\n\nOpen questions (that may arise from reviewing parts of the code):\n\n- Should we negotiate reconciliation using BIP-434?\n- Should the new connection type be considered a full-outbound? If so, the eviction logic needs to be patched to include these.\n- Are extensions worth if we will be using reconciliation as a fallback, or should we just slightly overestimate the sketch capacity and default to fanout on failure?\n- Should we cap the maximum capacity sketch we accept closer to `MAX_RECONSET_SIZE` than to `MAX_SKETCH_CAPACITY`?"
  },
  {
   "t": "2026-08-24T11:28:40Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "534a89069d594a05e6bfb15858046464b05fbc9e"
  },
  {
   "t": "2026-08-24T12:34:56Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "Rebased  [e366778](https://github.com/bitcoin/bitcoin/pull/35591/commits/e366778976f36998a120ea3bdf397e9c456692c7)...[534a890](https://github.com/bitcoin/bitcoin/pull/35591/commits/534a89069d594a05e6bfb15858046464b05fbc9e)"
  },
  {
   "t": "2026-08-31T17:58:39Z",
   "kind": "review_comment",
   "who": "brunoerg",
   "assoc": "MEMBER",
   "path": "src/init.cpp",
   "commit": "37912ec1789ab2384982a3a045f9e864fdccf722",
   "in_reply_to": null,
   "text": "Could reconcilitation peers exceed `m_max_outbound_full_recon` during v2-to-v1 fallback? Thinking about a possible race."
  },
  {
   "t": "2026-08-31T18:07:54Z",
   "kind": "review_comment",
   "who": "brunoerg",
   "assoc": "MEMBER",
   "path": "src/node/txreconciliation_impl.cpp",
   "commit": "37912ec1789ab2384982a3a045f9e864fdccf722",
   "in_reply_to": null,
   "text": "I got 31.2 seconds on my machine (Ryzen 9 7900). Wondering if a malicious peer could use it to cause a DoS since it would block all msgs processings?"
  },
  {
   "t": "2026-08-31T18:12:20Z",
   "kind": "review_comment",
   "who": "brunoerg",
   "assoc": "MEMBER",
   "path": "src/net_processing.cpp",
   "commit": "534a89069d594a05e6bfb15858046464b05fbc9e",
   "in_reply_to": null,
   "text": "nit: I think that, according to the BIP330, we must accept 0 or 1 here. This way it would treat any nonzero byte as true."
  },
  {
   "t": "2026-09-01T09:11:05Z",
   "kind": "review_comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "path": "src/node/txreconciliation_impl.cpp",
   "commit": "37912ec1789ab2384982a3a045f9e864fdccf722",
   "in_reply_to": 3897073818,
   "text": "Yes, I think it can. I left a comment on this earlier on the PR.\n\nGiven this is quadratic, I think limiting the size of the sketch (and potentially getting rid of extensions) will make it less of an issue.\n\nhttps://github.com/bitcoin/bitcoin/pull/35591#issuecomment-5354604209"
  },
  {
   "t": "2026-09-01T09:20:57Z",
   "kind": "review_comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "path": "src/net_processing.cpp",
   "commit": "534a89069d594a05e6bfb15858046464b05fbc9e",
   "in_reply_to": 3897104353,
   "text": "You're right, will change"
  },
  {
   "t": "2026-09-01T10:29:20Z",
   "kind": "review_comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "path": "src/init.cpp",
   "commit": "37912ec1789ab2384982a3a045f9e864fdccf722",
   "in_reply_to": 3897009587,
   "text": "I took a look at this, and I think we can overshoot it by 1 if there is a race between a v2-to-v1 downgrade and the opening of a new full recon connection. Since we do not check for extra reconciliation peers in `EvictExtraOutboundPeers`, we can end up with an extra connection.\n\nI will note this, I think it can be handled alongside deciding whether we want to count reconciliations connections as full outbounds (we will need eviction logic in that case too)."
  },
  {
   "t": "2026-09-01T10:37:14Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "25e545c9448a70e0080d97aac583c2869b6c5723"
  },
  {
   "t": "2026-09-01T10:44:43Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "Addresses @brunoerg comments.\n\nI changed the way we parse `recon_result` to mimic the check we already have in place for BIP152. Also added a test for it.\n\nRegarding the race, I left a comment so we can address it when addressing general recon connection eviction.\n\nI'd appreciate your input on whether `OUTBOUND_FULL_RECONCILIATION` should be considered full outbound, and on whether extensions are worth keeping.\n\n[534a890](https://github.com/bitcoin/bitcoin/pull/35591/commits/534a89069d594a05e6bfb15858046464b05fbc9e)...[25e545c](https://github.com/bitcoin/bitcoin/pull/35591/commits/25e545c9448a70e0080d97aac583c2869b6c5723)"
  },
  {
   "t": "2026-09-01T13:52:58Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "0eddbbca81d0ceceb6375ba34e2113575057e579"
  },
  {
   "t": "2026-09-01T13:57:03Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "Rebased to fix CI, plus slightly decreased `MAX_INBOUND_RECONCILIATION_PEERS` for now, as some inbounds were being evicted in `p2p_sendtxrcncl.py` after #36078.\n\n`MAX_INBOUND_RECONCILIATION_PEERS` is currently a magic number, so we can set it properly (and increase the number of inbounds accordingly) once we decide on how to treat recon connections eviction.\n\n[d08f127](https://github.com/bitcoin/bitcoin/commit/d08f127a7764e37c30ed815b0a6c4f1d37282173)...[0eddbbc](https://github.com/bitcoin/bitcoin/pull/35591/commits/0eddbbca81d0ceceb6375ba34e2113575057e579)"
  },
  {
   "t": "2026-09-04T19:05:12Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "094a75a64ae6e23149e639d691092966a4ed2540"
  },
  {
   "t": "2026-09-04T19:27:19Z",
   "kind": "force_push",
   "who": "sr-gi",
   "commit": "37912ec1789ab2384982a3a045f9e864fdccf722"
  },
  {
   "t": "2026-09-04T19:42:14Z",
   "kind": "comment",
   "who": "sr-gi",
   "assoc": "MEMBER",
   "text": "@brunoerg, I've gone ahead and added reconciliation connections as full outbound connections, and dealt with connection eviction in the same way we did for full outbounds.\n\nI'm happy to re-work this if reviewers think this should no be seen as full outbounds, but I thought it may be best to just go ahead with an approach instead of waiting for discussion. The change is split in two commits, ab8528650be36714554934946679d69247dbb719 to refactor the current logic into a method that can be reused by reconciliation connections, and a 0ce6c11e2a1c2f583a5e0b4eaed5f019c62c0dba that implements that for them.\n\nWith this, I should have also covered your concern about v2->v1 downgrades, as outbound reconciliations now have eviction logic.\n\nOn top of that, I've changed the logic for when a peer does not accept our reconciliation connection. Before, we would have keept that node connected, acting as a regular outbound but taking a reconciliation slot. This is dangerous as it can lead to 12 full outbound connections, which may make us create even more redundant announcements. Now, those connections are dropped, and we look for another peer.\n\nThis can create some issues during the deployment phase, if not enough slots are available for all the new connections. I think we can mitigate the issue by deploying the feature in two phases. Phase 1 deploys the code, but only makes nodes accept incoming reconciliation connections, not start them, that is gated over a flag that is disabled by default (or even just disabled in general). Once enough deployment is reached, we can flip that feature and allow nodes to proactively initiate those. I have currently not gated this, as it makes it easier for testing, but I think it is worth mentioning.\n\n[0eddbbc](https://github.com/bitcoin/bitcoin/pull/35591/commits/0eddbbca81d0ceceb6375ba34e2113575057e579)...[37912ec](https://github.com/bitcoin/bitcoin/pull/35591/commits/37912ec1789ab2384982a3a045f9e864fdccf722)"
  }
 ],
 "labels_log": [
  {
   "t": "2026-06-23T14:09:43Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-23T22:11:26Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-24T14:18:36Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-24T20:49:11Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-24T23:25:19Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-13T18:22:37Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-14T17:51:28Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-17T18:45:12Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-18T17:49:30Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-18T19:59:52Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-19T19:24:07Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-19T23:33:22Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-24T09:21:16Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-24T11:31:09Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-01T12:12:52Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-01T16:04:28Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-04T19:28:10Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-04T22:02:52Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-14T15:51:33Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 28165,
 "text_tokens_estimate": 7041,
 "changed_paths": [
  "src/CMakeLists.txt",
  "src/bench/CMakeLists.txt",
  "src/bench/txreconciliation.cpp",
  "src/init.cpp",
  "src/net.cpp",
  "src/net.h",
  "src/net_processing.cpp",
  "src/node/connection_types.cpp",
  "src/node/connection_types.h",
  "src/node/txreconciliation.cpp",
  "src/node/txreconciliation.h",
  "src/node/txreconciliation_impl.cpp",
  "src/node/txreconciliation_impl.h",
  "src/protocol.h",
  "src/qt/guiutil.cpp",
  "src/rpc/net.cpp",
  "src/test/denialofservice_tests.cpp",
  "src/test/fuzz/connman.cpp",
  "src/test/txreconciliation_tests.cpp",
  "src/test/util/net.h",
  "test/functional/p2p_reqtxrcncl.py",
  "test/functional/p2p_sendtxrcncl.py",
  "test/functional/p2p_txrecon_disabled.py",
  "test/functional/p2p_txrecon_initiator.py",
  "test/functional/p2p_txrecon_responder.py",
  "test/functional/test_framework/messages.py",
  "test/functional/test_framework/p2p.py",
  "test/functional/test_framework/p2p_txrecon.py",
  "test/functional/test_framework/test_node.py",
  "test/functional/test_runner.py"
 ],
 "files": [
  {
   "path": "src/CMakeLists.txt",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/bench/CMakeLists.txt",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/bench/txreconciliation.cpp",
   "add": 64,
   "del": 0
  },
  {
   "path": "src/init.cpp",
   "add": 6,
   "del": 1
  },
  {
   "path": "src/net.cpp",
   "add": 20,
   "del": 13
  },
  {
   "path": "src/net.h",
   "add": 36,
   "del": 13
  },
  {
   "path": "src/net_processing.cpp",
   "add": 465,
   "del": 114
  },
  {
   "path": "src/node/connection_types.cpp",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/node/connection_types.h",
   "add": 10,
   "del": 0
  },
  {
   "path": "src/node/txreconciliation.cpp",
   "add": 0,
   "del": 170
  },
  {
   "path": "src/node/txreconciliation.h",
   "add": 214,
   "del": 58
  },
  {
   "path": "src/node/txreconciliation_impl.cpp",
   "add": 848,
   "del": 0
  },
  {
   "path": "src/node/txreconciliation_impl.h",
   "add": 231,
   "del": 0
  },
  {
   "path": "src/protocol.h",
   "add": 25,
   "del": 0
  },
  {
   "path": "src/qt/guiutil.cpp",
   "add": 2,
   "del": 1
  },
  {
   "path": "src/rpc/net.cpp",
   "add": 4,
   "del": 1
  },
  {
   "path": "src/test/denialofservice_tests.cpp",
   "add": 117,
   "del": 0
  },
  {
   "path": "src/test/fuzz/connman.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/test/txreconciliation_tests.cpp",
   "add": 1109,
   "del": 24
  },
  {
   "path": "src/test/util/net.h",
   "add": 1,
   "del": 0
  },
  {
   "path": "test/functional/p2p_reqtxrcncl.py",
   "add": 111,
   "del": 0
  },
  {
   "path": "test/functional/p2p_sendtxrcncl.py",
   "add": 49,
   "del": 2
  },
  {
   "path": "test/functional/p2p_txrecon_disabled.py",
   "add": 51,
   "del": 0
  },
  {
   "path": "test/functional/p2p_txrecon_initiator.py",
   "add": 266,
   "del": 0
  },
  {
   "path": "test/functional/p2p_txrecon_responder.py",
   "add": 328,
   "del": 0
  },
  {
   "path": "test/functional/test_framework/messages.py",
   "add": 113,
   "del": 1
  },
  {
   "path": "test/functional/test_framework/p2p.py",
   "add": 15,
   "del": 1
  },
  {
   "path": "test/functional/test_framework/p2p_txrecon.py",
   "add": 330,
   "del": 0
  },
  {
   "path": "test/functional/test_framework/test_node.py",
   "add": 1,
   "del": 1
  },
  {
   "path": "test/functional/test_runner.py",
   "add": 4,
   "del": 0
  }
 ],
 "test_lines": 2592,
 "git": {
  "head": "37912ec1789ab2384982a3a045f9e864fdccf722",
  "head_matches_backup": true,
  "base": "dc0395c5858a1d55239b82a834e5075cf2069219",
  "commits": [
   {
    "sha": "312095c26b",
    "subject": "refactor: redesigns txreconciliation file split and namespace",
    "files": 6,
    "add": 200,
    "del": 176
   },
   {
    "sha": "9deab543e0",
    "subject": "refactor: remove legacy comments",
    "files": 1,
    "add": 0,
    "del": 5
   },
   {
    "sha": "0d3d5c9b24",
    "subject": "refactor: Defines generic error to be used in several reconciliation methods",
    "files": 4,
    "add": 41,
    "del": 37
   },
   {
    "sha": "8e9fec2a27",
    "subject": "refactor: add full stop in existing txreconciliation LogDebug lines",
    "files": 1,
    "add": 3,
    "del": 4
   },
   {
    "sha": "e703cdf680",
    "subject": "p2p: Allows inbound reconciliation connections up to a limit",
    "files": 5,
    "add": 59,
    "del": 11
   },
   {
    "sha": "3792744ae7",
    "subject": "net, gui, test: adds new connection type (OUTBOUND_FULL_RECONCILIATION)",
    "files": 10,
    "add": 57,
    "del": 6
   },
   {
    "sha": "4d2cb97a86",
    "subject": "p2p: Count reconciliation connections as full outbound connections",
    "files": 4,
    "add": 56,
    "del": 28
   },
   {
    "sha": "ab8528650b",
    "subject": "refactor: Extract EvictWorstOutboundPeer out of EvictExtraOutboundPeers",
    "files": 1,
    "add": 64,
    "del": 56
   },
   {
    "sha": "0ce6c11e2a",
    "subject": "p2p: Evict extra reconciliation peers",
    "files": 5,
    "add": 164,
    "del": 31
   },
   {
    "sha": "07823648d9",
    "subject": "p2p: send SENDTXRCNCL messages only over OUTBOUND_FULL_RECONCILIATION connection",
    "files": 2,
    "add": 12,
    "del": 8
   },
   {
    "sha": "1a42ba6945",
    "subject": "p2p: Disconnect outbound reconciliation peers that do not negotiate",
    "files": 2,
    "add": 25,
    "del": 1
   },
   {
    "sha": "c4d9ef36fc",
    "subject": "p2p: Functions to add/remove wtxids to tx reconciliation sets",
    "files": 4,
    "add": 201,
    "del": 11
   },
   {
    "sha": "9d60dee5ed",
    "subject": "p2p: Add transactions to reconciliation sets",
    "files": 2,
    "add": 169,
    "del": 5
   },
   {
    "sha": "2ac2615781",
    "subject": "p2p: Add helper to compute reconciliation tx short ids and a cache of short ids to wtxids",
    "files": 2,
    "add": 24,
    "del": 5
   },
   {
    "sha": "07659f3221",
    "subject": "p2p: Deal with shortid collisions for reconciliation sets",
    "files": 4,
    "add": 110,
    "del": 14
   },
   {
    "sha": "1e89a027ae",
    "subject": "p2p: Add peers to reconciliation queue on negotiation",
    "files": 1,
    "add": 17,
    "del": 0
   },
   {
    "sha": "2962667892",
    "subject": "p2p: Track reconciliation requests schedule",
    "files": 2,
    "add": 32,
    "del": 0
   },
   {
    "sha": "6f0ffb61ae",
    "subject": "p2p: Initiate reconciliation round",
    "files": 6,
    "add": 281,
    "del": 0
   },
   {
    "sha": "bbfa86d2b6",
    "subject": "test: Functional test for reqtxrcncl",
    "files": 4,
    "add": 143,
    "del": 1
   },
   {
    "sha": "9409b1807c",
    "subject": "p2p: Handle reconciliation request",
    "files": 5,
    "add": 135,
    "del": 0
   },
   {
    "sha": "c1b900ef62",
    "subject": "p2p: Add helper to compute sketches for tx reconciliation",
    "files": 3,
    "add": 57,
    "del": 0
   },
   {
    "sha": "7e4c2b5edd",
    "subject": "p2p: Respond to a reconciliation request",
    "files": 6,
    "add": 127,
    "del": 0
   },
   {
    "sha": "ff227373d0",
    "subject": "p2p: Add a function to identify local/remote missing txs",
    "files": 2,
    "add": 27,
    "del": 0
   },
   {
    "sha": "07d6c6d1fc",
    "subject": "refactor: Extract AnnounceTxs out of SendMessages",
    "files": 1,
    "add": 60,
    "del": 48
   },
   {
    "sha": "db3d3e10ec",
    "subject": "p2p: Add a function to announce transactions after reconciliation",
    "files": 1,
    "add": 59,
    "del": 5
   },
   {
    "sha": "5a73d050f1",
    "subject": "p2p: Handle reconciliation sketch and successful decoding",
    "files": 6,
    "add": 333,
    "del": 4
   },
   {
    "sha": "fad7f9c261",
    "subject": "p2p: Request extension if decoding failed",
    "files": 4,
    "add": 14,
    "del": 1
   },
   {
    "sha": "6bc290a609",
    "subject": "p2p: Be ready to receive sketch extension",
    "files": 2,
    "add": 92,
    "del": 7
   },
   {
    "sha": "b9ef0cce59",
    "subject": "p2p: Prepare for sketch extension request",
    "files": 2,
    "add": 16,
    "del": 0
   },
   {
    "sha": "9f7f1d102b",
    "subject": "p2p: Keep track of announcements during txrcncl extension",
    "files": 2,
    "add": 44,
    "del": 6
   },
   {
    "sha": "fd95370940",
    "subject": "p2p: Handle reconciliation extension request",
    "files": 4,
    "add": 105,
    "del": 1
   },
   {
    "sha": "50dc0109a7",
    "subject": "p2p: Respond to sketch extension request",
    "files": 3,
    "add": 73,
    "del": 25
   },
   {
    "sha": "ddfd680a0e",
    "subject": "p2p: Handle sketch extension",
    "files": 3,
    "add": 92,
    "del": 10
   },
   {
    "sha": "880bdd7430",
    "subject": "p2p: Add a finalize incoming reconciliation function",
    "files": 4,
    "add": 316,
    "del": 0
   },
   {
    "sha": "cf883f512b",
    "subject": "p2p: Handle reconciliation finalization message",
    "files": 1,
    "add": 43,
    "del": 1
   },
   {
    "sha": "3554b3db62",
    "subject": "p2p, test: Add tx reconciliation functional tests",
    "files": 8,
    "add": 1047,
    "del": 4
   },
   {
    "sha": "0752851617",
    "subject": "p2p: Remove transactions from reconciliation sets when removed from the mempool",
    "files": 5,
    "add": 167,
    "del": 0
   },
   {
    "sha": "37912ec178",
    "subject": "bench: Adds txreconciliation benches",
    "files": 3,
    "add": 70,
    "del": 0
   }
  ],
  "patch_truncated": true
 },
 "input_hash": "5d4294d46daca43c",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}