{
 "number": 33959,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/33959",
 "title": "test: deduplicate reorg test code",
 "author": "yuvicc",
 "author_association": "CONTRIBUTOR",
 "created_at": "2025-11-27T05:49:29Z",
 "updated_at": "2026-09-08T08:13:10Z",
 "age_days": 294,
 "draft": false,
 "labels": [
  "Tests"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "56e96c0a5d397b066e633421bc5c6889c14f969d",
 "head_ref": "2025-11-followup_fix_reorgs_tests",
 "head_repo": "yuvicc/bitcoin",
 "head_history": [
  {
   "t": "2025-12-13T11:04:56Z",
   "sha": "b6150c28d1aa9bc854cd5286bf9d0484443fd73f"
  },
  {
   "t": "2026-06-12T07:45:49Z",
   "sha": "6dd6819a4bf65dcd49e399c3a09918324e508021"
  },
  {
   "t": "2026-06-12T12:17:50Z",
   "sha": "59476869d2c6168445d22c927800cd235e5ad91e"
  },
  {
   "t": "2026-07-27T04:15:28Z",
   "sha": "2edf79707828e63957f911fa57e6b0280faee508"
  },
  {
   "t": "2026-07-30T04:06:16Z",
   "sha": "56e96c0a5d397b066e633421bc5c6889c14f969d"
  }
 ],
 "additions": 104,
 "deletions": 90,
 "changed_files": 13,
 "commit_count": 2,
 "size_bucket": "M",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {},
   "conflicts": []
  }
 },
 "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": [
   "instagibbs",
   "maflcko",
   "sedited"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-07-30T04:16:23Z",
  "last_reviewer_activity": "2026-07-27T13:52:50Z",
  "last_reviewer": "instagibbs",
  "author_silent_days": 49,
  "waiting_on_author_days": 0,
  "days_since_update": 9
 },
 "refs": {
  "mentioned": [
   32587
  ],
  "depends_on": [
   32587
  ],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 32587,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2025-11-26",
    "title": "test: Fix reorg patterns in tests to use proper fork-based approach"
   }
  ],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "test/functional/mempool_updatefromblock.py",
  "test/functional/p2p_sendheaders.py",
  "test/functional/rpc_gettxspendingprevout.py",
  "test/functional/wallet_balance.py"
 ],
 "body": "Follow-up to #32587.\n\n`trigger_reorg()` was copy-pasted across several functional tests. This moves it into `blocktools.py`, together with the fork construction, as two helpers: `create_empty_fork()` and `trigger_reorg()`.\n\nThe remaining tests that still simulated reorgs with the `invalidateblock` RPC are converted to use them, since `invalidateblock` takes a different codepath than a reorg caused by a competing chain arriving.",
 "commits": [
  {
   "sha": "39489439745ec17900abf758f25a5213ec7f29ad",
   "date": "2026-07-28T04:33:42Z",
   "message": "test: move duplicated `trigger_reorg` method to blocktools.py."
  },
  {
   "sha": "56e96c0a5d397b066e633421bc5c6889c14f969d",
   "date": "2026-07-28T04:33:43Z",
   "message": "test: fix reorg behaviour in wallet, p2p and rpc functional tests to use proper fork-based approach"
  }
 ],
 "timeline": [
  {
   "t": "2025-12-13T11:04:56Z",
   "kind": "force_push",
   "who": "yuvicc",
   "commit": "b6150c28d1aa9bc854cd5286bf9d0484443fd73f"
  },
  {
   "t": "2026-05-21T14:05:06Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "are you still working on this, or can it be closed?"
  },
  {
   "t": "2026-05-22T11:50:48Z",
   "kind": "comment",
   "who": "yuvicc",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nYes resumed the work, will push the update soon!"
  },
  {
   "t": "2026-06-12T07:45:49Z",
   "kind": "force_push",
   "who": "yuvicc",
   "commit": "6dd6819a4bf65dcd49e399c3a09918324e508021"
  },
  {
   "t": "2026-06-12T12:17:50Z",
   "kind": "force_push",
   "who": "yuvicc",
   "commit": "59476869d2c6168445d22c927800cd235e5ad91e"
  },
  {
   "t": "2026-06-12T12:24:27Z",
   "kind": "comment",
   "who": "yuvicc",
   "assoc": "CONTRIBUTOR",
   "text": "Updated the PR description and ready for review"
  },
  {
   "t": "2026-07-24T09:19:32Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "@instagibbs do you want to take a look here?"
  },
  {
   "t": "2026-07-24T11:09:11Z",
   "kind": "comment",
   "who": "instagibbs",
   "assoc": "MEMBER",
   "text": "I think this might be a bit of overengineering. Centralizing code is nice, but really I don't see the value of the added abstraction aside from centralizing trigger_reorg?"
  },
  {
   "t": "2026-07-27T04:15:28Z",
   "kind": "force_push",
   "who": "yuvicc",
   "commit": "2edf79707828e63957f911fa57e6b0280faee508"
  },
  {
   "t": "2026-07-27T04:59:16Z",
   "kind": "comment",
   "who": "yuvicc",
   "assoc": "CONTRIBUTOR",
   "text": "Addressed @instagibbs suggestion to only keep `trigger_reorg` method in blocktools.py."
  },
  {
   "t": "2026-07-27T13:39:25Z",
   "kind": "review_comment",
   "who": "instagibbs",
   "assoc": "MEMBER",
   "path": "test/functional/p2p_sendheaders.py",
   "commit": "2edf79707828e63957f911fa57e6b0280faee508",
   "in_reply_to": null,
   "text": "stale comment with \"invalid\""
  },
  {
   "t": "2026-07-27T13:41:52Z",
   "kind": "review_comment",
   "who": "instagibbs",
   "assoc": "MEMBER",
   "path": "test/functional/wallet_balance.py",
   "commit": "2edf79707828e63957f911fa57e6b0280faee508",
   "in_reply_to": null,
   "text": "are these nodes disconnected? I think it can be prepped once and used to trigger reorg on both sides?"
  },
  {
   "t": "2026-07-27T13:43:39Z",
   "kind": "review_comment",
   "who": "instagibbs",
   "assoc": "MEMBER",
   "path": "test/functional/rpc_gettxspendingprevout.py",
   "commit": "2edf79707828e63957f911fa57e6b0280faee508",
   "in_reply_to": null,
   "text": "suggestion for wording:\n\n          # Disconnect tx1's block so tx1 can be replaced by tx3 below, which also\n          # evicts tx1's child tx2. Unlike the case above, use invalidateblock rather\n          # than a fork-based reorg: the index is only rewound when a block connects\n          # so disconnecting without connecting anything lets us check below that tx2 is still indexed until the next block."
  },
  {
   "t": "2026-07-27T13:51:45Z",
   "kind": "review_comment",
   "who": "instagibbs",
   "assoc": "MEMBER",
   "path": "test/functional/wallet_balance.py",
   "commit": "2edf79707828e63957f911fa57e6b0280faee508",
   "in_reply_to": null,
   "text": "no need for [0] subscript anymore"
  },
  {
   "t": "2026-07-27T13:52:50Z",
   "kind": "review_comment",
   "who": "instagibbs",
   "assoc": "MEMBER",
   "path": "test/functional/mempool_updatefromblock.py",
   "commit": "56e96c0a5d397b066e633421bc5c6889c14f969d",
   "in_reply_to": null,
   "text": "wondering if there's a good place to add this removed comment to have people not reintroduce this pattern"
  },
  {
   "t": "2026-07-28T04:20:17Z",
   "kind": "review_comment",
   "who": "yuvicc",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/mempool_updatefromblock.py",
   "commit": "56e96c0a5d397b066e633421bc5c6889c14f969d",
   "in_reply_to": 3657841530,
   "text": "Maybe we can add in `create_empty_fork` docstring?\n\n```python\ndef create_empty_fork(node, fork_length=FORK_LENGTH):\n    '''\n        Creates a fork using node's chaintip as the starting point.\n        Returns a list of blocks to submit in order.\n\n        Prefer this over calling the invalidateblock RPC to simulate a reorg:\n        invalidateblock takes a different codepath than a reorg caused by a\n        competing chain arriving, so tests using it are not exercising the\n        behaviour they mean to.\n    '''\n```"
  },
  {
   "t": "2026-07-28T04:30:52Z",
   "kind": "review_comment",
   "who": "yuvicc",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/wallet_balance.py",
   "commit": "2edf79707828e63957f911fa57e6b0280faee508",
   "in_reply_to": 3657725320,
   "text": "Correct, they are connected. Will do the changes."
  },
  {
   "t": "2026-07-30T04:06:16Z",
   "kind": "force_push",
   "who": "yuvicc",
   "commit": "56e96c0a5d397b066e633421bc5c6889c14f969d"
  },
  {
   "t": "2026-07-30T04:16:23Z",
   "kind": "comment",
   "who": "yuvicc",
   "assoc": "CONTRIBUTOR",
   "text": "Thanks for the review @instagibbs\nI've removed `Forkgenerator` class and only kept `trigger_reorg` in blocktools and addressed some comments.\n\nI have also updated PR title and the description."
  }
 ],
 "labels_log": [
  {
   "t": "2025-11-27T05:49:33Z",
   "action": "labeled",
   "label": "Tests",
   "who": "DrahtBot"
  },
  {
   "t": "2026-02-25T18:15:59Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-12T08:48:26Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-12T08:48:28Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-12T11:56:24Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2025-11-27T15:17:32Z",
   "kind": "renamed",
   "who": "fanquake",
   "from": "test: use ForkGenerator to deduplicate reorg test code (#32587 follow-up)",
   "to": "test: use ForkGenerator to deduplicate reorg test code"
  },
  {
   "t": "2026-06-12T12:23:56Z",
   "kind": "ready_for_review",
   "who": "yuvicc"
  },
  {
   "t": "2026-07-30T04:10:47Z",
   "kind": "renamed",
   "who": "yuvicc",
   "from": "test: use ForkGenerator to deduplicate reorg test code",
   "to": "test: deduplicate reorg test code and update remaining tests to fork-based reorgs"
  },
  {
   "t": "2026-07-30T04:11:19Z",
   "kind": "renamed",
   "who": "yuvicc",
   "from": "test: deduplicate reorg test code and update remaining tests to fork-based reorgs",
   "to": "test: deduplicate reorg test code"
  }
 ],
 "text_chars": 2545,
 "text_tokens_estimate": 636,
 "changed_paths": [],
 "files": [],
 "test_lines": null,
 "git": null,
 "input_hash": "6c627326d5c3ecf9",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}