{
 "number": 36406,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/36406",
 "title": "test: make p2p_orphan_handling's never-requested checks able to fail",
 "author": "fametrano",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-10-01T20:32:06Z",
 "updated_at": "2026-10-07T07:04:23Z",
 "description_hash": "bd2d1bef28906421",
 "age_days": 31,
 "draft": false,
 "labels": [
  "Tests"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "5f22014aca2d071edfea95e8d3d4ba0bebbc57ca",
 "head_ref": "test-orphan-handling-never-requested-int",
 "head_repo": "fametrano/bitcoin",
 "head_history": [
  {
   "t": "2026-10-02T15:06:55Z",
   "sha": "5f22014aca2d071edfea95e8d3d4ba0bebbc57ca"
  }
 ],
 "additions": 12,
 "deletions": 6,
 "changed_files": 1,
 "commit_count": 2,
 "size_bucket": "S",
 "mergeable_state": "unknown",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "ack": [
     {
      "login": "instagibbs",
      "url": "https://github.com/bitcoin/bitcoin/pull/36406#issuecomment-5955357196"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "instagibbs": {
   "kind": "ack",
   "hash": null,
   "t": "2026-10-02T15:10:32Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 1,
  "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"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "unknown",
  "last_author_activity": "2026-10-02T15:07:05Z",
  "last_reviewer_activity": "2026-10-02T15:10:32Z",
  "last_reviewer": "instagibbs",
  "author_silent_days": 30,
  "waiting_on_author_days": 30,
  "days_since_update": 25
 },
 "refs": {
  "mentioned": [],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "test/functional/p2p_orphan_handling.py"
 ],
 "body": "`assert_never_requested` compares its argument with the hashes in the node's getdata messages, which are ints. `test_orphan_inherit_rejection` passes it hex strings, so its four checks pass whatever the node requests.\n\nThis passes ints, which needs two more changes. The rejected parent is now relayed from `peer2`: relaying a transaction makes the node request it from that peer (the parent has no witness, so the request is for its txid), and from `peer1` that request would fail the `peer1` check. Mocktime is bumped before the `peer1` and `peer2` checks, because the node requests an orphan's missing parent only after a delay; without the bump those checks would pass before any request could be sent.\n\nIt also fixes a comment: the parent is rejected for its weight (`tx-size`), not its fee.\n\nTo see each check fail, change the scenario so that the node does request the hash. The commit message lists the changes I used.\n\nFound while porting these tests to https://github.com/btclib-org/bitcoin-node-tests.\n\n*Made with my usual tools: a computer, the Internet and an LLM. The mistakes, as usual, are all mine.*",
 "commits": [
  {
   "sha": "a3c4ad12e92e9d8c0e7c020d49cbdbdef203dfa5",
   "date": "2026-10-02T14:26:06Z",
   "message": "test: make orphan inherit-rejection getdata checks able to fail\n\nPeerTxRelayer.assert_never_requested compares the hash of every request\nreceived, an int, with its argument, and test_orphan_inherit_rejection\npassed it hex strings. An int never equals a str, so these checks passed\nwhatever the node requested. Pass ints instead.\n\nTwo more changes let the checks see the requests they are about:\n\n- Relay the parent from peer2 rather than peer1. Relaying it made the\n  node request it from peer1, so the check that peer1 never requested\n  the parent fails once it compares ints.\n- Bump mocktime by TXREQUEST_TIME_SKIP before the peer1 and peer2\n  checks. The node requests an orphan's missing parent after a delay,\n  so without the bump the request has not been sent when they run.\n\nAlso correct the comment on why the parent is rejected: it exceeds the\nmaximum standard weight, and the node rejects it with tx-size.\n\nTo check each assertion can fail, the scenario was mutated in a scratch\ncopy so that the node does request the hash, and each call site was\nevaluated with both the old and the new argument. The old one passed\nevery time, and the new one failed:\n- parent not relayed: peer1 is asked for the parent, peer2 for the\n  child's txid;\n- child not relayed: peer2 is asked for the child's txid;\n- child relayed from peer2: peer2 is asked for the child's wtxid;\n- neither child nor grandchild relayed: peer3 is asked for the child's\n  txid.\nWithout the mocktime bumps, the first two mutations pass with ints too."
  },
  {
   "sha": "5f22014aca2d071edfea95e8d3d4ba0bebbc57ca",
   "date": "2026-10-02T14:26:06Z",
   "message": "test: require an int in PeerTxRelayer.assert_never_requested\n\nThe requests it checks carry int hashes, so any other type never\nmatches and the check passes whatever the node requested."
  }
 ],
 "timeline": [
  {
   "t": "2026-10-02T13:36:03Z",
   "kind": "review_comment",
   "who": "instagibbs",
   "assoc": "MEMBER",
   "path": "test/functional/p2p_orphan_handling.py",
   "commit": "e275297a4a35d58b288b553f4efc1aca19c03263",
   "in_reply_to": null,
   "text": "nit: think this works here and elsewhere and is less verbose\n```suggestion\n        peer1.assert_never_requested(parent_overly_large_nonsegwit[\"txid\"].txid_int)\n```",
   "id": "rc:4166216883",
   "url": "https://github.com/bitcoin/bitcoin/pull/36406#discussion_r4166216883",
   "hash": "cd225245c342ca33",
   "edited": "2026-10-02T13:41:06Z"
  },
  {
   "t": "2026-10-02T13:36:05Z",
   "kind": "review_comment",
   "who": "instagibbs",
   "assoc": "MEMBER",
   "path": "test/functional/p2p_orphan_handling.py",
   "commit": "5f22014aca2d071edfea95e8d3d4ba0bebbc57ca",
   "in_reply_to": null,
   "text": "since we're changing this to peer2, and it's non-obvious, very brief comment why?\n```\n          # Relay it from peer2: below, we check that the node does not ask peer1 for the parent after\n          # peer1 relays the child. Relaying the parent from peer1 would make that check fail, since the\n          # node requests the parent from the relaying peer by wtxid, which equals its txid.\n```",
   "id": "rc:4166217180",
   "url": "https://github.com/bitcoin/bitcoin/pull/36406#discussion_r4166217180",
   "hash": "28af0abd6c5a1c1a",
   "edited": "2026-10-02T13:41:06Z"
  },
  {
   "t": "2026-10-02T13:41:06Z",
   "kind": "review",
   "who": "instagibbs",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "e275297a4a35d58b288b553f4efc1aca19c03263",
   "text": "concept ACK, good catches\n\nCould we add this to `assert_never_requested` to remove the footgun and find misuse elsewhere going forward:\n\n```\nassert isinstance(txhash, int), f\"txhash must be an int, got {type(txhash).__name__}\"\n```",
   "id": "r:5392430098",
   "url": "https://github.com/bitcoin/bitcoin/pull/36406#pullrequestreview-5392430098",
   "hash": "d8c08c522a6b450a",
   "edited": "2026-10-02T13:41:25Z"
  },
  {
   "t": "2026-10-02T15:06:55Z",
   "kind": "force_push",
   "who": "fametrano",
   "commit": "5f22014aca2d071edfea95e8d3d4ba0bebbc57ca",
   "id": "push:5f22014aca2d071edfea95e8d3d4ba0bebbc57ca"
  },
  {
   "t": "2026-10-02T15:07:05Z",
   "kind": "comment",
   "who": "fametrano",
   "assoc": "CONTRIBUTOR",
   "text": "Thanks, all three taken, and rebased on master. The int check is in its own commit; it trips nowhere else, because `assert_never_requested` is only defined and used in this test. `x[\"txid\"]` is a hex string, so I used `x[\"tx\"].txid_int` instead of `x[\"txid\"].txid_int`.",
   "id": "c:5955289311",
   "url": "https://github.com/bitcoin/bitcoin/pull/36406#issuecomment-5955289311",
   "hash": "642b5e45be2400d2",
   "edited": null
  },
  {
   "t": "2026-10-02T15:10:32Z",
   "kind": "comment",
   "who": "instagibbs",
   "assoc": "MEMBER",
   "text": "ACK https://github.com/bitcoin/bitcoin/pull/36406/commits/5f22014aca2d071edfea95e8d3d4ba0bebbc57ca",
   "id": "c:5955357196",
   "url": "https://github.com/bitcoin/bitcoin/pull/36406#issuecomment-5955357196",
   "hash": "84ba7afd49107f0a",
   "edited": null
  }
 ],
 "labels_log": [
  {
   "t": "2026-10-01T20:32:23Z",
   "action": "labeled",
   "label": "Tests",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 4045,
 "text_tokens_estimate": 1011,
 "changed_paths": [
  "test/functional/p2p_orphan_handling.py"
 ],
 "files": [
  {
   "path": "test/functional/p2p_orphan_handling.py",
   "add": 12,
   "del": 6
  }
 ],
 "test_lines": 18,
 "git": {
  "head": "5f22014aca2d071edfea95e8d3d4ba0bebbc57ca",
  "head_matches_backup": true,
  "base": "69142eacd1374925cc9e4ea736c21fcec16307d0",
  "patch_id": "2f6d6cbfff20273f",
  "commits": [
   {
    "sha": "a3c4ad12e9",
    "subject": "test: make orphan inherit-rejection getdata checks able to fail",
    "files": 1,
    "add": 11,
    "del": 6
   },
   {
    "sha": "5f22014aca",
    "subject": "test: require an int in PeerTxRelayer.assert_never_requested",
    "files": 1,
    "add": 1,
    "del": 0
   }
  ],
  "patch_truncated": false
 },
 "patch_id": "2f6d6cbfff20273f",
 "input_hash": "273340bf5918a44a",
 "extracted_at": "2026-11-02T01:09:49+00:00"
}