Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[common] Filter seed by features supported. #59

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ impl<R: Reactor<Publisher>> Client<R> {
if config.protocol.connect.is_empty() && peers.is_empty() {
log::info!("Address book is empty. Trying DNS seeds..");
peers.seed(
network.seeds().iter().map(|s| (*s, network.port())),
network.seeds().iter().map(|s| (s.as_str(), network.port())),
Source::Dns,
)?;
peers.flush()?;
Expand Down
54 changes: 39 additions & 15 deletions common/src/network.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! Bitcoin peer network. Eg. *Mainnet*.
use std::vec;

use bitcoin::blockdata::block::{Block, BlockHeader};
use bitcoin::consensus::params::Params;
Expand Down Expand Up @@ -99,29 +100,52 @@ impl Network {
}
}

/// Return the flag generated by the composition of the service flags.
fn service_flags(&self, services: &[ServiceFlags]) -> String {
let combination: u64 = services.iter().map(|service| service.as_u64()).sum();
format!("x{:x}", combination)
}

/// DNS seeds. Used to bootstrap the client's address book.
pub fn seeds(&self) -> &[&str] {
match self {
Network::Mainnet => &[
"seed.bitcoin.sipa.be", // Pieter Wuille
"dnsseed.bluematt.me", // Matt Corallo
"dnsseed.bitcoin.dashjr.org", // Luke Dashjr
"seed.bitcoinstats.com", // Christian Decker
"seed.bitcoin.jonasschnelli.ch", // Jonas Schnelli
"seed.btc.petertodd.org", // Peter Todd
"seed.bitcoin.sprovoost.nl", // Sjors Provoost
"dnsseed.emzy.de", // Stephan Oeste
"seed.bitcoin.wiz.biz", // Jason Maurice
"seed.cloudhead.io", // Alexis Sellier
pub fn seeds(&self) -> Vec<String> {
let seed_list = match self {
Network::Mainnet => vec![
"seed.bitcoin.sipa.be", // Pieter Wuille
"dnsseed.bluematt.me", // Matt Corallo
"dnsseed.bitcoin.dashjr.org", // Luke Dashjr
"seed.bitcoinstats.com", // Christian Decker
// "seed.bitcoin.jonasschnelli.ch", // Jonas Schnelli
"seed.btc.petertodd.org", // Peter Todd
"seed.bitcoin.sprovoost.nl", // Sjors Provoost
"dnsseed.emzy.de", // Stephan Oeste
"seed.bitcoin.wiz.biz", // Jason Maurice
"seed.cloudhead.io", // Alexis Sellier
],
Network::Testnet => &[
Network::Testnet => vec![
"testnet-seed.bitcoin.jonasschnelli.ch",
"seed.tbtc.petertodd.org",
"seed.testnet.bitcoin.sprovoost.nl",
"testnet-seed.bluematt.me",
],
Network::Regtest => &[], // No seeds
Network::Regtest => vec![], // No seeds
};

// We index this array by a step = 2, so
// each new seed has the following rules
// index i: Contains the dns with service flag
// index i + 1 Contains the pure dns without service flag
// the step size it is the number of feature typology supported
// in this case are 2, because we support ANY, and NETWORK + COMPACT_FILTERS
let mut feature_seeds = Vec::new();
let flag = self.service_flags(&[ServiceFlags::NETWORK, ServiceFlags::COMPACT_FILTERS]);
for seed in seed_list.iter() {
// Adding dns seed with service flag
let feature_seed = format!("{}.{}", flag, seed);
feature_seeds.push(feature_seed);
// Adding dns seed without service flag
feature_seeds.push(seed.to_string());
}
feature_seeds
}
}

Expand Down
37 changes: 23 additions & 14 deletions common/src/p2p/peer.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
//! Shared peer types.

use log::debug;
use std::io;
use std::net;

use microserde as serde;

use bitcoin::network::address::Address;
use bitcoin::network::constants::ServiceFlags;
use microserde as serde;

use crate::block::time::LocalTime;

Expand Down Expand Up @@ -40,15 +40,19 @@ pub trait Store {

/// Seed the peer store with addresses.
/// Fails if *none* of the seeds could be resolved to addresses.
fn seed<S: net::ToSocketAddrs>(
fn seed<S: net::ToSocketAddrs + std::fmt::Debug>(
&mut self,
seeds: impl Iterator<Item = S>,
mut seeds: impl Iterator<Item = S>,
source: Source,
) -> io::Result<()> {
let mut error = None;
let mut fail = false;
let mut success = false;

for seed in seeds {
// TODO: Introduce a step that mean how many combination
// of services flags we need to try before check the seeds without
// services flags.
// for the moment it is 2, but we need a more general solution.
while let Some(seed) = seeds.next() {
debug!("Resolving DNS seed {:?}", seed);
Comment on lines +54 to +55
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this PR it is not completed, because I'm missing the services flag that it is Supported by the network

Here there is still the services flag none, and this it wrong I think

match seed.to_socket_addrs() {
                Ok(addrs) => {
                    success = true;
                    for addr in addrs {
                        self.insert(
                            addr.ip(),
                            KnownAddress::new(
                                Address::new(&addr, ServiceFlags::NONE),
                                source,
                                None,
                            ),
                        );
                    }

Maybe this solution proposed is totally wrong because I'm missing the services flag in the address. Mh!

match seed.to_socket_addrs() {
Ok(addrs) => {
success = true;
Expand All @@ -62,18 +66,23 @@ pub trait Store {
),
);
}
// skip the item in position +1 because it is a recovered seed
// in case we receive a failure in match branch
if !fail {
seeds.next();
}
fail = false;
}
Err(err) => {
debug!("Error During DNS seed resolution {:?}", err);
fail = true;
}
Err(err) => error = Some(err),
}
}

if success {
return Ok(());
}
if let Some(err) = error {
if !success {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("seeds failed to resolve: {}", err),
"All seeds failed to resolve",
));
}
Ok(())
Expand Down