diff --git a/README.md b/README.md index 5879620..e54507d 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,16 @@ # Zcash DNS seeder -This is a CoreDNS plugin that scrapes addresses of peers from a Zcash network. It's intended as a safer, more configurable, and more scalable replacement for the [zcash-seeder](https://github.com/zcash/zcash-seeder) project. +This is a CoreDNS plugin that scrapes addresses of peers from a Zcash network +and returns them on A or AAAA queries. It's intended as a safer, more configurable, and more scalable +replacement for the [zcash-seeder](https://github.com/zcash/zcash-seeder) project. It's written in Go and uses [btcsuite](https://github.com/btcsuite) for low-level networking. +It works by connecting to a list of bootstrap peers and requesting new peers by sending `getaddr` +messages. The process is then periodically repeated with the current list of known peers. +This plugin accepts both `addr` and `addrv2` messages, though it ignores addresses that are not +IPv4 nor IPv6. It does not answer `getaddr` requests from other peers. + ## Build instructions This code cannot be used independently of CoreDNS. See [coredns-zcash](https://github.com/ZcashFoundation/coredns-zcash) for instructions. diff --git a/go.mod b/go.mod index da155e7..4892654 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/zcashfoundation/dnsseeder go 1.14 require ( - github.com/btcsuite/btcd v0.20.1-beta + github.com/btcsuite/btcd v0.22.0-beta github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/caddyserver/caddy v1.0.5 github.com/coredns/coredns v1.6.9 @@ -11,4 +11,5 @@ require ( github.com/pkg/errors v0.9.1 ) -replace github.com/btcsuite/btcd => github.com/gtank/btcd v0.0.0-20191012142736-b43c61a68604 +// Currently pointing to "main-zfnd" branch +replace github.com/btcsuite/btcd => github.com/ZcashFoundation/btcd v0.22.0-beta.0.20211118133831-ca5d3008dd64 diff --git a/go.sum b/go.sum index ee32d0a..b5c73d0 100644 --- a/go.sum +++ b/go.sum @@ -41,6 +41,8 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/sarama v1.21.0/go.mod h1:yuqtN/pe8cXRWG5zPaO7hCfNJp5MwmkoJEoLjkm5tCQ= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/ZcashFoundation/btcd v0.22.0-beta.0.20211118133831-ca5d3008dd64 h1:G6N+0l3XFLEMFfqWmjsnM0/x8TRgAijitcquCMB2tJU= +github.com/ZcashFoundation/btcd v0.22.0-beta.0.20211118133831-ca5d3008dd64/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k= github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE= @@ -62,14 +64,14 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/caddyserver/caddy v1.0.5 h1:5B1Hs0UF2x2tggr2X9jL2qOZtDXbIWQb9YLbmlxHSuM= @@ -95,11 +97,12 @@ github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMEl github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g= +github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= @@ -201,8 +204,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= -github.com/gtank/btcd v0.0.0-20191012142736-b43c61a68604 h1:UDj89D6y8vk+FqosmIp0KTsbQmikX+AMMVQdARP4MzI= -github.com/gtank/btcd v0.0.0-20191012142736-b43c61a68604/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -215,7 +216,7 @@ github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/infobloxopen/go-trees v0.0.0-20190313150506-2af4e13f9062/go.mod h1:PcNJqIlcX/dj3DTG/+QQnRvSgTMG6CLpRMjWcv4+J6w= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -291,6 +292,7 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -383,7 +385,6 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -396,8 +397,10 @@ golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -410,6 +413,7 @@ golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/zcash/client.go b/zcash/client.go index e0358da..1c4dd75 100644 --- a/zcash/client.go +++ b/zcash/client.go @@ -40,7 +40,7 @@ var defaultPeerConfig = &peer.Config{ // TODO: fork https://github.com/gtank/btcd/blob/master/peer/peer.go // and set MinAcceptableProtocolVersion based on the most recently activated network upgrade // see ticket #10 for details - ProtocolVersion: 170015, // Zcash NU5 testnet (second activation) + ProtocolVersion: 170017, // Zcash NU5 mainnet with addrv2 } var ( @@ -105,8 +105,15 @@ func NewSeeder(network network.Network) (*Seeder, error) { addrQueue: make(chan *wire.NetAddress, incomingAddressBufferSize), } + // The seeder only acts on verack, addr and addrv2 messages. + // verack is used to keep track of peers, while addr and addrv2 receives + // new addresses which are requested by the seeder periodically + // sending getaddr requests to peers (see `RequestAddresses`). newSeeder.config.Listeners.OnVerAck = newSeeder.onVerAck newSeeder.config.Listeners.OnAddr = newSeeder.onAddr + // Note that per ZIP-155 we should not receive addrv2 messages from pre-170017 + // peers, but we don't explicitly check for that. + newSeeder.config.Listeners.OnAddrV2 = newSeeder.onAddrV2 return &newSeeder, nil } @@ -136,6 +143,7 @@ func newTestSeeder(network network.Network) (*Seeder, error) { newSeeder.config.Listeners.OnVerAck = newSeeder.onVerAck newSeeder.config.Listeners.OnAddr = newSeeder.onAddr + newSeeder.config.Listeners.OnAddrV2 = newSeeder.onAddrV2 return &newSeeder, nil } @@ -350,9 +358,6 @@ func (s *Seeder) RequestAddresses() int { return } - // Note that AllowSelfConns is only exposed in a fork of btcd - // pending https://github.com/btcsuite/btcd/pull/1481, which - // is why the module `replace`s btcd. if !addrmgr.IsRoutable(na) && !s.config.AllowSelfConns { s.logger.Printf("Got bad addr %s:%d from peer %s", na.IP, na.Port, "") // TODO blacklist peers who give us crap addresses diff --git a/zcash/client_callbacks.go b/zcash/client_callbacks.go index ba2b44d..c67e2cb 100644 --- a/zcash/client_callbacks.go +++ b/zcash/client_callbacks.go @@ -61,3 +61,30 @@ func (s *Seeder) onAddr(p *peer.Peer, msg *wire.MsgAddr) { s.addrQueue <- na } } + +// onAddrV2 handles addrv2 messages. +// +// If the address is IPv4 or IPv6, it handles it the same way as an addr message. +// If other address type is received, the address is ignored. +func (s *Seeder) onAddrV2(p *peer.Peer, msg *wire.MsgAddrV2) { + if len(msg.AddrList) == 0 { + s.logger.Printf("Got empty addrv2 message from peer %s. Disconnecting.", p.Addr()) + s.DisconnectPeer(peerKeyFromPeer(p)) + return + } + + s.logger.Printf("Got %d addrv2s from peer %s", len(msg.AddrList), p.Addr()) + + for _, na := range msg.AddrList { + if na.NetworkID == wire.NIIPV4 || na.NetworkID == wire.NIIPV6 { + // By checking if we know them before adding to the queue, we create + // the end condition for the crawler thread: it will time out after + // not processing any new addresses. + if s.addrBook.IsKnown(peerKeyFromNAV2(na)) { + s.logger.Printf("Already knew about %s:%d", na.IP, na.Port) + continue + } + s.addrQueue <- &na.NetAddress + } + } +} diff --git a/zcash/client_test.go b/zcash/client_test.go index 6e9456e..7984375 100644 --- a/zcash/client_test.go +++ b/zcash/client_test.go @@ -5,6 +5,7 @@ import ( "net" "os" "sync" + "sync/atomic" "testing" "time" @@ -14,6 +15,10 @@ import ( "github.com/zcashfoundation/dnsseeder/zcash/network" ) +// useAddrV2 specifies if startMockLoop() should send addrv2 messages or regular addr. +// It's an uint32 since it's used with the atomic package. +var useAddrV2 uint32 + func TestMain(m *testing.M) { err := startMockLoop() if err != nil { @@ -39,8 +44,6 @@ func startMockLoop() error { peer.UseLogger(mockPeerLogger) config.Listeners.OnGetAddr = func(p *peer.Peer, msg *wire.MsgGetAddr) { - cache := make([]*wire.NetAddress, 0, 1) - // This will an unusable peer (testnet port) addr := wire.NewNetAddressTimestamp( time.Now(), @@ -65,10 +68,23 @@ func startMockLoop() error { uint16(12345), ) - cache = append(cache, addr, addr2, addr3) - _, err := p.PushAddrMsg(cache) - if err != nil { - mockPeerLogger.Error(err) + if atomic.LoadUint32(&useAddrV2) != 0 { + cache := make([]*wire.NetAddressV2, 0, 1) + addrv2_1 := wire.NewNetAddressV2NetAddress(addr) + addrv2_2 := wire.NewNetAddressV2NetAddress(addr2) + addrv2_3 := wire.NewNetAddressV2NetAddress(addr3) + cache = append(cache, addrv2_1, addrv2_2, addrv2_3) + _, err := p.PushAddrV2Msg(cache) + if err != nil { + mockPeerLogger.Error(err) + } + } else { + cache := make([]*wire.NetAddress, 0, 1) + cache = append(cache, addr, addr2, addr3) + _, err := p.PushAddrMsg(cache) + if err != nil { + mockPeerLogger.Error(err) + } } } @@ -207,6 +223,46 @@ func TestRequestAddresses(t *testing.T) { } } +func TestRequestAddressesV2(t *testing.T) { + atomic.StoreUint32(&useAddrV2, 1) + defer atomic.StoreUint32(&useAddrV2, 0) + + regSeeder, err := newTestSeeder(network.Regtest) + if err != nil { + t.Error(err) + return + } + + // Wrap the listener to allow checking it was called + originalFn := regSeeder.config.Listeners.OnAddrV2 + var receivedAddrV2 uint32 + regSeeder.config.Listeners.OnAddrV2 = func(p *peer.Peer, msg *wire.MsgAddrV2) { + atomic.StoreUint32(&receivedAddrV2, 1) + originalFn(p, msg) + } + + err = regSeeder.ConnectOnDefaultPort("127.0.0.1") + if err != nil { + t.Fatal(err) + } + + go regSeeder.RequestAddresses() + err = regSeeder.WaitForAddresses(1, 1*time.Second) + + if err != nil { + t.Errorf("Error getting one mocked address: %v", err) + } + + err = regSeeder.WaitForAddresses(500, 1*time.Second) + if err != ErrAddressTimeout { + t.Errorf("Should have timed out, instead got: %v", err) + } + + if atomic.LoadUint32(&receivedAddrV2) != 1 { + t.Error("OnAddrV2 was not called") + } +} + func TestBlacklist(t *testing.T) { regSeeder, err := newTestSeeder(network.Regtest) if err != nil { diff --git a/zcash/peer_map.go b/zcash/peer_map.go index 3876ddd..d2ff980 100644 --- a/zcash/peer_map.go +++ b/zcash/peer_map.go @@ -25,6 +25,11 @@ func peerKeyFromNA(na *wire.NetAddress) PeerKey { return PeerKey(net.JoinHostPort(na.IP.String(), portString)) } +func peerKeyFromNAV2(na *wire.NetAddressV2) PeerKey { + portString := strconv.Itoa(int(na.Port)) + return PeerKey(net.JoinHostPort(na.IP.String(), portString)) +} + // PeerMap is a typed wrapper for a sync.Map. Its keys are PeerKeys (host:port // format strings) and it stores a pointer to a btcsuite peer.Peer. type PeerMap struct {