{
 "number": 36151,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/36151",
 "title": "makeseeds: fix off-by-one in field count check",
 "author": "aman21-droid",
 "author_association": "FIRST_TIME_CONTRIBUTOR",
 "created_at": "2026-09-02T17:05:56Z",
 "updated_at": "2026-09-08T04:58:24Z",
 "age_days": 14,
 "draft": false,
 "labels": [
  "Scripts and tools"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "da29409f4b2e9197e6cc0cfe5a149b403dd27a95",
 "head_ref": "fix/makeseeds-field-count-off-by-one",
 "head_repo": "aman21-droid/bitcoin",
 "head_history": [
  {
   "t": "2026-09-02T19:12:56Z",
   "sha": "da29409f4b2e9197e6cc0cfe5a149b403dd27a95"
  }
 ],
 "additions": 22,
 "deletions": 1,
 "changed_files": 1,
 "commit_count": 2,
 "size_bucket": "S",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "ack": [
     {
      "login": "l0rinc",
      "url": "https://github.com/bitcoin/bitcoin/pull/36151#issuecomment-5515580735"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "l0rinc": {
   "kind": "ack",
   "hash": "da29409f4b2e9197e6cc0cfe5a149b403dd27a95",
   "t": "2026-09-02T19:58:58Z",
   "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": [
   "achow101",
   "l0rinc",
   "sedited"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-09-08T04:58:24Z",
  "last_reviewer_activity": "2026-09-07T22:43:18Z",
  "last_reviewer": "l0rinc",
  "author_silent_days": 9,
  "waiting_on_author_days": 0,
  "days_since_update": 9
 },
 "refs": {
  "mentioned": [
   36146
  ],
  "depends_on": [],
  "fixes": [
   36146
  ],
  "linked_issues": [
   {
    "number": 36146,
    "type": "issue",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "contrib: makeseeds.py parseline() raises IndexError on lines with exactly 11 fields"
   }
  ],
  "references": [
   {
    "number": 36146,
    "type": "issue",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "contrib: makeseeds.py parseline() raises IndexError on lines with exactly 11 fields"
   }
  ],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "contrib/seeds/makeseeds.py"
 ],
 "body": "Fixes #36146.\n\n`parseline()` checks that a line has at least 11 whitespace-separated fields:\n\n```python\nif len(sline) < 11:\n    # line too short to be valid, skip it.\n    return None\n```\n\nbut it later reads `sline[11]` (the user agent), which needs 12. A line with exactly 11 fields got past the check and then raised `IndexError`, aborting the whole run instead of skipping that line. 11 is the highest index the function uses, so the check now requires 12 fields.\n\nThis isn't only theoretical: README.md builds seeds_main.txt by appending one crawler's output onto another's, so the file mixes two independently maintained formats, and a truncated download leaves a short last line too. Skipping the line is what the check was already trying to do.\n\nThe first commit adds tests, since nothing covered makeseeds before. They pass on both commits with different expectations: it first records that an 11-field line raises `IndexError`, and the fix commit replaces that single assertion with the line being skipped. Run with:\n\n```\npython3 -m unittest contrib.seeds.makeseeds\n```",
 "commits": [
  {
   "sha": "0d0b2cbd97b218c6c2a3a328e30ded9a55f6f11d",
   "date": "2026-09-02T19:11:33Z",
   "message": "test: characterize makeseeds.py field count check\n\nRecord that a valid 12-field seeder line parses, that shorter lines are\nskipped, and that a line missing only the user agent still aborts the\nrun."
  },
  {
   "sha": "da29409f4b2e9197e6cc0cfe5a149b403dd27a95",
   "date": "2026-09-02T19:11:54Z",
   "message": "makeseeds: fix off-by-one in field count check\n\nDNS seeder lines contain 12 whitespace-separated fields ending with the\nuser agent. `parseline()` skipped only lines with fewer than 11 fields\nbut reads the user agent from `sline[11]`.\n\nA truncated line with exactly 11 fields therefore raised `IndexError`\nand aborted the run after the asmap database was loaded. Require all 12\nfields so truncated lines are skipped."
  }
 ],
 "timeline": [
  {
   "t": "2026-09-02T19:00:17Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "The fix looks correct, but it would be slightly easier to review as a [characterization plus fix pair](https://github.com/bitcoin/bitcoin/pull/35260), with the unit tests kept inline in `makeseeds.py` like we do in `contrib/asmap/asmap.py`.\n\nThe first commit can record the current `IndexError` with a TODO explaining that it should be skipped. The fix commit then replaces only that assertion.\n\nI pushed this alternative as two commits to https://github.com/l0rinc/bitcoin/pull/290 for reference. The test can be run with:\n```bash\npython3 -m unittest contrib.seeds.makeseeds\n```"
  },
  {
   "t": "2026-09-02T19:12:56Z",
   "kind": "force_push",
   "who": "aman21-droid",
   "commit": "da29409f4b2e9197e6cc0cfe5a149b403dd27a95"
  },
  {
   "t": "2026-09-02T19:15:21Z",
   "kind": "comment",
   "who": "aman21-droid",
   "assoc": "NONE",
   "text": "thanks for the reference,i have pushed it accordingly."
  },
  {
   "t": "2026-09-02T19:58:58Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "ACK da29409f4b2e9197e6cc0cfe5a149b403dd27a95\n\nThe PR description should be updated since the tests are in the first commit now and pass on both commits with different expectations. The test run command should also be changed."
  },
  {
   "t": "2026-09-03T03:43:55Z",
   "kind": "comment",
   "who": "aman21-droid",
   "assoc": "NONE",
   "text": "I updated the description and title aswell."
  },
  {
   "t": "2026-09-07T14:17:10Z",
   "kind": "review_comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "path": "contrib/seeds/makeseeds.py",
   "commit": "0d0b2cbd97b218c6c2a3a328e30ded9a55f6f11d",
   "in_reply_to": null,
   "text": "Seems a bit much to introduce this TODO for a niche utility. Either this should be implemented, or droppped. I think it can be dropped, doesn't seem important to cover this."
  },
  {
   "t": "2026-09-07T16:25:02Z",
   "kind": "review_comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "path": "contrib/seeds/makeseeds.py",
   "commit": "0d0b2cbd97b218c6c2a3a328e30ded9a55f6f11d",
   "in_reply_to": 3950546738,
   "text": "The TODO is only in the characterization test so that reveiwers are aware that it's not the desired behavior but the actual one - it're adjusted in the next commit, see https://github.com/bitcoin/bitcoin/blob/db74d3390a391a2a76d7b4d676342a9d1489059b/doc/developer-notes.md?plain=1#L698-L703"
  },
  {
   "t": "2026-09-07T17:57:12Z",
   "kind": "review_comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "path": "contrib/seeds/makeseeds.py",
   "commit": "0d0b2cbd97b218c6c2a3a328e30ded9a55f6f11d",
   "in_reply_to": 3950546738,
   "text": "Not sure how I missed that, but yes, of course that is fine!"
  },
  {
   "t": "2026-09-07T22:26:43Z",
   "kind": "comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "text": "This file is run by a number of people that is countable on one hand, I don't think a test is particularly useful here, especially as it is not being run in CI, nor should it be."
  },
  {
   "t": "2026-09-07T22:43:18Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "I don't mind if we remove the test now that we have reproduced the problem and the fix, but I suggested that the author adds it similarly to `contrib/asmap/asmap.py` - the tests are simple, document the usage, I'd keep them"
  },
  {
   "t": "2026-09-08T04:58:24Z",
   "kind": "comment",
   "who": "aman21-droid",
   "assoc": "NONE",
   "text": "Apart from the test part this is just a single line fix and I will be happy to remove the test if thats preferred, since it already proved its intended point."
  }
 ],
 "labels_log": [
  {
   "t": "2026-09-02T17:06:01Z",
   "action": "labeled",
   "label": "Scripts and tools",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2026-09-07T18:11:56Z",
   "kind": "renamed",
   "who": "aman21-droid",
   "from": "contrib: fix off-by-one in makeseeds.py line length check",
   "to": "makeseeds: fix off-by-one in field count check"
  }
 ],
 "text_chars": 3731,
 "text_tokens_estimate": 932,
 "changed_paths": [
  "contrib/seeds/makeseeds.py"
 ],
 "files": [
  {
   "path": "contrib/seeds/makeseeds.py",
   "add": 22,
   "del": 1
  }
 ],
 "test_lines": 23,
 "git": {
  "head": "da29409f4b2e9197e6cc0cfe5a149b403dd27a95",
  "head_matches_backup": true,
  "base": "dc0395c5858a1d55239b82a834e5075cf2069219",
  "commits": [
   {
    "sha": "0d0b2cbd97",
    "subject": "test: characterize makeseeds.py field count check",
    "files": 1,
    "add": 23,
    "del": 0
   },
   {
    "sha": "da29409f4b",
    "subject": "makeseeds: fix off-by-one in field count check",
    "files": 1,
    "add": 2,
    "del": 4
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "6b153adc6fc96714",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}