diff --git a/contrib/seeds/README.md b/contrib/seeds/README.md --- a/contrib/seeds/README.md +++ b/contrib/seeds/README.md @@ -4,7 +4,9 @@ (see [src/chainparamsseeds.h](/src/chainparamsseeds.h) and other utilities in [contrib/seeds](/contrib/seeds)). Be sure to update `PATTERN_AGENT` in `makeseeds.py` to include the current version, -and remove old versions as necessary. +and remove old versions as necessary (at a minimum when GetDesireableServiceFlags +changes its default return value, as those are the services which seeds are added +to addrman with). The seeds compiled into the release are created from sipa's DNS seed data, like this: diff --git a/src/chainparams.h b/src/chainparams.h --- a/src/chainparams.h +++ b/src/chainparams.h @@ -14,15 +14,6 @@ #include #include -struct CDNSSeedData { - std::string host; - bool supportsServiceBitsFiltering; - CDNSSeedData(const std::string &strHost, - bool supportsServiceBitsFilteringIn) - : host(strHost), - supportsServiceBitsFiltering(supportsServiceBitsFilteringIn) {} -}; - struct SeedSpec6 { uint8_t addr[16]; uint16_t port; @@ -77,7 +68,8 @@ bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } /** Return the BIP70 network string (main, test or regtest) */ std::string NetworkIDString() const { return strNetworkID; } - const std::vector &DNSSeeds() const { return vSeeds; } + /** Return the list of hostnames to look up for DNS seeds */ + const std::vector &DNSSeeds() const { return vSeeds; } const std::vector &Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } @@ -94,7 +86,7 @@ CMessageHeader::MessageMagic netMagic; int nDefaultPort; uint64_t nPruneAfterHeight; - std::vector vSeeds; + std::vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; std::string cashaddrPrefix; std::string strNetworkID; diff --git a/src/chainparams.cpp b/src/chainparams.cpp --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -160,20 +160,23 @@ uint256S("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b" "7afdeda33b")); - // Note that of those with the service bits flag, most only support a - // subset of possible options. + // Note that of those which support the service bits prefix, most only + // support a subset of possible options. This is fine at runtime as + // we'll fall back to using them as a oneshot if they dont support the + // service bits we want, but we should get them updated to support all + // service bits wanted by any release ASAP to avoid it where possible. // Bitcoin ABC seeder - vSeeds.emplace_back("seed.bitcoinabc.org", true); + vSeeds.emplace_back("seed.bitcoinabc.org"); // bitcoinforks seeders - vSeeds.emplace_back("seed-abc.bitcoinforks.org", true); + vSeeds.emplace_back("seed-abc.bitcoinforks.org"); // BU backed seeder - vSeeds.emplace_back("btccash-seeder.bitcoinunlimited.info", true); + vSeeds.emplace_back("btccash-seeder.bitcoinunlimited.info"); // Bitprim - vSeeds.emplace_back("seed.bitprim.org", true); + vSeeds.emplace_back("seed.bitprim.org"); // Amaury SÉCHET - vSeeds.emplace_back("seed.deadalnix.me", true); + vSeeds.emplace_back("seed.deadalnix.me"); // criptolayer.net - vSeeds.emplace_back("seeder.criptolayer.net", true); + vSeeds.emplace_back("seeder.criptolayer.net"); base58Prefixes[PUBKEY_ADDRESS] = std::vector(1, 0); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1, 5); @@ -324,15 +327,15 @@ vSeeds.clear(); // nodes with support for servicebits filtering should be at the top // Bitcoin ABC seeder - vSeeds.emplace_back("testnet-seed.bitcoinabc.org", true); + vSeeds.emplace_back("testnet-seed.bitcoinabc.org"); // bitcoinforks seeders - vSeeds.emplace_back("testnet-seed-abc.bitcoinforks.org", true); + vSeeds.emplace_back("testnet-seed-abc.bitcoinforks.org"); // Bitprim - vSeeds.emplace_back("testnet-seed.bitprim.org", true); + vSeeds.emplace_back("testnet-seed.bitprim.org"); // Amaury SÉCHET - vSeeds.emplace_back("testnet-seed.deadalnix.me", true); + vSeeds.emplace_back("testnet-seed.deadalnix.me"); // criptolayer.net - vSeeds.emplace_back("testnet-seeder.criptolayer.net", true); + vSeeds.emplace_back("testnet-seeder.criptolayer.net"); base58Prefixes[PUBKEY_ADDRESS] = std::vector(1, 111); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1, 196); diff --git a/src/net.cpp b/src/net.cpp --- a/src/net.cpp +++ b/src/net.cpp @@ -140,7 +140,8 @@ for (const auto &seed_in : vSeedsIn) { struct in6_addr ip; memcpy(&ip, seed_in.addr, sizeof(ip)); - CAddress addr(CService(ip, seed_in.port), NODE_NETWORK); + CAddress addr(CService(ip, seed_in.port), + GetDesirableServiceFlags(NODE_NONE)); addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek; vSeedsOut.push_back(addr); } @@ -1674,21 +1675,6 @@ } #endif -static std::string GetDNSHost(const CDNSSeedData &data, - ServiceFlags *requiredServiceBits) { - // use default host for non-filter-capable seeds or if we use the default - // service bits (NODE_NETWORK) - if (!data.supportsServiceBitsFiltering || - *requiredServiceBits == NODE_NETWORK) { - *requiredServiceBits = NODE_NETWORK; - return data.host; - } - - // See chainparams.cpp, most dnsseeds only support one or two possible - // servicebits hostnames - return strprintf("x%x.%s", *requiredServiceBits, data.host); -} - void CConnman::ThreadDNSAddressSeed() { // goal: only query DNS seeds if address need is acute. // Avoiding DNS seeds when we don't need them improves user privacy by @@ -1713,21 +1699,24 @@ } } - const std::vector &vSeeds = + const std::vector &vSeeds = config->GetChainParams().DNSSeeds(); int found = 0; LogPrintf("Loading addresses from DNS seeds (could take a while)\n"); - for (const CDNSSeedData &seed : vSeeds) { + for (const std::string &seed : vSeeds) { + if (interruptNet) { + return; + } if (HaveNameProxy()) { - AddOneShot(seed.host); + AddOneShot(seed); } else { std::vector vIPs; std::vector vAdd; ServiceFlags requiredServiceBits = GetDesirableServiceFlags(NODE_NONE); - std::string host = GetDNSHost(seed, &requiredServiceBits); + std::string host = strprintf("x%x.%s", requiredServiceBits, seed); CNetAddr resolveSource; if (!resolveSource.SetInternal(host)) { continue; @@ -1744,6 +1733,11 @@ found++; } addrman.Add(vAdd, resolveSource); + } else { + // We now avoid directly using results from DNS Seeds which do + // not support service bit filtering, instead using them as a + // oneshot to get nodes with our desired service bits. + AddOneShot(seed); } } } diff --git a/src/protocol.h b/src/protocol.h --- a/src/protocol.h +++ b/src/protocol.h @@ -318,7 +318,15 @@ * unless they set NODE_NETWORK_LIMITED and we are out of IBD, in which * case NODE_NETWORK_LIMITED suffices). * - * Thus, generally, avoid calling with peerServices == NODE_NONE. + * Thus, generally, avoid calling with peerServices == NODE_NONE, unless + * state-specific flags must absolutely be avoided. When called with + * peerServices == NODE_NONE, the returned desirable service flags are + * guaranteed to not change dependant on state - ie they are suitable for + * use when describing peers which we know to be desirable, but for which + * we do not have a confirmed set of service flags. + * + * If the NODE_NONE return value is changed, contrib/seeds/makeseeds.py + * should be updated appropriately to filter for the same nodes. */ static ServiceFlags GetDesirableServiceFlags(ServiceFlags services) { return ServiceFlags(NODE_NETWORK);