chaincfg: Introduce new type DNSSeed

DNSSeed defines a DNS Seed with a hostname and whether it supports
filtering by service flag bits.
This commit is contained in:
David Hill 2016-10-21 20:36:38 -04:00 committed by Dave Collins
parent 0d508e6522
commit f161d6b69e
3 changed files with 61 additions and 30 deletions

View file

@ -50,6 +50,16 @@ type Checkpoint struct {
Hash *chainhash.Hash Hash *chainhash.Hash
} }
// DNSSeed identifies a DNS seed.
type DNSSeed struct {
// Host defines the hostname of the seed.
Host string
// HasFiltering defines whether the seed supports filtering
// by service flags (wire.ServiceFlag).
HasFiltering bool
}
// Params defines a Bitcoin network by its parameters. These parameters may be // Params defines a Bitcoin network by its parameters. These parameters may be
// used by Bitcoin applications to differentiate networks as well as addresses // used by Bitcoin applications to differentiate networks as well as addresses
// and keys for one network from those intended for use on another network. // and keys for one network from those intended for use on another network.
@ -65,7 +75,7 @@ type Params struct {
// DNSSeeds defines a list of DNS seeds for the network that are used // DNSSeeds defines a list of DNS seeds for the network that are used
// as one method to discover peers. // as one method to discover peers.
DNSSeeds []string DNSSeeds []DNSSeed
// GenesisBlock defines the first block of the chain. // GenesisBlock defines the first block of the chain.
GenesisBlock *wire.MsgBlock GenesisBlock *wire.MsgBlock
@ -155,14 +165,14 @@ var MainNetParams = Params{
Name: "mainnet", Name: "mainnet",
Net: wire.MainNet, Net: wire.MainNet,
DefaultPort: "8333", DefaultPort: "8333",
DNSSeeds: []string{ DNSSeeds: []DNSSeed{
"seed.bitcoin.sipa.be", {"seed.bitcoin.sipa.be", true},
"dnsseed.bluematt.me", {"dnsseed.bluematt.me", true},
"dnsseed.bitcoin.dashjr.org", {"dnsseed.bitcoin.dashjr.org", false},
"seed.bitcoinstats.com", {"seed.bitcoinstats.com", true},
"seed.bitnodes.io", {"seed.bitnodes.io", false},
"bitseed.xf2.org", {"bitseed.xf2.org", false},
"seed.bitcoin.jonasschnelli.ch", {"seed.bitcoin.jonasschnelli.ch", true},
}, },
// Chain parameters // Chain parameters
@ -235,7 +245,7 @@ var RegressionNetParams = Params{
Name: "regtest", Name: "regtest",
Net: wire.TestNet, Net: wire.TestNet,
DefaultPort: "18444", DefaultPort: "18444",
DNSSeeds: []string{}, DNSSeeds: []DNSSeed{},
// Chain parameters // Chain parameters
GenesisBlock: &regTestGenesisBlock, GenesisBlock: &regTestGenesisBlock,
@ -288,10 +298,11 @@ var TestNet3Params = Params{
Name: "testnet3", Name: "testnet3",
Net: wire.TestNet3, Net: wire.TestNet3,
DefaultPort: "18333", DefaultPort: "18333",
DNSSeeds: []string{ DNSSeeds: []DNSSeed{
"testnet-seed.bitcoin.schildbach.de", {"testnet-seed.bitcoin.jonasschnelli.ch", true},
"testnet-seed.bitcoin.petertodd.org", {"testnet-seed.bitcoin.schildbach.de", false},
"testnet-seed.bluematt.me", {"seed.tbtc.petertodd.org", true},
{"testnet-seed.bluematt.me", false},
}, },
// Chain parameters // Chain parameters
@ -351,7 +362,7 @@ var SimNetParams = Params{
Name: "simnet", Name: "simnet",
Net: wire.SimNet, Net: wire.SimNet,
DefaultPort: "18555", DefaultPort: "18555",
DNSSeeds: []string{}, // NOTE: There must NOT be any seeds. DNSSeeds: []DNSSeed{}, // NOTE: There must NOT be any seeds.
// Chain parameters // Chain parameters
GenesisBlock: &simNetGenesisBlock, GenesisBlock: &simNetGenesisBlock,
@ -416,6 +427,11 @@ var (
hdPrivToPubKeyIDs = make(map[[4]byte][]byte) hdPrivToPubKeyIDs = make(map[[4]byte][]byte)
) )
// String returns the hostname of the DNS seed in human-readable form.
func (d DNSSeed) String() string {
return d.Host
}
// Register registers the network parameters for a Bitcoin network. This may // Register registers the network parameters for a Bitcoin network. This may
// error with ErrDuplicateNet if the network is already registered (either // error with ErrDuplicateNet if the network is already registered (either
// due to a previous Register call, or the network being one of the default // due to a previous Register call, or the network being one of the default

View file

@ -5,6 +5,7 @@
package connmgr package connmgr
import ( import (
"fmt"
mrand "math/rand" mrand "math/rand"
"net" "net"
"strconv" "strconv"
@ -29,19 +30,28 @@ type OnSeed func(addrs []*wire.NetAddress)
type LookupFunc func(string) ([]net.IP, error) type LookupFunc func(string) ([]net.IP, error)
// SeedFromDNS uses DNS seeding to populate the address manager with peers. // SeedFromDNS uses DNS seeding to populate the address manager with peers.
func SeedFromDNS(chainParams *chaincfg.Params, lookupFn LookupFunc, seedFn OnSeed) { func SeedFromDNS(chainParams *chaincfg.Params, reqServices wire.ServiceFlag,
for _, seeder := range chainParams.DNSSeeds { lookupFn LookupFunc, seedFn OnSeed) {
go func(seeder string) {
for _, dnsseed := range chainParams.DNSSeeds {
var host string
if !dnsseed.HasFiltering || reqServices == wire.SFNodeNetwork {
host = dnsseed.Host
} else {
host = fmt.Sprintf("x%x.%s", uint64(reqServices), dnsseed.Host)
}
go func(host string) {
randSource := mrand.New(mrand.NewSource(time.Now().UnixNano())) randSource := mrand.New(mrand.NewSource(time.Now().UnixNano()))
seedpeers, err := lookupFn(seeder) seedpeers, err := lookupFn(host)
if err != nil { if err != nil {
log.Infof("DNS discovery failed on seed %s: %v", seeder, err) log.Infof("DNS discovery failed on seed %s: %v", host, err)
return return
} }
numPeers := len(seedpeers) numPeers := len(seedpeers)
log.Infof("%d addresses found from DNS seed %s", numPeers, seeder) log.Infof("%d addresses found from DNS seed %s", numPeers, host)
if numPeers == 0 { if numPeers == 0 {
return return
@ -61,6 +71,6 @@ func SeedFromDNS(chainParams *chaincfg.Params, lookupFn LookupFunc, seedFn OnSee
} }
seedFn(addresses) seedFn(addresses)
}(seeder) }(host)
} }
} }

View file

@ -40,6 +40,10 @@ const (
// the server. // the server.
defaultServices = wire.SFNodeNetwork | wire.SFNodeBloom defaultServices = wire.SFNodeNetwork | wire.SFNodeBloom
// defaultRequiredServices describes the default services that are
// required to be supported by outbound peers.
defaultRequiredServices = wire.SFNodeNetwork
// defaultMaxOutbound is the default number of max outbound peers. // defaultMaxOutbound is the default number of max outbound peers.
defaultMaxOutbound = 8 defaultMaxOutbound = 8
@ -1627,14 +1631,15 @@ func (s *server) peerHandler() {
if !cfg.DisableDNSSeed { if !cfg.DisableDNSSeed {
// Add peers discovered through DNS to the address manager. // Add peers discovered through DNS to the address manager.
connmgr.SeedFromDNS(activeNetParams.Params, btcdLookup, func(addrs []*wire.NetAddress) { connmgr.SeedFromDNS(activeNetParams.Params, defaultRequiredServices,
// Bitcoind uses a lookup of the dns seeder here. This btcdLookup, func(addrs []*wire.NetAddress) {
// is rather strange since the values looked up by the // Bitcoind uses a lookup of the dns seeder here. This
// DNS seed lookups will vary quite a lot. // is rather strange since the values looked up by the
// to replicate this behaviour we put all addresses as // DNS seed lookups will vary quite a lot.
// having come from the first one. // to replicate this behaviour we put all addresses as
s.addrManager.AddAddresses(addrs, addrs[0]) // having come from the first one.
}) s.addrManager.AddAddresses(addrs, addrs[0])
})
} }
go s.connManager.Start() go s.connManager.Start()