Discovery and seeding of other peers. Relies either on a gist with IP addresses or a static list. Connects to a first list, sending peer request messages to discover more. Monitor the server to make sure there's always enough peer connections.
This commit is contained in:
+7
-12
@@ -223,7 +223,7 @@ impl Connection {
|
||||
pub struct TimeoutConnection {
|
||||
underlying: Connection,
|
||||
|
||||
expected_responses: Arc<Mutex<Vec<(Type, Hash, Option<bool>, Instant)>>>,
|
||||
expected_responses: Arc<Mutex<Vec<(Type, Option<Hash>, Instant)>>>,
|
||||
}
|
||||
|
||||
impl TimeoutConnection {
|
||||
@@ -244,15 +244,13 @@ impl TimeoutConnection {
|
||||
let recv_h = try!(handler.handle(sender, header, data));
|
||||
|
||||
let mut expects = exp.lock().unwrap();
|
||||
println!("EXP1 {}", expects.len());
|
||||
let filtered = expects.iter()
|
||||
.filter(|&&(typ, h, _, _)| {
|
||||
msg_type != typ || recv_h.is_some() && recv_h.unwrap() != h
|
||||
.filter(|&&(typ, h, _): &&(Type, Option<Hash>, Instant)| {
|
||||
msg_type != typ || h.is_some() && recv_h != h
|
||||
})
|
||||
.map(|&x| x)
|
||||
.collect::<Vec<_>>();
|
||||
*expects = filtered;
|
||||
println!("EXP2 {}", expects.len());
|
||||
|
||||
Ok(recv_h)
|
||||
});
|
||||
@@ -263,7 +261,7 @@ impl TimeoutConnection {
|
||||
.interval(Duration::new(2, 0))
|
||||
.fold((), move |_, _| {
|
||||
let exp = exp.lock().unwrap();
|
||||
for &(_, _, _, t) in exp.deref() {
|
||||
for &(_, _, t) in exp.deref() {
|
||||
if Instant::now() - t > Duration::new(2, 0) {
|
||||
return Err(TimerError::TooLong);
|
||||
}
|
||||
@@ -283,17 +281,14 @@ impl TimeoutConnection {
|
||||
/// optionally the hash of the sent data.
|
||||
pub fn send_request(&self,
|
||||
t: Type,
|
||||
rt: Type,
|
||||
body: &ser::Writeable,
|
||||
expect_h: Option<(Type, Hash)>)
|
||||
expect_h: Option<(Hash)>)
|
||||
-> Result<(), ser::Error> {
|
||||
let sent = try!(self.underlying.send_msg(t, body));
|
||||
|
||||
let mut expects = self.expected_responses.lock().unwrap();
|
||||
if let Some((rt, h)) = expect_h {
|
||||
expects.push((rt, h, None, Instant::now()));
|
||||
} else {
|
||||
expects.push((t, ZERO_HASH, None, Instant::now()));
|
||||
}
|
||||
expects.push((rt, expect_h, Instant::now()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use futures::Future;
|
||||
@@ -47,17 +48,19 @@ impl Handshake {
|
||||
|
||||
/// Handles connecting to a new remote peer, starting the version handshake.
|
||||
pub fn connect(&self,
|
||||
capab: Capabilities,
|
||||
total_difficulty: Difficulty,
|
||||
self_addr: SocketAddr,
|
||||
conn: TcpStream)
|
||||
-> Box<Future<Item = (TcpStream, ProtocolV1, PeerInfo), Error = Error>> {
|
||||
// prepare the first part of the hanshake
|
||||
let nonce = self.next_nonce();
|
||||
let hand = Hand {
|
||||
version: PROTOCOL_VERSION,
|
||||
capabilities: FULL_HIST,
|
||||
capabilities: capab,
|
||||
nonce: nonce,
|
||||
total_difficulty: total_difficulty,
|
||||
sender_addr: SockAddr(conn.local_addr().unwrap()),
|
||||
sender_addr: SockAddr(self_addr),
|
||||
receiver_addr: SockAddr(conn.peer_addr().unwrap()),
|
||||
user_agent: USER_AGENT.to_string(),
|
||||
};
|
||||
@@ -90,6 +93,7 @@ impl Handshake {
|
||||
/// Handles receiving a connection from a new remote peer that started the
|
||||
/// version handshake.
|
||||
pub fn handshake(&self,
|
||||
capab: Capabilities,
|
||||
total_difficulty: Difficulty,
|
||||
conn: TcpStream)
|
||||
-> Box<Future<Item = (TcpStream, ProtocolV1, PeerInfo), Error = Error>> {
|
||||
@@ -116,20 +120,21 @@ impl Handshake {
|
||||
let peer_info = PeerInfo {
|
||||
capabilities: hand.capabilities,
|
||||
user_agent: hand.user_agent,
|
||||
addr: conn.peer_addr().unwrap(),
|
||||
addr: hand.sender_addr.0,
|
||||
version: hand.version,
|
||||
total_difficulty: hand.total_difficulty,
|
||||
};
|
||||
// send our reply with our info
|
||||
let shake = Shake {
|
||||
version: PROTOCOL_VERSION,
|
||||
capabilities: FULL_HIST,
|
||||
capabilities: capab,
|
||||
total_difficulty: total_difficulty,
|
||||
user_agent: USER_AGENT.to_string(),
|
||||
};
|
||||
Ok((conn, shake, peer_info))
|
||||
})
|
||||
.and_then(|(conn, shake, peer_info)| {
|
||||
debug!("Success handshake with {}.", peer_info.addr);
|
||||
write_msg(conn, shake, Type::Shake)
|
||||
// when more than one protocol version is supported, choosing should go here
|
||||
.map(|conn| (conn, ProtocolV1::new(), peer_info))
|
||||
|
||||
+4
-2
@@ -44,9 +44,11 @@ mod msg;
|
||||
mod peer;
|
||||
mod protocol;
|
||||
mod server;
|
||||
pub mod store;
|
||||
mod store;
|
||||
mod types;
|
||||
|
||||
pub use server::{Server, DummyAdapter};
|
||||
pub use peer::Peer;
|
||||
pub use types::{P2PConfig, NetAdapter, MAX_LOCATORS, MAX_BLOCK_HEADERS};
|
||||
pub use types::{P2PConfig, NetAdapter, MAX_LOCATORS, MAX_BLOCK_HEADERS, MAX_PEER_ADDRS,
|
||||
Capabilities, UNKNOWN, FULL_NODE, FULL_HIST, PeerInfo};
|
||||
pub use store::{PeerStore, PeerData, State};
|
||||
|
||||
+8
-2
@@ -311,10 +311,16 @@ impl Writeable for PeerAddrs {
|
||||
impl Readable<PeerAddrs> for PeerAddrs {
|
||||
fn read(reader: &mut Reader) -> Result<PeerAddrs, ser::Error> {
|
||||
let peer_count = try!(reader.read_u32());
|
||||
if peer_count > 1000 {
|
||||
if peer_count > MAX_PEER_ADDRS {
|
||||
return Err(ser::Error::TooLargeReadErr);
|
||||
} else if peer_count == 0 {
|
||||
return Ok(PeerAddrs { peers: vec![] });
|
||||
}
|
||||
// let peers = try_map_vec!([0..peer_count], |_| SockAddr::read(reader));
|
||||
let mut peers = Vec::with_capacity(peer_count as usize);
|
||||
for _ in 0..peer_count {
|
||||
peers.push(SockAddr::read(reader)?);
|
||||
}
|
||||
let peers = try_map_vec!([0..peer_count], |_| SockAddr::read(reader));
|
||||
Ok(PeerAddrs { peers: peers })
|
||||
}
|
||||
}
|
||||
|
||||
+25
-14
@@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use futures::Future;
|
||||
@@ -35,31 +36,36 @@ unsafe impl Send for Peer {}
|
||||
impl Peer {
|
||||
/// Initiates the handshake with another peer.
|
||||
pub fn connect(conn: TcpStream,
|
||||
capab: Capabilities,
|
||||
total_difficulty: Difficulty,
|
||||
self_addr: SocketAddr,
|
||||
hs: &Handshake)
|
||||
-> Box<Future<Item = (TcpStream, Peer), Error = Error>> {
|
||||
let connect_peer = hs.connect(total_difficulty, conn).and_then(|(conn, proto, info)| {
|
||||
Ok((conn,
|
||||
Peer {
|
||||
info: info,
|
||||
proto: Box::new(proto),
|
||||
}))
|
||||
});
|
||||
let connect_peer = hs.connect(capab, total_difficulty, self_addr, conn)
|
||||
.and_then(|(conn, proto, info)| {
|
||||
Ok((conn,
|
||||
Peer {
|
||||
info: info,
|
||||
proto: Box::new(proto),
|
||||
}))
|
||||
});
|
||||
Box::new(connect_peer)
|
||||
}
|
||||
|
||||
/// Accept a handshake initiated by another peer.
|
||||
pub fn accept(conn: TcpStream,
|
||||
capab: Capabilities,
|
||||
total_difficulty: Difficulty,
|
||||
hs: &Handshake)
|
||||
-> Box<Future<Item = (TcpStream, Peer), Error = Error>> {
|
||||
let hs_peer = hs.handshake(total_difficulty, conn).and_then(|(conn, proto, info)| {
|
||||
Ok((conn,
|
||||
Peer {
|
||||
info: info,
|
||||
proto: Box::new(proto),
|
||||
}))
|
||||
});
|
||||
let hs_peer = hs.handshake(capab, total_difficulty, conn)
|
||||
.and_then(|(conn, proto, info)| {
|
||||
Ok((conn,
|
||||
Peer {
|
||||
info: info,
|
||||
proto: Box::new(proto),
|
||||
}))
|
||||
});
|
||||
Box::new(hs_peer)
|
||||
}
|
||||
|
||||
@@ -102,6 +108,11 @@ impl Peer {
|
||||
self.proto.send_block_request(h)
|
||||
}
|
||||
|
||||
pub fn send_peer_request(&self, capab: Capabilities) -> Result<(), Error> {
|
||||
debug!("Asking {} for more peers.", self.info.addr);
|
||||
self.proto.send_peer_request(capab)
|
||||
}
|
||||
|
||||
pub fn stop(&self) {
|
||||
self.proto.close();
|
||||
}
|
||||
|
||||
+39
-5
@@ -68,7 +68,7 @@ impl Protocol for ProtocolV1 {
|
||||
/// Sends a ping message to the remote peer. Will panic if handle has never
|
||||
/// been called on this protocol.
|
||||
fn send_ping(&self) -> Result<(), ser::Error> {
|
||||
self.send_request(Type::Ping, &Empty {}, None)
|
||||
self.send_request(Type::Ping, Type::Pong, &Empty {}, None)
|
||||
}
|
||||
|
||||
/// Serializes and sends a block to our remote peer
|
||||
@@ -82,11 +82,21 @@ impl Protocol for ProtocolV1 {
|
||||
}
|
||||
|
||||
fn send_header_request(&self, locator: Vec<Hash>) -> Result<(), ser::Error> {
|
||||
self.send_request(Type::GetHeaders, &Locator { hashes: locator }, None)
|
||||
self.send_request(Type::GetHeaders,
|
||||
Type::Headers,
|
||||
&Locator { hashes: locator },
|
||||
None)
|
||||
}
|
||||
|
||||
fn send_block_request(&self, h: Hash) -> Result<(), ser::Error> {
|
||||
self.send_request(Type::GetBlock, &h, Some((Type::Block, h)))
|
||||
self.send_request(Type::GetBlock, Type::Block, &h, Some(h))
|
||||
}
|
||||
|
||||
fn send_peer_request(&self, capab: Capabilities) -> Result<(), ser::Error> {
|
||||
self.send_request(Type::GetPeerAddrs,
|
||||
Type::PeerAddrs,
|
||||
&GetPeerAddrs { capabilities: capab },
|
||||
None)
|
||||
}
|
||||
|
||||
/// Close the connection to the remote peer
|
||||
@@ -102,10 +112,11 @@ impl ProtocolV1 {
|
||||
|
||||
fn send_request(&self,
|
||||
t: Type,
|
||||
rt: Type,
|
||||
body: &ser::Writeable,
|
||||
expect_resp: Option<(Type, Hash)>)
|
||||
expect_resp: Option<Hash>)
|
||||
-> Result<(), ser::Error> {
|
||||
self.conn.borrow().send_request(t, body, expect_resp)
|
||||
self.conn.borrow().send_request(t, rt, body, expect_resp)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,6 +179,29 @@ fn handle_payload(adapter: &NetAdapter,
|
||||
adapter.headers_received(headers.headers);
|
||||
Ok(None)
|
||||
}
|
||||
Type::GetPeerAddrs => {
|
||||
let get_peers = ser::deserialize::<GetPeerAddrs>(&mut &buf[..])?;
|
||||
let peer_addrs = adapter.find_peer_addrs(get_peers.capabilities);
|
||||
|
||||
// serialize and send all the headers over
|
||||
let mut body_data = vec![];
|
||||
try!(ser::serialize(&mut body_data,
|
||||
&PeerAddrs {
|
||||
peers: peer_addrs.iter().map(|sa| SockAddr(*sa)).collect(),
|
||||
}));
|
||||
let mut data = vec![];
|
||||
try!(ser::serialize(&mut data,
|
||||
&MsgHeader::new(Type::PeerAddrs, body_data.len() as u64)));
|
||||
data.append(&mut body_data);
|
||||
sender.send(data);
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
Type::PeerAddrs => {
|
||||
let peer_addrs = ser::deserialize::<PeerAddrs>(&mut &buf[..])?;
|
||||
adapter.peer_addrs_received(peer_addrs.peers.iter().map(|pa| pa.0).collect());
|
||||
Ok(None)
|
||||
}
|
||||
_ => {
|
||||
debug!("unknown message type {:?}", header.msg_type);
|
||||
Ok(None)
|
||||
|
||||
+46
-8
@@ -23,7 +23,7 @@ use std::time::Duration;
|
||||
|
||||
use futures;
|
||||
use futures::{Future, Stream};
|
||||
use futures::future::IntoFuture;
|
||||
use futures::future::{self, IntoFuture};
|
||||
use rand::{self, Rng};
|
||||
use tokio_core::net::{TcpListener, TcpStream};
|
||||
use tokio_core::reactor;
|
||||
@@ -51,12 +51,18 @@ impl NetAdapter for DummyAdapter {
|
||||
fn get_block(&self, h: Hash) -> Option<core::Block> {
|
||||
None
|
||||
}
|
||||
fn find_peer_addrs(&self, capab: Capabilities) -> Vec<SocketAddr> {
|
||||
vec![]
|
||||
}
|
||||
fn peer_addrs_received(&self, peer_addrs: Vec<SocketAddr>) {}
|
||||
fn peer_connected(&self, pi: &PeerInfo) {}
|
||||
}
|
||||
|
||||
/// P2P server implementation, handling bootstrapping to find and connect to
|
||||
/// peers, receiving connections from other peers and keep track of all of them.
|
||||
pub struct Server {
|
||||
config: P2PConfig,
|
||||
capabilities: Capabilities,
|
||||
peers: Arc<RwLock<Vec<Arc<Peer>>>>,
|
||||
adapter: Arc<NetAdapter>,
|
||||
stop: RefCell<Option<futures::sync::oneshot::Sender<()>>>,
|
||||
@@ -68,9 +74,10 @@ unsafe impl Send for Server {}
|
||||
// TODO TLS
|
||||
impl Server {
|
||||
/// Creates a new idle p2p server with no peers
|
||||
pub fn new(config: P2PConfig, adapter: Arc<NetAdapter>) -> Server {
|
||||
pub fn new(capab: Capabilities, config: P2PConfig, adapter: Arc<NetAdapter>) -> Server {
|
||||
Server {
|
||||
config: config,
|
||||
capabilities: capab,
|
||||
peers: Arc::new(RwLock::new(Vec::new())),
|
||||
adapter: adapter,
|
||||
stop: RefCell::new(None),
|
||||
@@ -87,6 +94,7 @@ impl Server {
|
||||
let hs = Arc::new(Handshake::new());
|
||||
let peers = self.peers.clone();
|
||||
let adapter = self.adapter.clone();
|
||||
let capab = self.capabilities.clone();
|
||||
|
||||
// main peer acceptance future handling handshake
|
||||
let hp = h.clone();
|
||||
@@ -96,7 +104,9 @@ impl Server {
|
||||
let peers = peers.clone();
|
||||
|
||||
// accept the peer and add it to the server map
|
||||
let peer_accept = add_to_peers(peers, Peer::accept(conn, total_diff, &hs.clone()));
|
||||
let peer_accept = add_to_peers(peers,
|
||||
adapter.clone(),
|
||||
Peer::accept(conn, capab, total_diff, &hs.clone()));
|
||||
|
||||
// wire in a future to timeout the accept after 5 secs
|
||||
let timed_peer = with_timeout(Box::new(peer_accept), &hp);
|
||||
@@ -136,23 +146,49 @@ impl Server {
|
||||
pub fn connect_peer(&self,
|
||||
addr: SocketAddr,
|
||||
h: reactor::Handle)
|
||||
-> Box<Future<Item = (), Error = Error>> {
|
||||
-> Box<Future<Item = Option<Arc<Peer>>, Error = Error>> {
|
||||
for p in self.peers.read().unwrap().deref() {
|
||||
// if we're already connected to the addr, just return the peer
|
||||
if p.info.addr == addr {
|
||||
return Box::new(future::ok(Some((*p).clone())));
|
||||
}
|
||||
}
|
||||
// asked to connect to ourselves
|
||||
if addr.ip() == self.config.host && addr.port() == self.config.port {
|
||||
return Box::new(future::ok(None));
|
||||
}
|
||||
let peers = self.peers.clone();
|
||||
let adapter1 = self.adapter.clone();
|
||||
let adapter2 = self.adapter.clone();
|
||||
let capab = self.capabilities.clone();
|
||||
let self_addr = SocketAddr::new(self.config.host, self.config.port);
|
||||
|
||||
debug!("{} connecting to {}", self_addr, addr);
|
||||
|
||||
let socket = TcpStream::connect(&addr, &h).map_err(|e| Error::IOErr(e));
|
||||
let h2 = h.clone();
|
||||
let request = socket.and_then(move |socket| {
|
||||
let peers = peers.clone();
|
||||
let total_diff = adapter1.total_difficulty();
|
||||
let total_diff = adapter1.clone().total_difficulty();
|
||||
|
||||
// connect to the peer and add it to the server map, wiring it a timeout for
|
||||
// the handhake
|
||||
let peer_connect =
|
||||
add_to_peers(peers, Peer::connect(socket, total_diff, &Handshake::new()));
|
||||
let peer_connect = add_to_peers(peers,
|
||||
adapter1,
|
||||
Peer::connect(socket,
|
||||
capab,
|
||||
total_diff,
|
||||
self_addr,
|
||||
&Handshake::new()));
|
||||
with_timeout(Box::new(peer_connect), &h)
|
||||
})
|
||||
.and_then(move |(socket, peer)| peer.run(socket, adapter2));
|
||||
.and_then(move |(socket, peer)| {
|
||||
h2.spawn(peer.run(socket, adapter2).map_err(|e| {
|
||||
error!("Peer error: {:?}", e);
|
||||
()
|
||||
}));
|
||||
Ok(Some(peer))
|
||||
});
|
||||
Box::new(request)
|
||||
}
|
||||
|
||||
@@ -212,11 +248,13 @@ impl Server {
|
||||
|
||||
// Adds the peer built by the provided future in the peers map
|
||||
fn add_to_peers<A>(peers: Arc<RwLock<Vec<Arc<Peer>>>>,
|
||||
adapter: Arc<NetAdapter>,
|
||||
peer_fut: A)
|
||||
-> Box<Future<Item = Result<(TcpStream, Arc<Peer>), ()>, Error = Error>>
|
||||
where A: IntoFuture<Item = (TcpStream, Peer), Error = Error> + 'static
|
||||
{
|
||||
let peer_add = peer_fut.into_future().map(move |(conn, peer)| {
|
||||
adapter.peer_connected(&peer.info);
|
||||
let apeer = Arc::new(peer);
|
||||
let mut peers = peers.write().unwrap();
|
||||
peers.push(apeer.clone());
|
||||
|
||||
+12
-8
@@ -36,14 +36,14 @@ enum_from_primitive! {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Peer {
|
||||
pub struct PeerData {
|
||||
pub addr: SocketAddr,
|
||||
pub capabilities: Capabilities,
|
||||
pub user_agent: String,
|
||||
pub flags: State,
|
||||
}
|
||||
|
||||
impl Writeable for Peer {
|
||||
impl Writeable for PeerData {
|
||||
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||
SockAddr(self.addr).write(writer)?;
|
||||
ser_multiwrite!(writer,
|
||||
@@ -54,15 +54,15 @@ impl Writeable for Peer {
|
||||
}
|
||||
}
|
||||
|
||||
impl Readable<Peer> for Peer {
|
||||
fn read(reader: &mut Reader) -> Result<Peer, ser::Error> {
|
||||
impl Readable<PeerData> for PeerData {
|
||||
fn read(reader: &mut Reader) -> Result<PeerData, ser::Error> {
|
||||
let addr = SockAddr::read(reader)?;
|
||||
let (capab, ua, fl) = ser_multiread!(reader, read_u32, read_vec, read_u8);
|
||||
let user_agent = String::from_utf8(ua).map_err(|_| ser::Error::CorruptedData)?;
|
||||
let capabilities = Capabilities::from_bits(capab).ok_or(ser::Error::CorruptedData)?;
|
||||
match State::from_u8(fl) {
|
||||
Some(flags) => {
|
||||
Ok(Peer {
|
||||
Ok(PeerData {
|
||||
addr: addr.0,
|
||||
capabilities: capabilities,
|
||||
user_agent: user_agent,
|
||||
@@ -84,18 +84,22 @@ impl PeerStore {
|
||||
Ok(PeerStore { db: db })
|
||||
}
|
||||
|
||||
pub fn save_peer(&self, p: &Peer) -> Result<(), Error> {
|
||||
pub fn save_peer(&self, p: &PeerData) -> Result<(), Error> {
|
||||
self.db.put_ser(&to_key(PEER_PREFIX, &mut format!("{}", p.addr).into_bytes())[..],
|
||||
p)
|
||||
}
|
||||
|
||||
pub fn exists_peer(&self, peer_addr: SocketAddr) -> Result<bool, Error> {
|
||||
self.db.exists(&to_key(PEER_PREFIX, &mut format!("{}", peer_addr).into_bytes())[..])
|
||||
}
|
||||
|
||||
pub fn delete_peer(&self, peer_addr: SocketAddr) -> Result<(), Error> {
|
||||
self.db.delete(&to_key(PEER_PREFIX, &mut format!("{}", peer_addr).into_bytes())[..])
|
||||
}
|
||||
|
||||
pub fn find_peers(&self, state: State, cap: Capabilities, count: usize) -> Vec<Peer> {
|
||||
pub fn find_peers(&self, state: State, cap: Capabilities, count: usize) -> Vec<PeerData> {
|
||||
let peers_iter = self.db
|
||||
.iter::<Peer>(&to_key(PEER_PREFIX, &mut "".to_string().into_bytes()));
|
||||
.iter::<PeerData>(&to_key(PEER_PREFIX, &mut "".to_string().into_bytes()));
|
||||
let mut peers = Vec::with_capacity(count);
|
||||
for p in peers_iter {
|
||||
if p.flags == state && p.capabilities.contains(cap) {
|
||||
|
||||
@@ -32,6 +32,9 @@ pub const MAX_BLOCK_HEADERS: u32 = 512;
|
||||
/// Maximum number of block bodies a peer should ever ask for and send
|
||||
pub const MAX_BLOCK_BODIES: u32 = 16;
|
||||
|
||||
/// Maximum number of peer addresses a peer should ever send
|
||||
pub const MAX_PEER_ADDRS: u32 = 256;
|
||||
|
||||
/// Configuration for the peer-to-peer server.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct P2PConfig {
|
||||
@@ -60,6 +63,10 @@ bitflags! {
|
||||
/// Can provide block headers and the UTXO set for some recent-enough
|
||||
/// height.
|
||||
const UTXO_HIST = 0b00000010,
|
||||
/// Can provide a list of healthy peers
|
||||
const PEER_LIST = 0b00000100,
|
||||
|
||||
const FULL_NODE = FULL_HIST.bits | UTXO_HIST.bits | PEER_LIST.bits,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +108,9 @@ pub trait Protocol {
|
||||
/// Sends a request for a block from its hash.
|
||||
fn send_block_request(&self, h: Hash) -> Result<(), Error>;
|
||||
|
||||
/// Sends a request for some peer addresses.
|
||||
fn send_peer_request(&self, capab: Capabilities) -> Result<(), Error>;
|
||||
|
||||
/// How many bytes have been sent/received to/from the remote peer.
|
||||
fn transmitted_bytes(&self) -> (u64, u64);
|
||||
|
||||
@@ -133,4 +143,14 @@ pub trait NetAdapter: Sync + Send {
|
||||
|
||||
/// Gets a full block by its hash.
|
||||
fn get_block(&self, h: Hash) -> Option<core::Block>;
|
||||
|
||||
/// Find good peers we know with the provided capability and return their
|
||||
/// addresses.
|
||||
fn find_peer_addrs(&self, capab: Capabilities) -> Vec<SocketAddr>;
|
||||
|
||||
/// A list of peers has been received from one of our peers.
|
||||
fn peer_addrs_received(&self, Vec<SocketAddr>);
|
||||
|
||||
/// Network successfully connected to a peer.
|
||||
fn peer_connected(&self, &PeerInfo);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user