net: seed from a round-robin DNS record instead of hardcoded hosts

seed.dragonx.is is now an A-record set over the five seed nodes (DNS-only, TTL 300,
created in Cloudflare alongside this change). One lookup returns all of them, and
the set can change -- a node added, a node retired -- with a DNS edit rather than a
release.

That is the actual point. Before this the network's entry points were hardcoded
into the binary twice over: here in vSeeds, and again in the -addnode injection in
hush_utils.h. Adding a sixth node meant shipping a new version and waiting for
users to upgrade.

node1 and node5 stay as static fallbacks against the round-robin record being
mistyped or deleted. They resolve to the same hosts, so that is insurance against a
DNS mistake rather than real redundancy.

Verified end to end on a fresh datadir (empty addrman, real node untouched, and
crucially with NO custom -port -- see below):

  before:  0 addresses found from DNS seeds, 0 handshakes, 1 block (genesis)
  after:   7 addresses found, connection attempts to all five seeds on :21768,
           3 version handshakes, 3296 blocks connected and syncing

The earlier run of this test appeared to fail with 0 handshakes. That was the
harness, not the code: -port overrides ASSETCHAINS_P2PPORT, and net.cpp builds
DNS-seeded addresses as CAddress(CService(ip, ASSETCHAINS_P2PPORT)), so a test node
with a custom port dials every seeded peer on its own port and reaches nothing.
That is the mechanism behind the long-standing "never use a custom -port on a test
node" rule; use -listen=0 instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-26 00:22:56 +02:00
parent 499f02a905
commit dde6cd810f

View File

@@ -191,14 +191,18 @@ public:
// path that worked was the node1..node5.dragonx.is -addnode injection in
// hush_utils.h, which is almost certainly why that injection exists.
//
// These are single-A-record hosts, so each contributes one address rather than
// the spread a real seeder returns. That is still strictly better than nothing;
// a dedicated seeder (or a round-robin A record over the seed set) would be the
// proper fix and needs only a DNS change, not a release.
// seed.dragonx.is is a round-robin A record over the seed set, so ONE lookup
// returns all of them and the set can be changed -- a node added, a node retired
// -- with a DNS edit instead of a release. That is the point of it: the previous
// arrangement hardcoded the seed list into the binary twice over (here and in the
// -addnode injection in hush_utils.h), so the network's entry points could only
// change by shipping a new version.
//
// node1/node5 stay as static fallbacks in case the round-robin record is ever
// mistyped or removed. They are the same hosts, so this is insurance against a
// DNS mistake rather than genuine redundancy.
vSeeds.push_back(CDNSSeedData("seed", "seed.dragonx.is"));
vSeeds.push_back(CDNSSeedData("node1", "node1.dragonx.is"));
vSeeds.push_back(CDNSSeedData("node2", "node2.dragonx.is"));
vSeeds.push_back(CDNSSeedData("node3", "node3.dragonx.is"));
vSeeds.push_back(CDNSSeedData("node4", "node4.dragonx.is"));
vSeeds.push_back(CDNSSeedData("node5", "node5.dragonx.is"));
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,60);