Skip to content

Commit

Permalink
chaincfg: Introduce new type DNSSeed
Browse files Browse the repository at this point in the history
DNSSeed defines a DNS Seed with a hostname and whether it supports
filtering by service flag bits.
  • Loading branch information
dajohi authored and davecgh committed Oct 23, 2016
1 parent 0d508e6 commit f161d6b
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 30 deletions.
46 changes: 31 additions & 15 deletions chaincfg/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ type Checkpoint struct {
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
// used by Bitcoin applications to differentiate networks as well as addresses
// and keys for one network from those intended for use on another network.
Expand All @@ -65,7 +75,7 @@ type Params struct {

// DNSSeeds defines a list of DNS seeds for the network that are used
// as one method to discover peers.
DNSSeeds []string
DNSSeeds []DNSSeed

// GenesisBlock defines the first block of the chain.
GenesisBlock *wire.MsgBlock
Expand Down Expand Up @@ -155,14 +165,14 @@ var MainNetParams = Params{
Name: "mainnet",
Net: wire.MainNet,
DefaultPort: "8333",
DNSSeeds: []string{
"seed.bitcoin.sipa.be",
"dnsseed.bluematt.me",
"dnsseed.bitcoin.dashjr.org",
"seed.bitcoinstats.com",
"seed.bitnodes.io",
"bitseed.xf2.org",
"seed.bitcoin.jonasschnelli.ch",
DNSSeeds: []DNSSeed{
{"seed.bitcoin.sipa.be", true},
{"dnsseed.bluematt.me", true},
{"dnsseed.bitcoin.dashjr.org", false},
{"seed.bitcoinstats.com", true},
{"seed.bitnodes.io", false},
{"bitseed.xf2.org", false},
{"seed.bitcoin.jonasschnelli.ch", true},
},

// Chain parameters
Expand Down Expand Up @@ -235,7 +245,7 @@ var RegressionNetParams = Params{
Name: "regtest",
Net: wire.TestNet,
DefaultPort: "18444",
DNSSeeds: []string{},
DNSSeeds: []DNSSeed{},

// Chain parameters
GenesisBlock: &regTestGenesisBlock,
Expand Down Expand Up @@ -288,10 +298,11 @@ var TestNet3Params = Params{
Name: "testnet3",
Net: wire.TestNet3,
DefaultPort: "18333",
DNSSeeds: []string{
"testnet-seed.bitcoin.schildbach.de",
"testnet-seed.bitcoin.petertodd.org",
"testnet-seed.bluematt.me",
DNSSeeds: []DNSSeed{
{"testnet-seed.bitcoin.jonasschnelli.ch", true},
{"testnet-seed.bitcoin.schildbach.de", false},
{"seed.tbtc.petertodd.org", true},
{"testnet-seed.bluematt.me", false},
},

// Chain parameters
Expand Down Expand Up @@ -351,7 +362,7 @@ var SimNetParams = Params{
Name: "simnet",
Net: wire.SimNet,
DefaultPort: "18555",
DNSSeeds: []string{}, // NOTE: There must NOT be any seeds.
DNSSeeds: []DNSSeed{}, // NOTE: There must NOT be any seeds.

// Chain parameters
GenesisBlock: &simNetGenesisBlock,
Expand Down Expand Up @@ -416,6 +427,11 @@ var (
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
// error with ErrDuplicateNet if the network is already registered (either
// due to a previous Register call, or the network being one of the default
Expand Down
24 changes: 17 additions & 7 deletions connmgr/seed.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package connmgr

import (
"fmt"
mrand "math/rand"
"net"
"strconv"
Expand All @@ -29,19 +30,28 @@ type OnSeed func(addrs []*wire.NetAddress)
type LookupFunc func(string) ([]net.IP, error)

// SeedFromDNS uses DNS seeding to populate the address manager with peers.
func SeedFromDNS(chainParams *chaincfg.Params, lookupFn LookupFunc, seedFn OnSeed) {
for _, seeder := range chainParams.DNSSeeds {
go func(seeder string) {
func SeedFromDNS(chainParams *chaincfg.Params, reqServices wire.ServiceFlag,
lookupFn LookupFunc, seedFn OnSeed) {

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()))

seedpeers, err := lookupFn(seeder)
seedpeers, err := lookupFn(host)
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
}
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 {
return
Expand All @@ -61,6 +71,6 @@ func SeedFromDNS(chainParams *chaincfg.Params, lookupFn LookupFunc, seedFn OnSee
}

seedFn(addresses)
}(seeder)
}(host)
}
}
21 changes: 13 additions & 8 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ const (
// the server.
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 = 8

Expand Down Expand Up @@ -1627,14 +1631,15 @@ func (s *server) peerHandler() {

if !cfg.DisableDNSSeed {
// Add peers discovered through DNS to the address manager.
connmgr.SeedFromDNS(activeNetParams.Params, btcdLookup, func(addrs []*wire.NetAddress) {
// Bitcoind uses a lookup of the dns seeder here. This
// is rather strange since the values looked up by the
// DNS seed lookups will vary quite a lot.
// to replicate this behaviour we put all addresses as
// having come from the first one.
s.addrManager.AddAddresses(addrs, addrs[0])
})
connmgr.SeedFromDNS(activeNetParams.Params, defaultRequiredServices,
btcdLookup, func(addrs []*wire.NetAddress) {
// Bitcoind uses a lookup of the dns seeder here. This
// is rather strange since the values looked up by the
// DNS seed lookups will vary quite a lot.
// to replicate this behaviour we put all addresses as
// having come from the first one.
s.addrManager.AddAddresses(addrs, addrs[0])
})
}
go s.connManager.Start()

Expand Down

0 comments on commit f161d6b

Please sign in to comment.