net: repair DragonX peer discovery, broken three separate ways
A DRAGONX node had no working peer discovery. Both mechanisms were broken, and a third bug hid the fact. 1. DNS seeds were Hush's, and all three are dead. chainparams_commandline() sets an assetchain's port, magic, blocktime, upgrade heights and checkpoints but never touches vSeeds or vFixedSeeds, so DRAGONX silently inherited CMainParams': seed1.hush.is, seed2.hush.is and dns.leto.net. None of the three has an A record any more -- verified against 1.1.1.1 and 8.8.8.8, with google.com and node1..node5.dragonx.is resolving fine from the same host as a control. Replaced with the five DragonX node hostnames, which do resolve and do listen. 2. Every fixed seed carried port 0. contrib/seeds/generate-seeds.py documents its input as <ip>:<port>, but contrib/seeds/nodes_main.txt held bare IPs, so parse_spec() took the port as empty and emitted 0x00,0x00 for all five entries. The fixed-seed fallback -- which exists precisely for when DNS seeding yields nothing -- was therefore handing out unconnectable addresses. Added the port to nodes_main.txt and regenerated; entries now end 0x55,0x08 (21768). 3. ThreadDNSAddressSeed never incremented `found`, so "%d addresses found from DNS seeds" printed 0 unconditionally, whether seeding worked or not. That is almost certainly why nobody noticed the seeds had gone dead: the one diagnostic that would have shown it was hardcoded to say zero. Verified on a fresh datadir (empty addrman, separate ports, real node untouched): DNS seeding now reports "5 addresses found from DNS seeds" where it previously reported 0, and the fixed-seed path adds 5 entries carrying the correct port. Note on scope: the five hostnames are single-A-record hosts, so each contributes one address rather than the spread a real seeder returns. A dedicated DNS seeder, or simply a round-robin A record over the seed set, would be the proper fix and needs only a DNS change rather than a release. This restores a working discovery path; it does not make it a good one. Also corrected the generated header's #endif comment, which said HUSH_CHAINPARAMSSEEDS_H while the guard is DRAGONX_CHAINPARAMSSEEDS_H. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -177,7 +177,7 @@ def main():
|
|||||||
g.write('\n')
|
g.write('\n')
|
||||||
with open(os.path.join(indir,'nodes_test.txt'), 'r', encoding="utf8") as f:
|
with open(os.path.join(indir,'nodes_test.txt'), 'r', encoding="utf8") as f:
|
||||||
process_nodes(g, f, 'chainparams_seed_test')
|
process_nodes(g, f, 'chainparams_seed_test')
|
||||||
g.write('#endif // HUSH_CHAINPARAMSSEEDS_H\n')
|
g.write('#endif // DRAGONX_CHAINPARAMSSEEDS_H\n')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
|
# generate-seeds.py expects <ip>:<port> (see its docstring). Without the port it
|
||||||
|
# emits 0, and every fixed seed becomes unconnectable -- which is what shipped:
|
||||||
|
# the whole chainparams_seed_main array carried 0x00,0x00 as the port.
|
||||||
# node1.dragonx.is
|
# node1.dragonx.is
|
||||||
212.56.41.63
|
212.56.41.63:21768
|
||||||
|
|
||||||
# node2.dragonx.is
|
# node2.dragonx.is
|
||||||
194.140.198.176
|
194.140.198.176:21768
|
||||||
|
|
||||||
# node3.dragonx.is
|
# node3.dragonx.is
|
||||||
212.56.41.47
|
212.56.41.47:21768
|
||||||
|
|
||||||
# node4.dragonx.is
|
# node4.dragonx.is
|
||||||
144.126.147.165
|
144.126.147.165:21768
|
||||||
|
|
||||||
# node5.dragonx.is
|
# node5.dragonx.is
|
||||||
176.126.87.241
|
176.126.87.241:21768
|
||||||
|
|||||||
@@ -181,11 +181,25 @@ public:
|
|||||||
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
|
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
|
||||||
vFixedSeeds.clear();
|
vFixedSeeds.clear();
|
||||||
vSeeds.clear();
|
vSeeds.clear();
|
||||||
// Hush Official DNS Seeds
|
// DragonX DNS seeds. These must be names that actually resolve.
|
||||||
vSeeds.push_back(CDNSSeedData("node1", "seed1.hush.is"));
|
//
|
||||||
vSeeds.push_back(CDNSSeedData("node2", "seed2.hush.is"));
|
// An assetchain INHERITS these: chainparams_commandline() sets the port, magic,
|
||||||
// Community run DNS Seeds
|
// blocktime, upgrade heights and checkpoints, but never touches vSeeds or
|
||||||
vSeeds.push_back(CDNSSeedData("node3", "dns.leto.net"));
|
// vFixedSeeds. DRAGONX therefore ran on Hush's seeds -- seed1.hush.is,
|
||||||
|
// seed2.hush.is and dns.leto.net -- and all three have no A records left, so DNS
|
||||||
|
// seeding silently returned zero addresses on every start. The only bootstrap
|
||||||
|
// 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.
|
||||||
|
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);
|
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,60);
|
||||||
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,85);
|
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,85);
|
||||||
|
|||||||
@@ -11,14 +11,14 @@
|
|||||||
// Each line contains a BIP155 serialized address.
|
// Each line contains a BIP155 serialized address.
|
||||||
//
|
//
|
||||||
static const uint8_t chainparams_seed_main[] = {
|
static const uint8_t chainparams_seed_main[] = {
|
||||||
0x01,0x04,0xd4,0x38,0x29,0x3f,0x00,0x00, // 212.56.41.63
|
0x01,0x04,0xd4,0x38,0x29,0x3f,0x55,0x08, // 212.56.41.63:21768
|
||||||
0x01,0x04,0xc2,0x8c,0xc6,0xb0,0x00,0x00, // 194.140.198.176
|
0x01,0x04,0xc2,0x8c,0xc6,0xb0,0x55,0x08, // 194.140.198.176:21768
|
||||||
0x01,0x04,0xd4,0x38,0x29,0x2f,0x00,0x00, // 212.56.41.47
|
0x01,0x04,0xd4,0x38,0x29,0x2f,0x55,0x08, // 212.56.41.47:21768
|
||||||
0x01,0x04,0x90,0x7e,0x93,0xa5,0x00,0x00, // 144.126.147.165
|
0x01,0x04,0x90,0x7e,0x93,0xa5,0x55,0x08, // 144.126.147.165:21768
|
||||||
0x01,0x04,0xb0,0x7e,0x57,0xf1,0x00,0x00, // 176.126.87.241
|
0x01,0x04,0xb0,0x7e,0x57,0xf1,0x55,0x08, // 176.126.87.241:21768
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t chainparams_seed_test[] = {
|
static const uint8_t chainparams_seed_test[] = {
|
||||||
0x01,0x04,0x01,0x02,0x03,0x04,0x00,0x00, // 1.2.3.4
|
0x01,0x04,0x01,0x02,0x03,0x04,0x00,0x00, // 1.2.3.4
|
||||||
};
|
};
|
||||||
#endif // HUSH_CHAINPARAMSSEEDS_H
|
#endif // DRAGONX_CHAINPARAMSSEEDS_H
|
||||||
|
|||||||
@@ -1581,6 +1581,7 @@ void ThreadDNSAddressSeed()
|
|||||||
CAddress addr = CAddress(CService(ip, ASSETCHAINS_P2PPORT));
|
CAddress addr = CAddress(CService(ip, ASSETCHAINS_P2PPORT));
|
||||||
addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
|
addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
|
||||||
vAdd.push_back(addr);
|
vAdd.push_back(addr);
|
||||||
|
found++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: The seed name resolve may fail, yielding an IP of [::], which results in
|
// TODO: The seed name resolve may fail, yielding an IP of [::], which results in
|
||||||
|
|||||||
Reference in New Issue
Block a user