diff --git a/config/src/comments.rs b/config/src/comments.rs index 4a623f130c..1a43111207 100644 --- a/config/src/comments.rs +++ b/config/src/comments.rs @@ -267,7 +267,7 @@ fn comments() -> HashMap { ); retval.insert( - "[server.p2p_config.capabilities]".to_string(), + "[server.pool_config]".to_string(), "#If the seeding type is List, the list of peers to connect to can #be specified as follows: #seeds = [\"192.168.0.1:3414\",\"192.168.0.2:3414\"] @@ -296,19 +296,9 @@ fn comments() -> HashMap { #amount of incoming connections temporarily allowed to exceed peer_max_inbound_count #peer_listener_buffer_count = 8 -# 15 = Bit flags for FULL_NODE -#This structure needs to be changed internally, to make it more configurable - # A preferred dandelion_peer, mainly used for testing dandelion # dandelion_peer = \"10.0.0.1:13144\" -" - .to_string(), - ); - - retval.insert( - "[server.pool_config]".to_string(), - " ######################################### ### MEMPOOL CONFIGURATION ### ######################################### diff --git a/p2p/src/serv.rs b/p2p/src/serv.rs index 3211e285a8..19fcab93b4 100644 --- a/p2p/src/serv.rs +++ b/p2p/src/serv.rs @@ -51,7 +51,7 @@ impl Server { /// Creates a new idle p2p server with no peers pub fn new( db_root: &str, - capab: Capabilities, + capabilities: Capabilities, config: P2PConfig, adapter: Arc, genesis: Hash, @@ -59,7 +59,7 @@ impl Server { ) -> Result { Ok(Server { config: config.clone(), - capabilities: capab, + capabilities, handshake: Arc::new(Handshake::new(genesis, config.clone())), peers: Arc::new(Peers::new(PeerStore::new(db_root)?, adapter, config)), stop_state, diff --git a/p2p/src/types.rs b/p2p/src/types.rs index f8929d5ce4..faf2d1dfeb 100644 --- a/p2p/src/types.rs +++ b/p2p/src/types.rs @@ -266,11 +266,6 @@ pub struct P2PConfig { /// The list of seed nodes, if using Seeding as a seed type pub seeds: Option, - /// TODO: Rethink this. We need to separate what *we* advertise vs. who we connect to. - /// Capabilities expose by this node, also conditions which other peers this - /// node will have an affinity toward when connection. - pub capabilities: Capabilities, - pub peers_allow: Option, pub peers_deny: Option, @@ -298,7 +293,6 @@ impl Default for P2PConfig { P2PConfig { host: ipaddr, port: 3414, - capabilities: Capabilities::FULL_NODE, seeding_type: Seeding::default(), seeds: None, peers_allow: None, @@ -386,22 +380,27 @@ bitflags! { /// Can provide full history of headers back to genesis /// (for at least one arbitrary fork). const HEADER_HIST = 0b0000_0001; - /// Can provide block headers and the TxHashSet for some recent-enough - /// height. + /// Can provide recent txhashset archive for fast sync. const TXHASHSET_HIST = 0b0000_0010; /// Can provide a list of healthy peers const PEER_LIST = 0b0000_0100; /// Can broadcast and request txs by kernel hash. const TX_KERNEL_HASH = 0b0000_1000; + /// Can provide PIBD segments during initial byte download (fast sync). + const PIBD_HIST = 0b0001_0000; + } +} + +/// Default capabilities. +impl Default for Capabilities { + fn default() -> Self { + Capabilities::HEADER_HIST + | Capabilities::TXHASHSET_HIST + | Capabilities::PEER_LIST + | Capabilities::TX_KERNEL_HASH - /// All nodes right now are "full nodes". - /// Some nodes internally may maintain longer block histories (archival_mode) - /// but we do not advertise this to other nodes. - /// All nodes by default will accept lightweight "kernel first" tx broadcast. - const FULL_NODE = Capabilities::HEADER_HIST.bits - | Capabilities::TXHASHSET_HIST.bits - | Capabilities::PEER_LIST.bits - | Capabilities::TX_KERNEL_HASH.bits; + // To be enabled once we start supporting the various PIBD segment msgs. + // | Capabilities::PIBD_HIST } } diff --git a/p2p/tests/capabilities.rs b/p2p/tests/capabilities.rs new file mode 100644 index 0000000000..1e179a4e98 --- /dev/null +++ b/p2p/tests/capabilities.rs @@ -0,0 +1,52 @@ +// Copyright 2020 The Grin Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use grin_p2p::Capabilities; + +// We use `contains()` to filter capabilities bits. +#[test] +fn capabilities_contains() { + let x = Capabilities::HEADER_HIST; + + // capabilities contain themselves + assert!(x.contains(Capabilities::HEADER_HIST)); + + // UNKNOWN can be used to filter for any capabilities + assert!(x.contains(Capabilities::UNKNOWN)); + + // capabilities do not contain other disjoint capabilities + assert_eq!(false, x.contains(Capabilities::PEER_LIST)); +} + +#[test] +fn default_capabilities() { + let x = Capabilities::default(); + + // Check that default capabilities is covered by UNKNOWN. + assert!(x.contains(Capabilities::UNKNOWN)); + + // Check that all the expected capabilities are included in default capabilities. + assert!(x.contains(Capabilities::HEADER_HIST)); + assert!(x.contains(Capabilities::TXHASHSET_HIST)); + assert!(x.contains(Capabilities::PEER_LIST)); + assert!(x.contains(Capabilities::TX_KERNEL_HASH)); + + assert_eq!( + x, + Capabilities::HEADER_HIST + | Capabilities::TXHASHSET_HIST + | Capabilities::PEER_LIST + | Capabilities::TX_KERNEL_HASH + ); +} diff --git a/p2p/tests/ser_deser.rs b/p2p/tests/ser_deser.rs index 2a403fa92c..f341f60f8c 100644 --- a/p2p/tests/ser_deser.rs +++ b/p2p/tests/ser_deser.rs @@ -42,6 +42,8 @@ fn test_type_enum() { #[test] fn test_capabilities() { + let expected = p2p::types::Capabilities::default(); + assert_eq!( p2p::types::Capabilities::from_bits_truncate(0b00000000 as u32), p2p::types::Capabilities::UNKNOWN @@ -52,29 +54,33 @@ fn test_capabilities() { ); assert_eq!( + expected, p2p::types::Capabilities::from_bits_truncate(0b1111 as u32), - p2p::types::Capabilities::FULL_NODE ); assert_eq!( + expected, p2p::types::Capabilities::from_bits_truncate(0b00001111 as u32), - p2p::types::Capabilities::FULL_NODE - ); - assert_eq!( - p2p::types::Capabilities::from_bits_truncate(0b11111111 as u32), - p2p::types::Capabilities::FULL_NODE ); + assert_eq!( + expected, p2p::types::Capabilities::from_bits_truncate(0b00101111 as u32), - p2p::types::Capabilities::FULL_NODE ); - assert!( - p2p::types::Capabilities::from_bits_truncate(0b00101111 as u32) - .contains(p2p::types::Capabilities::FULL_NODE) - ); + assert!(p2p::types::Capabilities::from_bits_truncate(0b00101111 as u32).contains(expected)); assert!( p2p::types::Capabilities::from_bits_truncate(0b00101111 as u32) .contains(p2p::types::Capabilities::TX_KERNEL_HASH) ); } + +// Default capabilities do not currently include PIBD_HIST +// but it is a supported capability bit flag (currently unused). +#[test] +fn test_pibd_capabilities() { + assert_eq!( + p2p::types::Capabilities::default() | p2p::types::Capabilities::PIBD_HIST, + p2p::types::Capabilities::from_bits_truncate(0b11111111 as u32), + ); +} diff --git a/servers/src/grin/seed.rs b/servers/src/grin/seed.rs index ed5a682e44..4016969905 100644 --- a/servers/src/grin/seed.rs +++ b/servers/src/grin/seed.rs @@ -49,7 +49,6 @@ const TESTNET_DNS_SEEDS: &[&str] = &[ pub fn connect_and_monitor( p2p_server: Arc, - capabilities: p2p::Capabilities, seed_list: Box Vec + Send>, preferred_peers: &[PeerAddr], stop_state: Arc, @@ -104,7 +103,6 @@ pub fn connect_and_monitor( listen_for_addrs( peers.clone(), p2p_server.clone(), - capabilities, &rx, &mut connecting_history, ); @@ -303,7 +301,6 @@ fn connect_to_seeds_and_preferred_peers( fn listen_for_addrs( peers: Arc, p2p: Arc, - capab: p2p::Capabilities, rx: &mpsc::Receiver, connecting_history: &mut HashMap>, ) { @@ -345,8 +342,11 @@ fn listen_for_addrs( .name("peer_connect".to_string()) .spawn(move || match p2p_c.connect(addr) { Ok(p) => { + // If peer advertizes PEER_LIST then ask it for more peers that support PEER_LIST. + // We want to build a local db of possible peers to connect to. + // We do not necessarily care (at this point in time) what other capabilities these peers support. if p.info.capabilities.contains(p2p::Capabilities::PEER_LIST) { - let _ = p.send_peer_request(capab); + let _ = p.send_peer_request(p2p::Capabilities::PEER_LIST); } let _ = peers_c.update_state(addr, p2p::State::Healthy); } diff --git a/servers/src/grin/server.rs b/servers/src/grin/server.rs index c5b1871302..f0962b3539 100644 --- a/servers/src/grin/server.rs +++ b/servers/src/grin/server.rs @@ -48,7 +48,7 @@ use crate::grin::{dandelion_monitor, seed, sync}; use crate::mining::stratumserver; use crate::mining::test_miner::Miner; use crate::p2p; -use crate::p2p::types::PeerAddr; +use crate::p2p::types::{Capabilities, PeerAddr}; use crate::pool; use crate::util::file::get_first_line; use crate::util::{RwLock, StopState}; @@ -214,9 +214,14 @@ impl Server { init_net_hooks(&config), )); + // Use our default capabilities here. + // We will advertize these to our peers during hand/shake. + let capabilities = Capabilities::default(); + debug!("Capabilities: {:?}", capabilities); + let p2p_server = Arc::new(p2p::Server::new( &config.db_root, - config.p2p_config.capabilities, + capabilities, config.p2p_config.clone(), net_adapter.clone(), genesis.hash(), @@ -255,7 +260,6 @@ impl Server { connect_thread = Some(seed::connect_and_monitor( p2p_server.clone(), - config.p2p_config.capabilities, seeder, &preferred_peers, stop_state.clone(),