{
 "number": 34717,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/34717",
 "title": "p2p: remove m_getaddr_sent",
 "author": "naiyoma",
 "author_association": "MEMBER",
 "created_at": "2026-03-03T12:04:38Z",
 "updated_at": "2026-09-17T11:40:49Z",
 "age_days": 198,
 "draft": false,
 "labels": [
  "P2P"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "c8ee319fffa1b7674fad3a797cd6d5110435a74c",
 "head_ref": "2026_1/m_getaddr_sent",
 "head_repo": "naiyoma/bitcoin",
 "head_history": [
  {
   "t": "2026-03-06T10:55:00Z",
   "sha": "b5914990464e581731f8214c0ff1c3cb6b58cb94"
  },
  {
   "t": "2026-03-17T11:35:56Z",
   "sha": "a69f745d7b7d4cb0a0447f23ffa459ef087c5e3c"
  },
  {
   "t": "2026-03-17T12:35:10Z",
   "sha": "753f04448bb9d064d7dd9d03ffd17e6639fed7f3"
  },
  {
   "t": "2026-03-17T14:47:14Z",
   "sha": "016077e8b2eeb7f80c687facc188d9cb1f5b4f13"
  },
  {
   "t": "2026-03-26T10:18:17Z",
   "sha": "c8ee319fffa1b7674fad3a797cd6d5110435a74c"
  }
 ],
 "additions": 1,
 "deletions": 13,
 "changed_files": 2,
 "commit_count": 2,
 "size_bucket": "S",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "ack": [
     {
      "login": "w0xlt",
      "url": "https://github.com/bitcoin/bitcoin/pull/34717#pullrequestreview-4047442971"
     },
     {
      "login": "danielabrozzoni",
      "url": "https://github.com/bitcoin/bitcoin/pull/34717#pullrequestreview-4088924027"
     }
    ],
    "concept_nack": [
     {
      "login": "taki-abedesselam",
      "url": "https://github.com/bitcoin/bitcoin/pull/34717#issuecomment-4020647442"
     }
    ],
    "concept_ack": [
     {
      "login": "mzumsande",
      "url": "https://github.com/bitcoin/bitcoin/pull/34717#pullrequestreview-3903255479"
     }
    ],
    "stale_ack": [
     {
      "login": "Crypt-iQ",
      "url": "https://github.com/bitcoin/bitcoin/pull/34717#issuecomment-4012108837"
     },
     {
      "login": "stratospher",
      "url": "https://github.com/bitcoin/bitcoin/pull/34717#issuecomment-4025542351"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "chriszeng1010": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-03-03T20:48:18Z",
   "stale": false
  },
  "stratospher": {
   "kind": "ack",
   "hash": "b591499",
   "t": "2026-03-09T17:34:10Z",
   "stale": true
  },
  "Crypt-iQ": {
   "kind": "ack",
   "hash": "b5914990464e581731f8214c0ff1c3cb6b58cb94",
   "t": "2026-03-06T14:34:19Z",
   "stale": true
  },
  "mzumsande": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-03-06T11:45:01Z",
   "stale": false
  },
  "taki-abedesselam": {
   "kind": "concept_nack",
   "hash": null,
   "t": "2026-03-09T02:11:49Z",
   "stale": false
  },
  "danielabrozzoni": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-03-26T14:55:52Z",
   "stale": false
  },
  "w0xlt": {
   "kind": "ack",
   "hash": "c8ee319fffa1b7674fad3a797cd6d5110435a74c",
   "t": "2026-04-01T22:34:05Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 1,
  "stale_ack": 2,
  "concept_ack": 3,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 1,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 1,
  "changes_requested": 0,
  "distinct_reviewers": [
   "Bortlesboat",
   "Crypt-iQ",
   "ajtowns",
   "chriszeng1010",
   "danielabrozzoni",
   "fanquake",
   "mzumsande",
   "sedited",
   "stratospher",
   "taki-abedesselam",
   "w0xlt"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-07-08T14:39:13Z",
  "last_reviewer_activity": "2026-09-17T11:40:49Z",
  "last_reviewer": "sedited",
  "author_silent_days": 71,
  "waiting_on_author_days": 0,
  "days_since_update": 0
 },
 "refs": {
  "mentioned": [
   19794,
   34146,
   34150
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 19794,
    "type": "pull",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "p2p: Remove fGetAddr flag"
   },
   {
    "number": 34146,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-01-14",
    "title": "p2p: send first addr self-announcement in separate message \ud83c\udf84"
   },
   {
    "number": 34150,
    "type": "issue",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "Windows cross-build: unit test `system_tests/run_command` fails and functional tests cannot start `bitcoind`"
   }
  ],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "test/functional/p2p_addr_relay.py"
 ],
 "body": "This PR removes `m_getaddr_sent`, as it no longer behaves as originally intended. Initially, this flag was meant to track when a getaddr message was sent to a peer.\n\nNow that the initial self-announcements are sent separately from getaddr responses, the self-announcement sets `m_getaddr_sent `to `false` even though we are still waiting for the getaddr response (1000 addresses).\nWhen the getaddr response does arrive, we rely on the size of the addr message, not the flag, to decide whether it should be relayed. This makes the flag redundant.\n\nThis is the current behavior:\n\n- The initial self-announcement is not relayed but it flips m_getaddr_sent to be false\n- We use addr.size() to avoid relaying  (1000) getaddr response.(assuming the other two flags are false)\n- The first addr message is relayed because the flag is  false(this was not the case before https://github.com/bitcoin/bitcoin/pull/34146).\n\nRemoving this flag ensures that:\n\n- The initial self-announcement is relayed.\n- The getaddr response is still not relayed, using the existing size-based check.\n\nI had initially considered an alternative approach https://github.com/naiyoma/bitcoin/pull/14, where the self-announcement would not affect this flag and would therefore retain the initial behaviour, but i decided to reattempt its removal, as this was previously attempted, see https://github.com/bitcoin/bitcoin/pull/19794. Given the changes since then, I believe revisiting it is now more appropriate.",
 "commits": [
  {
   "sha": "a1ecda2609965f623ec808bc870ff6d7f151a419",
   "date": "2026-03-26T07:40:27Z",
   "message": "test: delete redundant addr relay assertion\n\nThe assertion checks that the first addr message is not relayed\ndue to m_getaddr_sent being set to true.\nBut we now send a self-announcement as the first message,\nwhich resets the flag to false, meaning subsequent addr messages are relayed."
  },
  {
   "sha": "c8ee319fffa1b7674fad3a797cd6d5110435a74c",
   "date": "2026-03-26T07:57:58Z",
   "message": "net: remove m_getaddr_sent\n\nThe flag was intended to track whether we sent a GETADDR to a peer,\nbut it became redundant after the initial self-announcement sets it to false,\neven though we still expect the actual getaddr response.\n\nCo-authored-by: Martin Zumsande <mzumsande@gmail.com>"
  }
 ],
 "timeline": [
  {
   "t": "2026-03-03T12:06:39Z",
   "kind": "comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "text": "Sharing this here in case it\u2019s helpful for review.\n\n1. This PR also addresses the concern raised here \u2192 https://github.com/bitcoin/bitcoin/pull/34146#issuecomment-3826058451. I found the comment a bit confusing, as I didn\u2019t fully understand how the self-announcement is disadvantaged. That said, the flag being set incorrectly is true.\n\n2. The issue discussed here -> https://github.com/bitcoin/bitcoin/pull/19794#issuecomment-687476649\n Removing this flag means that we can relay a (small <= 10) getaddr reponse if an addrman is very small , maybe this is still an issue, but this flag will not prevent this from happening.\n\n3. If you cherry-pick this commit 481135858a743bc28fec20a45828293eb6512a18 you can test that this assertion https://github.com/bitcoin/bitcoin/blob/master/test/functional/p2p_addr_relay.py#L189 passes even without the flag, hence the deletion\n\n4. Some logs with the messages in order:\n\n```\n2026-02-25T10:48:57Z [net] ADDR recv: msg #1 from peer=15, contains 1 addresses\n2026-02-25T10:48:57Z [net] ADDR msg #1 from peer=15: 1 received, 1 processed, 0 rate-limited, 0 relayed\n2026-02-25T10:48:57Z [net] ADDR state: peer=15 m_getaddr_sent=true\n\n2026-02-25T10:49:05Z [net] ADDR recv: msg #2 from peer=15, contains 999 addresses\n2026-02-25T10:49:05Z [net] ADDR msg #2 from peer=15: 999 received, 999 processed, 0 rate-limited, 0 relayed\n2026-02-25T10:49:05Z [net] ADDR state: peer=15 m_getaddr_sent=false\n\n2026-02-25T10:49:28Z [net] ADDR recv: msg #3 from peer=15, contains 2 addresses\n2026-02-25T10:49:28Z [net] ADDR relay: [2a02:908:530:c1a0:bd2e:450e:8330:e0f2]:8333 from msg #3 (peer=15)\n2026-02-25T10:49:28Z [net] ADDR relay: j3og3zy5og3acpbcwl7jncmcobhfk66bmrphcev7ct6pjc765zi4t5id.onion:8333 from msg #3 (peer=15)\n2026-02-25T10:49:28Z [net] ADDR msg #3 from peer=15: 2 received, 2 processed, 0 rate-limited, 2 relayed\n2026-02-25T10:49:28Z [net] ADDR state: peer=15 m_getaddr_sent=false\n```\n\n msg # 1 message one is the self announcement\n\nmsg # 2 getaddr response\n\nmsg # 3 addresses to relay"
  },
  {
   "t": "2026-03-03T15:57:29Z",
   "kind": "comment",
   "who": "w0xlt",
   "assoc": "CONTRIBUTOR",
   "text": "Interesting. Concept ACK."
  },
  {
   "t": "2026-03-03T20:48:18Z",
   "kind": "comment",
   "who": "chriszeng1010",
   "assoc": "NONE",
   "text": "concept ack."
  },
  {
   "t": "2026-03-05T09:47:02Z",
   "kind": "review_comment",
   "who": "stratospher",
   "assoc": "MEMBER",
   "path": "test/functional/p2p_addr_relay.py",
   "commit": "b5914990464e581731f8214c0ff1c3cb6b58cb94",
   "in_reply_to": null,
   "text": "9e34acb: nit: I think keeping this comment \"`# Send an empty ADDR message to initialize address relay on this connection.`\" is useful."
  },
  {
   "t": "2026-03-05T10:49:35Z",
   "kind": "review",
   "who": "stratospher",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "9e34acb1dbff61efb1c5e4e9cfce2a4591c2832f",
   "text": "ACK 9e34acb1. nice find!\n\n`m_getaddr_sent` logic is broken after https://github.com/bitcoin/bitcoin/pull/34146 and doesn\u2019t do what it\u2019s supposed to do anymore.\n\ni think removing it is a logical bug fix which would be nice to have in v31. (not sure if it\u2019s too late for that)\n\nthere would be a few behaviour changes with this PR:\n\n1. (might be debatable change) we would relay ADDR messages to peers just based on size \u226410. feel it's ok because:\n    1. is it ok if someone send 5 ADDR as the GETADDR response (instead of the usual 1000 ADDR) and we relay it?\n        1. we do GETADDR requests only to outbound peers ( so unlikely for it to be attacker controlled).\n        2. in some remote scenario (where we got eclipsed) , suppose an attacker  is chosen as our outbound peer - and it only sends us 5 ADDR as GETADDR response. we will relay it to our other peers once during the start of node\u2019s lifecycle (wouldn\u2019t have relayed these 5 ADDR before this PR). we also will have bigger problems to worry about than if address got relayed.\n        3. there are much more effective ways for an attacker to force certain ADDR to be relayed than focus on the response to GETADDR - a normal node only sends GETADDR once during the version handshake.\n2. (good change -fixes [an inconsistent behaviour](https://github.com/bitcoin/bitcoin/blob/083242aac81d02b6547ca37e0b4e6f37e0e89d87/test/functional/p2p_addr_relay.py#L184) on master) currently we don\u2019t relay the 1st ADDR message received from an outbound peer with size \u2264 10. now we relay it.\n3. (good change) initial self announcement always gets relayed."
  },
  {
   "t": "2026-03-05T15:28:25Z",
   "kind": "review_comment",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "path": "test/functional/p2p_addr_relay.py",
   "commit": "b5914990464e581731f8214c0ff1c3cb6b58cb94",
   "in_reply_to": 2888884291,
   "text": "I agree, it took me a minute to figure out what was going on here.\n\nAlso, unrelated to this PR, I noticed the outbound p2p connections are sending GETADDR that will get ignored."
  },
  {
   "t": "2026-03-05T15:50:54Z",
   "kind": "comment",
   "who": "fanquake",
   "assoc": "MEMBER",
   "text": "cc @mzumsande"
  },
  {
   "t": "2026-03-05T15:59:59Z",
   "kind": "review",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "9e34acb1dbff61efb1c5e4e9cfce2a4591c2832f",
   "text": "crACK 9e34acb1dbff61efb1c5e4e9cfce2a4591c2832f\n\n[quoted text omitted]\nCan you elaborate? It seems like the very first addr message was not being relayed, like you said?"
  },
  {
   "t": "2026-03-06T10:20:44Z",
   "kind": "comment",
   "who": "fanquake",
   "assoc": "MEMBER",
   "text": "cc @0xB10C"
  },
  {
   "t": "2026-03-06T10:55:00Z",
   "kind": "force_push",
   "who": "naiyoma",
   "commit": "b5914990464e581731f8214c0ff1c3cb6b58cb94"
  },
  {
   "t": "2026-03-06T10:59:05Z",
   "kind": "review_comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "path": "test/functional/p2p_addr_relay.py",
   "commit": "b5914990464e581731f8214c0ff1c3cb6b58cb94",
   "in_reply_to": 2888884291,
   "text": "comment added back b5914990464e581731f8214c0ff1c3cb6b58cb94"
  },
  {
   "t": "2026-03-06T11:29:54Z",
   "kind": "comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\nThanks for reviewing\nA quick clarification on this: we started relaying the first ADDR message after PR 34146, not this PR.\nThis is because the self-announcement sets this flag to false. If you look at the logs here -> https://github.com/bitcoin/bitcoin/pull/34717#issuecomment-3990585763\nThe first ADDR message, which is message 3 (msg # 3) that you are referring to, is being relayed, also, notice that by the time we receive this message, m_getaddr_sent = false, so the relay condition is true."
  },
  {
   "t": "2026-03-06T11:42:49Z",
   "kind": "comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nFor the first regular ADDR after the GETADDR response, this condition was false because `m_getaddr_sent` was true https://github.com/bitcoin/bitcoin/blob/01651324f4e540f6b96cff31e89752c3f9417293/src/net_processing.cpp#L4074"
  },
  {
   "t": "2026-03-06T11:45:01Z",
   "kind": "review",
   "who": "mzumsande",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "b5914990464e581731f8214c0ff1c3cb6b58cb94",
   "text": "Concept ACK\n\nJust making clear that while #34146 had the effect that `m_get_addr_sent` doesn't match the GETADDR answer anymore, it didn't make anything worse: the flag was already unnecessary before (due to the <10 criterion), and the first self-announcement (when it was mixed into the 1000 size GETADDR answer) did not get relayed to peers before either.\n\nSo I'd say this PR doesn't correct a bug introduced by #34146, but improves logic that was already broken before."
  },
  {
   "t": "2026-03-06T12:51:22Z",
   "kind": "comment",
   "who": "ajtowns",
   "assoc": "MEMBER",
   "text": "I think the intended logic is (was) \"we sent a getaddr, therefore the next addr message we receive will probably be old information which we shouldn't relay further\".\n\nSo #34146 did introduce a \"bug\" in that it became no longer true that next next addr message contained old information -- instead it would contain a self-announcement. That would then clear the flag, and we'd risk relaying the old information in the following addr message, that was in response to the getaddr request. The `< 10` check and the `10 minute` checks both probably made the impact of that \"bug\" pretty rare/trivial however. So I don't think this is urgent for 31.0.\n\nI think this change is fine though -- the 10min and <10 check seem already sufficient: if we get a small response to our getaddr, that's full of (honestly) recent information, then relaying that is either good or at worst harmless; and if an attacker were trying to exploit that ability, they could simply have sent a dummy addr message, and the real attack data later, avoiding the `m_get_addr_sent` gate entirely.\n\nI'm not sure that improved relay of self-announcements of nodes that only just connected to you is necessarily a good thing. Currently (and prior to #34146) your node's IP would likely only be relayed reliably once you've been connected to a peer for a couple of hours or so, which serves as an automatic way of avoiding cluttering up everyone's address book with (honest) nodes that start up, sync, and shut down. So Concept ~0. Code looks fine if the behaviour is desirable, though."
  },
  {
   "t": "2026-03-06T13:26:18Z",
   "kind": "comment",
   "who": "mzumsande",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nDoes this have the direction mixed up? This is about improved relay of self-announcements originating from peers that _we connected_ to - we, the initiating node, issue the GETADDR request, set `m_get_addr_sent` and process the answer / the self-announcement of that peer and maybe relay it further. So the affected self-announcements are those from reachable, usually reliable nodes (after all we picked them somehow).\n\nThe reverse direction (we, a possibly new/unreliable node, connect to a peer, and our own self-advertisment gets relayed by that peer or not) is not affected by this PR at all I think because this would involve `m_getaddr_recvd` instead of `m_get_addr_sent`."
  },
  {
   "t": "2026-03-06T14:34:19Z",
   "kind": "comment",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "text": "reACK b5914990464e581731f8214c0ff1c3cb6b58cb94"
  },
  {
   "t": "2026-03-06T15:45:10Z",
   "kind": "review_comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "path": "test/functional/p2p_addr_relay.py",
   "commit": "b5914990464e581731f8214c0ff1c3cb6b58cb94",
   "in_reply_to": 2888884291,
   "text": "[quoted text omitted]\nI think its because -> https://github.com/bitcoin/bitcoin/blob/master/src/net_processing.cpp#L4911"
  },
  {
   "t": "2026-03-06T17:26:20Z",
   "kind": "comment",
   "who": "ajtowns",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nYeah, it does have the direction mixed up. Still not sure how much benefit it makes to relay the initial self-announcement though. If they're already reachable/reliable nodes, then their address is already well known, and only getting re-announced by long-term connections is probably not terrible? I guess if it weren't useful to relay it, the peer shouldn't bother sending it to us -- we've already connected successfully, so we already have a working address for the peer and don't need to be told; so why else would they send it unless they wanted it relayed so others could more easily connect to them? Delaying the self-announcement until the connection's been alive a random amount of time would obviously be possible on the sender's side; (eg suggested [here](https://github.com/bitcoin/bitcoin/issues/19694#issuecomment-671438244)) so why treat it specially on the receiver side?\n\nI guess this doesn't have privacy implications -- I don't think you can distinguish a relayed self-announcement between being one of our outbounds or one of our inbounds; and distinguishing an addr relay for a direct connection vs a random forwarded addr seems like it requires a long-term connection and probably a lot of probability analysis?\n\nFrom https://github.com/bitcoin/bitcoin/pull/19794#issuecomment-687476649 :\n\n[quoted text omitted]\nI suppose that's something we could consider. I suppose we could also consider limiting our GETADDR responses to addr entries that are more than 10min old, or artificially inflating the ages of the addresses we send to ensure they're more than 10min old (and perhaps documenting that in a BIP so other node software that cares about the privacy concerns raised in that comment can implement compatible logic)."
  },
  {
   "t": "2026-03-09T02:11:49Z",
   "kind": "comment",
   "who": "taki-abedesselam",
   "assoc": "NONE",
   "text": "Concept NACK\n\nI do not agree with this solution for removing `m_getaddr_sent`. Instead we should consider reusing it. I believe there is a significant issue in the bitcoin code: it gives a malicious neighbor node the ability to abuse our unsolicited message relaying. This could happen as follows :\n\n- We establish an outbound connection to a node **X**.\n- We increase the token counter to [ **+1000 tokens**](https://github.com/bitcoin/bitcoin/blob/d198635fa2d48b7618789aedf112783935015d77/src/net_processing.cpp#L3772) since we expect to receive up to **1000 addresses** in response from node **X**.\n- Node **X** sends a buffer containing only **1 address**, to [bypasses](https://github.com/bitcoin/bitcoin/blob/d198635fa2d48b7618789aedf112783935015d77/src/net_processing.cpp#L4100) the initial `m_getaddr_sent` check (or this protection disappears entirely if the variable is removed as proposed in this PR)\n- Node **X** then starts sending unsolicited messages of size 10, since it knows it can use up to **1000 tokens** (each address they will consume 1 token and if the number of addresses in the buffer is less or equal to 10 our node will relay it).\n- Our node become an intermediate relay, unintentionally helping hide this malicious node, since its (our node) the one who will relay the unsolicited messages.\n- Our node they will consume all of its tokens with other nodes by forwarding  malicious addresses instead of forwarding addresses for legitimate nodes.\n\nFor these reasons, instead of removing `m_getaddr_sent`, we should keep it and improve the token handling logic for `GETADDR` messages."
  },
  {
   "t": "2026-03-09T12:36:58Z",
   "kind": "comment",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nCan't this be done independent of this patch? Also, the GETADDR is only sent for outbound connections so its impact is limited?"
  },
  {
   "t": "2026-03-09T13:20:45Z",
   "kind": "comment",
   "who": "ajtowns",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nI think this doesn't make sense -- if we want to treat addresses received as a response to \"GETADDR\" differently, then `m_getaddr_sent` should be a bucket that's normally 0, but is bumped to 1000 when we send \"GETADDR\". Then the idea might be:\n\n```c++\n    bool relay{true};\n    if (peer.m_addr_token_bucket < 1.0) {\n        if (rate_limited) {\n            if (m_getaddr_bucket == 0) {\n                ++num_rate_limit; continue;\n           } else {\n                 --m_getaddr_bucket;\n                relay = false;\n           }\n        }\n    } else {\n        peer.m_addr_token_bucket -= 1.0;\n    }\n    ...\n    if (relay && addr.nTime > current_a_time - 10min && vAddr.size() <= 10 && addr.IsRoutable()) {\n        // Relay to a limited number of other nodes\n        RelayAddress(pfrom.GetId(), addr, reachable);\n    }\n```"
  },
  {
   "t": "2026-03-09T16:42:47Z",
   "kind": "comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "text": "This doesn't need to be part of v31. As mentioned above, even though it is possible for us to relay a GETADDR response currently, the probability is low because the default node behaviour will almost always have around 1000 addresses (> 10 addresses, hence we don't relay), and GETADDR responses are usually older."
  },
  {
   "t": "2026-03-09T16:48:37Z",
   "kind": "comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n This attack is still possible with or without this flag in normal address relay, not just in response to GETADDR."
  },
  {
   "t": "2026-03-09T17:34:10Z",
   "kind": "comment",
   "who": "stratospher",
   "assoc": "MEMBER",
   "text": "reACK b591499.\n\nagree regarding it not being important for v31 - it's just an extra address relay anyways. I thought of this as a logical couple to #34150 - we're changing initial self announcement sending logic in that PR - so makes sense that the receiving logic code is also updated which is why I initially suggested it for v31. but it's just an inconsistency in our code and won't matter to people running the software.\n\nI guess the initial self announcement being relayed + this not being done before is what's causing concern. There's the alternative (https://github.com/naiyoma/bitcoin/pull/14) which naiyoma proposed of making `m_get_addrsent` more strict - but it can't act as a proper gate anyways and might as well remove it.\n\nalso liked [aj's alternative suggestion](https://github.com/bitcoin/bitcoin/pull/34717#issuecomment-4013027535) of making sure GETADDR responses are actually old when selecting from addrman.  I collected some address relay stats of my node last month. don't quote me on this since I haven't cross checked with other GETADDR responses. this is the address staleness of the GETADDR response of 1 particular peer (GPT plotted a histogram from the data):\n\nalso worth noting - the previous version of PR in https://github.com/bitcoin/bitcoin/pull/19794 was made at a time when ADDR token logic wasn't there + possibility of someone spamming us without any rate limiting."
  },
  {
   "t": "2026-03-11T05:17:00Z",
   "kind": "comment",
   "who": "taki-abedesselam",
   "assoc": "NONE",
   "text": "[quoted text omitted]\n\ngood idea to separate the logic of the response from normal forwarding , could i also suggest the following: that during the first X seconds we are expecting that we will receive a self-announcement and a response to our GETADDR message, for self-announcement  we could distinguish it by checking if the sender is the same as the address in the buffer + the time it will be fresh, so we will relay it. and for the other addresses we will use `peer.m_addr_token_bucket` and a timer tracker if `now - get_addr_send_time <= X`,\notherwise we will switch to the normal tokens."
  },
  {
   "t": "2026-03-17T11:35:56Z",
   "kind": "force_push",
   "who": "naiyoma",
   "commit": "a69f745d7b7d4cb0a0447f23ffa459ef087c5e3c"
  },
  {
   "t": "2026-03-17T12:35:10Z",
   "kind": "force_push",
   "who": "naiyoma",
   "commit": "753f04448bb9d064d7dd9d03ffd17e6639fed7f3"
  },
  {
   "t": "2026-03-17T14:47:14Z",
   "kind": "force_push",
   "who": "naiyoma",
   "commit": "016077e8b2eeb7f80c687facc188d9cb1f5b4f13"
  },
  {
   "t": "2026-03-17T17:45:21Z",
   "kind": "review_comment",
   "who": "Bortlesboat",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/p2p_addr_relay.py",
   "commit": "c8ee319fffa1b7674fad3a797cd6d5110435a74c",
   "in_reply_to": null,
   "text": "Since this removes the suppression of the first addr message, could we flip the assertion rather than delete it? Something like:\n```python\nmsg = self.setup_addr_msg(2)\nself.send_addr_msg(full_outbound_peer, msg, [inbound_peer])\nself.log.info('Check that the first addr message from an outbound peer is relayed')\nassert_equal(inbound_peer.num_ipv4_received, 2)\n```\nThat way the behavioral change (first addr from outbound is now relayed) has positive test coverage."
  },
  {
   "t": "2026-03-17T18:46:06Z",
   "kind": "comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "text": "rebased, re-ordered commits, and updated test commit message"
  },
  {
   "t": "2026-03-25T15:18:19Z",
   "kind": "review_comment",
   "who": "danielabrozzoni",
   "assoc": "MEMBER",
   "path": "test/functional/p2p_addr_relay.py",
   "commit": "b5914990464e581731f8214c0ff1c3cb6b58cb94",
   "in_reply_to": 2888884291,
   "text": "[quoted text omitted]\nCan you clarify? I don't see how this can happen.\n\nWe only send a GETADDR to our outbound, non-block-relay peers:\n\nhttps://github.com/bitcoin/bitcoin/blob/2fe76ed8324af44c985b96455a05c3e8bec0a03e/src/net_processing.cpp#L3749-L3767\n\nAnd we only reply to GETADDR requests if they're from inbound connections:\n\nhttps://github.com/bitcoin/bitcoin/blob/2fe76ed8324af44c985b96455a05c3e8bec0a03e/src/net_processing.cpp#L4816-L4825\n\nSo, I think this happens:\n\n(--> means the direction of the connection, so outbound for the node on the left, inbound for the node on the right)\n\n```\n+------+            +------+\n| Node | ---------> | Node |\n+------+            +------+\n         -> getaddr\n         <- addr\n```"
  },
  {
   "t": "2026-03-25T15:28:41Z",
   "kind": "review_comment",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "path": "test/functional/p2p_addr_relay.py",
   "commit": "b5914990464e581731f8214c0ff1c3cb6b58cb94",
   "in_reply_to": 2888884291,
   "text": "[quoted text omitted]\n\nThe test does it."
  },
  {
   "t": "2026-03-26T10:18:17Z",
   "kind": "force_push",
   "who": "naiyoma",
   "commit": "c8ee319fffa1b7674fad3a797cd6d5110435a74c"
  },
  {
   "t": "2026-03-26T10:21:09Z",
   "kind": "review_comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "path": "test/functional/p2p_addr_relay.py",
   "commit": "c8ee319fffa1b7674fad3a797cd6d5110435a74c",
   "in_reply_to": 2948505290,
   "text": "@Bortlesboat, this is already being tested here -> https://github.com/naiyoma/bitcoin/blob/2026_1/m_getaddr_sent/test/functional/p2p_addr_relay.py#L192"
  },
  {
   "t": "2026-03-26T11:05:37Z",
   "kind": "comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "text": "Rebased,"
  },
  {
   "t": "2026-03-26T14:27:52Z",
   "kind": "review_comment",
   "who": "danielabrozzoni",
   "assoc": "MEMBER",
   "path": "test/functional/p2p_addr_relay.py",
   "commit": "c8ee319fffa1b7674fad3a797cd6d5110435a74c",
   "in_reply_to": null,
   "text": "nit: 'subsequent' here made sense when read after 'Check that the first message is not relayed'. Since we are deleting that part of the test, this should be changed to something like 'Check that every addr message sent from an outbound peer is relayed'."
  },
  {
   "t": "2026-03-26T14:28:28Z",
   "kind": "review_comment",
   "who": "danielabrozzoni",
   "assoc": "MEMBER",
   "path": "test/functional/p2p_addr_relay.py",
   "commit": "b5914990464e581731f8214c0ff1c3cb6b58cb94",
   "in_reply_to": 2888884291,
   "text": "Got it, sorry for the confusion"
  },
  {
   "t": "2026-03-26T14:55:52Z",
   "kind": "review",
   "who": "danielabrozzoni",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "c8ee319fffa1b7674fad3a797cd6d5110435a74c",
   "text": "Concept ACK, code looks good, but I need to spend some more time thinking about this before ACKing :)\n\nI think there's a small source of confusion in the PR description, and [here](https://github.com/bitcoin/bitcoin/pull/34717#issuecomment-4011188780):\n\n[quoted text omitted]\nWhat you're calling \"the first addr message\" is really the second ADDR message, the first one being the initial self announcement. So it's correct to say that in master the first ADDR message (the self announcement) is not relayed, and subsequent ADDR messages are relayed."
  },
  {
   "t": "2026-03-31T13:18:32Z",
   "kind": "comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\nits actually the third addr message, if you see the logs I posted here ->  https://github.com/bitcoin/bitcoin/pull/34717#issuecomment-3990585763\n\nthe first message is the self announcement,\nthe second is the getaddr response\nthe third is the few addresses we want to relay\n\nIt's true, this is confusing; it's not easy to distinguish these messages. What I am referring to here as the first addr message is the first addr message to be relayed, but it's the third in order of messages received\n\n[quoted text omitted]\nThe next addr message after the self announcement is not relayed because it's the getaddr addr response, and we have this size check `vAddr.size() <= 10` to prevent this.\n\nPerhaps this is clearer? -> The first addr message after a getaddr response is relayed because the flag is false(this was not the case before https://github.com/bitcoin/bitcoin/pull/34146)."
  },
  {
   "t": "2026-04-01T22:34:05Z",
   "kind": "review",
   "who": "w0xlt",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "c8ee319fffa1b7674fad3a797cd6d5110435a74c",
   "text": "ACK c8ee319fffa1b7674fad3a797cd6d5110435a74c\n\nIf an outbound peer does not send an initial self-announcement, master still has `m_getaddr_sent == true` when it processes the first `ADDR` reply to our `GETADDR`.\n\nThat suppresses relay of a small fresh routable response (<=10 addrs). This PR removes that distinction, so such `GETADDR` replies would now be relayed.\n\nIt might be worth documenting this minor behavior change."
  },
  {
   "t": "2026-04-10T10:16:15Z",
   "kind": "review",
   "who": "danielabrozzoni",
   "assoc": "MEMBER",
   "state": "APPROVED",
   "commit": "c8ee319fffa1b7674fad3a797cd6d5110435a74c",
   "text": "tACK c8ee319fffa1b7674fad3a797cd6d5110435a74c\n\nWhat often happens right now is that we send a getaddr, and receive the self announcement of the peer before the getaddr response:\n\n```\nus                          peer\n |---- getaddr ------------>|\n |<--- addr (self, size=1)--|\n |<--- addr (response, usually size=1000)\n```\n\nWith the `m_getaddr_sent` flag, the first addr received is treated as if it was the getaddr response, and as such it sets `m_getaddr_sent` to false, and is not relayed. The second addr received is the getaddr response, and might get relayed if its size is <10.\nIt's cleaner to remove the `m_getaddr_sent` flag altogether, since it often doesn't reflect whether a getaddr response has been received or not. The effect of this is:\n- we will start relaying our peer's first self announcement\n- we might relay the getaddr response if its size is <10 - similarly to what we might do now, in master, if we received the self announcement first and a small getaddr response second\n\nI would like to see https://github.com/bitcoin/bitcoin/pull/34717/changes/a1ecda2609965f623ec808bc870ff6d7f151a419#r2995359668 fixed if you push again :)\n\n[quoted text omitted]\nYes, sorry about that!\n\n[quoted text omitted]\nYes, I think so :)"
  },
  {
   "t": "2026-04-16T15:15:38Z",
   "kind": "comment",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "text": "The code makes sense, though I think there can be more discussion of https://github.com/bitcoin/bitcoin/pull/34717#issuecomment-4013027535 and its links:\n- is there a privacy leak with the initial self-announcement relay? is it even beneficial if the peer already knows the address?\n- is relaying the response to a GETADDR a privacy leak? [This comment](https://github.com/bitcoin/bitcoin/pull/19794#issuecomment-687476649) suggests it is, though I want to point out that the response would be split up (due to separate `RelayAddress` calls) among your peers unless you have few peers. The scenario mentioned in the linked comment could be more clear, I couldn't figure it out from reading it.\n\nAlso #19794 mentions if the GETADDR response is exactly 1000, the next ADDR message will not be relayed. This is to support other clients that send multiple ADDR messages in response. If a client sends the first part of the response with size 1000 and the next part with size <= 10, the second part will get relayed if the flag is removed. Don't know if this is a concern?"
  },
  {
   "t": "2026-04-22T18:29:41Z",
   "kind": "comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\nSo far, I haven\u2019t identified any privacy risks. From Aj\u2019s comment, this would only be an issue if we could distinguish whether it is from an inbound or outbound connection.\n\n[quoted text omitted]\nI don\u2019t think this self-announcement would benefit us much, However, other peers might benefit from it if they are not aware of the address or haven\u2019t heard about it recently, as it would allow them to update it. Simply receiving the address without relaying using it wouldn\u2019t be beneficial.\n\n[quoted text omitted]\nThis is my understanding of the initial privacy risk being discussed-> https://github.com/bitcoin/bitcoin/pull/19794#issuecomment-687476649. I\u2019m not 100% sure it exactly matches the original discussion, but I think this flow makes sense:\n\n- Node A just bootstrapped and has an empty AddrMan\n- Node A sends GETADDR to Node B\n- Node B responds with 9 addresses\n- Node A relays those 9 addresses to Node C\n- Node A adds those 9 addresses to its AddrMan\n\nAs a result, Node C can infer which peers Node A is likely to connect to next.\n\nSo, a potential solution to prevent this is the complete separation of getaddr messages and addr relay messages.\nThat way, there would be no possibility of relaying getaddr responses, which is what has been suggested here:\n[quoted text omitted]\n\nOverall, to me, this feels like the best long-term approach. Helps us avoid relying on heuristics that can be gamed or are difficult to verify, such as time and size, and instead provides a clearer separation of concerns with message types.\n\nAjs suggestions -> https://github.com/bitcoin/bitcoin/pull/34717#issuecomment-4013027535\n\n[quoted text omitted]\nI think this might be problematic for a small AddrMan.\nI also think this filtering could reduce the number of getaddr responses, especially when the AddrMan is small.\n\n[quoted text omitted]\nthis seems okay. I don\u2019t see any downsides, and I\u2019m fine with adding this to the PR.\n\nTaki's suggested having a separate bucket for getaddr -> https://github.com/bitcoin/bitcoin/pull/34717#issuecomment-4036510421\n\n[quoted text omitted]\nI haven\u2019t tested it yet, but  it could be a good solution.\n\nWhere I\u2019m currently at with this PR:\nI think it's safe to relay self-announcements.\nI am figuring out the best approach for separating getaddr and addr relay.\nI am also considering Aj\u2019s and Taki\u2019s solutions and testing each one"
  },
  {
   "t": "2026-04-24T14:54:34Z",
   "kind": "comment",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nThe only thing I can think of is that the timestamp of the self-announcement for the node sending GETADDR might be earlier than the other side's timestamp for their self-announcement. If I'm right, to distinguish though, you'd need to be relayed both self-announcements.\n\n[quoted text omitted]\nMy point here (mentioned by @ajtowns above), that I didn't elaborate on, was that eventually the rest of the network would hear about it if our self-announcement is broadcast about once a day.\n\n[quoted text omitted]\nI think this assumes that C is the only other peer that A has? If A had more peers, the repeated calls to `RelayAddress` would split up the relay among A's peers.\n\nI think both separate messages types and inflating the age make sense. I can't think of any hidden gotchas with inflating the age past the relay cut-off."
  },
  {
   "t": "2026-05-06T11:00:05Z",
   "kind": "comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nYes, the only way I can see this being a real issue is an extreme edge case,  where addrman is very small, and we have very few peers. Outside of that, it's hard to see how the privacy leak materializes."
  },
  {
   "t": "2026-05-06T12:07:42Z",
   "kind": "comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nI think I understand this now.\nIt\u2019s possible that this getaddr self-announcement will always have a fresher/newer timestamp. I think that, in addition to both being relayed to the same peer, timing may also matter. It has to happen within the same 24 hours; otherwise, the other self-announcement might sometimes have a newer timestamp."
  },
  {
   "t": "2026-07-04T09:52:14Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "I'm a bit confused what the status here is. Is this just waiting for some final review, or is there need for further discussion about potential privacy leakage?"
  },
  {
   "t": "2026-07-08T14:39:13Z",
   "kind": "comment",
   "who": "naiyoma",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\nthere are two concerns that need more discussion.\n\nInitial Self-Announcement Relay Privacy\n\nIt may be possible for an attacker to observe self-announcements and use timestamps to determine that fresher timestamps correspond to a direct outbound connection. This is not something I have personally observed. Maybe we can keep this flag and change its purpose to suppress relaying the initial self-announcement?\n\nBut what do we do with this initial self-announcement? If we are not relaying it, then why are we receiving it?\n\nGETADDR Relay\n\nWe do not want to relay a GETADDR response. In practice, this is unlikely to happen to us.\nHowever, if a peer has a very small addrman and only a few peers, then this can happen. Keeping this flag does not prevent it unless the outbound peer does not send us a self-announcement first.\nWhat happens if there are clients that split their GETADDR responses into multiple ADDR messages?\nIn that case, the flag might still be helpful by preventing us from relaying the second ADDR message. However, the way I see it, clients that split their GETADDR responses may split them into more than two messages.\nFor example, a client could split the response across four ADDR messages. In that case, even with the flag, we would eventually end up relaying part of the response anyway."
  },
  {
   "t": "2026-09-17T11:40:49Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "@mzumsande @Crypt-iQ @stratospher can you take another look here and the comment that naiyoma left above?"
  }
 ],
 "labels_log": [
  {
   "t": "2026-03-03T12:04:41Z",
   "action": "labeled",
   "label": "P2P",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-12T16:35:38Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-17T12:22:30Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-17T13:23:08Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-17T15:32:34Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-20T10:55:16Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-26T11:08:49Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2026-03-06T10:25:12Z",
   "kind": "milestoned",
   "who": "fanquake"
  },
  {
   "t": "2026-03-09T16:45:35Z",
   "kind": "demilestoned",
   "who": "fanquake"
  }
 ],
 "text_chars": 28126,
 "text_tokens_estimate": 7031,
 "changed_paths": [
  "src/net_processing.cpp",
  "test/functional/p2p_addr_relay.py"
 ],
 "files": [
  {
   "path": "src/net_processing.cpp",
   "add": 1,
   "del": 5
  },
  {
   "path": "test/functional/p2p_addr_relay.py",
   "add": 0,
   "del": 8
  }
 ],
 "test_lines": 8,
 "git": {
  "head": "c8ee319fffa1b7674fad3a797cd6d5110435a74c",
  "head_matches_backup": true,
  "base": "99f99c989e737cae003cbf848196a70ab472f8bc",
  "commits": [
   {
    "sha": "a1ecda2609",
    "subject": "test: delete redundant addr relay assertion",
    "files": 1,
    "add": 0,
    "del": 7
   },
   {
    "sha": "c8ee319fff",
    "subject": "net: remove m_getaddr_sent",
    "files": 2,
    "add": 2,
    "del": 7
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "a06aa902a6d4844a",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}