-
Notifications
You must be signed in to change notification settings - Fork 9
feat: collect addresses from connected peers #421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v0.42-dev
Are you sure you want to change the base?
Conversation
📝 WalkthroughWalkthroughThe address storage mechanism in the network module is refactored from a Vec to a HashMap, introducing timestamp validation and an eviction policy. Address discovery is enhanced through GetAddr requests, with legacy address formats converted and unified into the new storage system. Changes
Sequence DiagramsequenceDiagram
participant Self as Local Node
participant Peer as Peer Node
participant Handler as AddrV2 Handler
Self->>Peer: TCP Connect
Peer-->>Self: Connection Established
Self->>Peer: GetAddr Request
Peer-->>Self: Addr Response (Legacy or V2)
alt Legacy Format
Self->>Self: Convert Addr to AddrV2
end
Self->>Handler: Validate Timestamps
Handler->>Handler: Filter by ONE_WEEK & TEN_MINUTES
Handler->>Handler: Insert/Update HashMap<SocketAddr, AddrV2>
Handler->>Handler: Evict if exceeds MAX_ADDR_TO_STORE
Handler-->>Self: Updated Peer List
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them. |
1 similar comment
|
This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them. |
b2adf62 to
3de0075
Compare
This way from the beginning we only add new peers or update existing ones in instead of adding everything with a valid timestamp and then later in the flow drop all duplicates.
Makes sure we send `GetAddr` after handshake to request `Addr`/`AddrV2` messages and convert `Addr` messages to `AddrV2` if we receive them, which shouldn't really happen since we signal v2 support during the handshake.
With the current validation rules we drop most of the addresses while they still might be useful since it doesn't necessarily mean they are offline. We should still keep more addresses to have at least some addresses to try to connect to.
3de0075 to
11f6cce
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
dash-spv/src/network/addrv2.rs (1)
206-234:⚠️ Potential issue | 🟡 MinorTest comments are misleading — the "too old" message is actually valid by timestamp rules.
A 4-hour-old timestamp is well within the 1-week window, so it passes timestamp validation. It only gets skipped because the same
SocketAddr(127.0.0.1:9999) was already inserted with a fresher timestamp (now), so the dedup logic at Line 81 (existing.time >= msg.time) rejects it.The test passes for the right reason (HashMap dedup), but the comments claim the timestamp itself is invalid. This will confuse future readers. Consider either:
- Fixing the comments to explain the actual reason each message is accepted/rejected.
- Using distinct addresses per message so the test truly exercises timestamp filtering in isolation.
Option 2: Use distinct addresses to properly test timestamp filtering
let messages = vec![ // Valid: current time AddrV2Message { time: now, services: ServiceFlags::from(1), addr: AddrV2::Ipv4(ipv4_addr), - port: addr.port(), + port: 9999, }, - // Invalid: too old (4 hours ago) + // Valid timestamp (4h ago, within 1 week) but uses distinct port AddrV2Message { time: now.saturating_sub(14400), services: ServiceFlags::from(1), addr: AddrV2::Ipv4(ipv4_addr), - port: addr.port(), + port: 10000, }, - // Invalid: too far in future (20 minutes) + // Invalid: too far in future (20 minutes), distinct port AddrV2Message { time: now + 1200, services: ServiceFlags::from(1), addr: AddrV2::Ipv4(ipv4_addr), - port: addr.port(), + port: 10001, }, ]; handler.handle_addrv2(messages).await; - // Only the valid message should be stored + // Two valid messages stored (current + 4h old); the future one is rejected let known = handler.get_known_addresses().await; - assert_eq!(known.len(), 1); + assert_eq!(known.len(), 2);
🧹 Nitpick comments (1)
dash-spv/src/network/addrv2.rs (1)
70-70:now + TEN_MINUTEScould theoretically overflowu32.While not a practical concern until ~2106 (u32 epoch overflow), the code uses
saturating_subdefensively for the lower bound but plain addition for the upper bound. For symmetry and defensive coding:Proposed fix
- if msg.time < now.saturating_sub(ONE_WEEK) || msg.time > now + TEN_MINUTES { + if msg.time < now.saturating_sub(ONE_WEEK) || msg.time > now.saturating_add(TEN_MINUTES) {
We currently don't request any addresses from connected peers so we ever only end up with the 3 addresses we initially try to connect to from the DNS seed lookup. This PR fixes it by making sure we send a
GetAddrafter handshake and process the responses properly.See individual commits and their messages.
Based on:
Working towards closing:
Summary by CodeRabbit