From af55e865f8c2bd249123389d47c3cc67187e3784 Mon Sep 17 00:00:00 2001 From: Andrey Petrov Date: Tue, 22 Apr 2014 18:53:40 -0700 Subject: [PATCH] Default DNS seeding (broken for now, use --seed override). --- btc-crawl.go | 41 +++++++++++++++++++++++++++++++++-------- client.go | 6 +----- crawler.go | 6 ++---- seed.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 seed.go diff --git a/btc-crawl.go b/btc-crawl.go index 3b4b1e1..15cad86 100644 --- a/btc-crawl.go +++ b/btc-crawl.go @@ -1,21 +1,46 @@ package main import ( + "github.com/jessevdk/go-flags" "log" ) +// Taken from: https://github.com/bitcoin/bitcoin/blob/89d72f3d9b6e7ef051ad1439f266b809f348229b/src/chainparams.cpp#L143 +var defaultDnsSeeds = []string{ + "seed.bitcoin.sipa.be", + "dnsseed.bluematt.me", + "dnsseed.bitcoin.dashjr.org", + "seed.bitcoinstats.com", + "seed.bitnodes.io", + "bitseed.xf2.org", +} + +// TODO: Unhardcode these: +var userAgent string = "/btc-crawl:0.0.1" +var lastBlock int32 = 0 + +type Options struct { + Verbose []bool `short:"v" long:"verbose" description:"Show verbose logging."` + Seed []string `short:"s" long:"seed" description:"Override which seeds to use." default-mask:""` +} + func main() { // TODO: Parse args. - // TODO: Export to a reasonable format. - // TODO: Use proper logger for logging. - var seedNodes []string = []string{"85.214.251.25:8333", "62.75.216.13:8333"} - client := NewDefaultClient() - crawler := NewCrawler(client, seedNodes, 10) - - done, err := crawler.Start() + options := Options{} + _, err := flags.Parse(&options) if err != nil { log.Fatal(err) } - <-done + seedNodes := options.Seed + + // TODO: Export to a reasonable format. + // TODO: Use proper logger for logging. + if len(seedNodes) == 0 { + seedNodes = GetSeedsFromDNS(defaultDnsSeeds) + } + + client := NewClient(userAgent, lastBlock) + crawler := NewCrawler(client, seedNodes, 10) + crawler.Start() } diff --git a/client.go b/client.go index befd089..2a5972f 100644 --- a/client.go +++ b/client.go @@ -4,10 +4,6 @@ import ( "github.com/conformal/btcwire" ) -// TODO: Unhardcode these: -var userAgent string = "/btc-crawl:0.0.1" -var lastBlock int32 = 0 - type Client struct { btcnet btcwire.BitcoinNet // Bitcoin Network pver uint32 // Protocl Version @@ -15,7 +11,7 @@ type Client struct { lastBlock int32 } -func NewDefaultClient() *Client { +func NewClient(userAgent string, lastBlock int32) *Client { return &Client{ btcnet: btcwire.MainNet, pver: btcwire.ProtocolVersion, diff --git a/crawler.go b/crawler.go index 2cfcb6b..a099a58 100644 --- a/crawler.go +++ b/crawler.go @@ -115,8 +115,7 @@ func (c *Crawler) addAddress(address string) bool { return true } -func (c *Crawler) Start() (chan struct{}, error) { - done := make(chan struct{}, 1) +func (c *Crawler) Start() { numWorkers := 0 numGood := 0 @@ -159,8 +158,7 @@ func (c *Crawler) Start() (chan struct{}, error) { if len(c.queue) == 0 && numWorkers == 0 { log.Printf("Done.") - done <- struct{}{} - return done, nil + return } <-c.workers diff --git a/seed.go b/seed.go new file mode 100644 index 0000000..26ea31e --- /dev/null +++ b/seed.go @@ -0,0 +1,43 @@ +package main + +import ( + "github.com/conformal/btcwire" + "log" + "net" + "sync" +) + +func GetSeedsFromDNS(dnsSeeds []string) []string { + wait := sync.WaitGroup{} + results := make(chan []net.IP) + + for _, address := range dnsSeeds { + wait.Add(1) + go func() { + defer wait.Done() + ips, err := net.LookupIP(address) + if err != nil { + log.Printf("Failed to resolve %s: %v", address, err) + return + } + results <- ips + }() + } + + go func() { + wait.Wait() + close(results) + }() + + seeds := []string{} + for ips := range results { + for _, ip := range ips { + seeds = append(seeds, net.JoinHostPort(ip.String(), btcwire.MainPort)) + } + } + + log.Printf("Resolved %d seed nodes from %d DNS seeds.", len(seeds), len(dnsSeeds)) + + // Note that this will likely include duplicate seeds. The crawler deduplicates them. + return seeds +}