2022-01-20 05:43:23 -08:00
|
|
|
//! Networking code for Zebra.
|
|
|
|
//!
|
|
|
|
//! ## Network Protocol Design
|
2019-10-16 19:27:52 -07:00
|
|
|
//!
|
|
|
|
//! The Zcash network protocol is inherited from Bitcoin, which uses a
|
|
|
|
//! stateful network protocol in which messages can arrive in any
|
2022-01-20 05:43:23 -08:00
|
|
|
//! order (even before a handshake is complete!). The same Bitcoin message
|
2019-10-16 19:27:52 -07:00
|
|
|
//! may be a request or a response depending on context.
|
|
|
|
//!
|
2022-01-20 05:43:23 -08:00
|
|
|
//! ### Achieving Concurrency
|
|
|
|
//!
|
|
|
|
//! This crate translates the legacy Zcash network protocol
|
2019-10-16 19:27:52 -07:00
|
|
|
//! into a stateless, request-response oriented protocol defined by
|
2022-01-20 05:43:23 -08:00
|
|
|
//! the [`Request`] and [`Response`] enums. `zebra-network` completely
|
2019-10-16 19:27:52 -07:00
|
|
|
//! encapsulates all peer handling code behind a single
|
2022-01-20 05:43:23 -08:00
|
|
|
//! [`tower::Service`] representing "the network", which load-balances
|
2019-10-16 19:27:52 -07:00
|
|
|
//! outbound [`Request`]s over available peers.
|
|
|
|
//!
|
2022-06-13 18:22:16 -07:00
|
|
|
//! Unlike the underlying legacy network protocol, Zebra's `PeerSet`
|
|
|
|
//! [`tower::Service`] guarantees that each `Request` future will resolve to the
|
|
|
|
//! correct `Response`, rather than an unrelated `Response` message.
|
2020-07-22 11:38:00 -07:00
|
|
|
//!
|
2022-06-13 18:22:16 -07:00
|
|
|
//! Each peer connection is handled by a distinct [`peer::Connection`] task.
|
2022-01-20 05:43:23 -08:00
|
|
|
//! The Zcash network protocol is bidirectional, so Zebra interprets incoming
|
|
|
|
//! Zcash messages as either:
|
|
|
|
//! - [`Response`]s to previously sent outbound [`Request`]s, or
|
|
|
|
//! - inbound [`Request`]s to an internal [`tower::Service`] representing "this node".
|
|
|
|
//!
|
|
|
|
//! All connection state is isolated to individual peers, so this
|
2019-10-16 19:27:52 -07:00
|
|
|
//! design is structurally immune to the recent `ping` attack.
|
|
|
|
//!
|
2022-01-20 05:43:23 -08:00
|
|
|
//! ### Connection Pool
|
|
|
|
//!
|
2019-10-16 19:27:52 -07:00
|
|
|
//! Because [`tower::Service`]s provide backpressure information, we
|
|
|
|
//! can dynamically manage the size of the connection pool according
|
|
|
|
//! to inbound and outbound demand. The inbound service can shed load
|
|
|
|
//! when it is not ready for requests, causing those peer connections
|
|
|
|
//! to close, and the outbound service can connect to additional peers
|
|
|
|
//! when it is overloaded.
|
2022-01-20 05:43:23 -08:00
|
|
|
//!
|
|
|
|
//! ## `zebra-network` Structure
|
|
|
|
//!
|
|
|
|
//! [`zebra-network::init`] is the main entry point for `zebra-network`.
|
|
|
|
//! It uses the following services, tasks, and endpoints:
|
|
|
|
//!
|
|
|
|
//! ### Low-Level Network Connections
|
|
|
|
//!
|
|
|
|
//! Inbound Zcash Listener Task:
|
|
|
|
//! * accepts inbound connections on the listener port
|
2022-06-02 08:07:35 -07:00
|
|
|
//! * initiates Zcash [`peer::Handshake`]s, which creates [`peer::Connection`]
|
|
|
|
//! tasks for each inbound connection
|
2022-01-20 05:43:23 -08:00
|
|
|
//!
|
|
|
|
//! Outbound Zcash Connector Service:
|
|
|
|
//! * initiates outbound connections to peer addresses
|
2022-06-02 08:07:35 -07:00
|
|
|
//! * initiates Zcash [`peer::Handshake`]s, which creates [`peer::Connection`]
|
|
|
|
//! tasks for each outbound connection
|
2022-01-20 05:43:23 -08:00
|
|
|
//!
|
|
|
|
//! Zebra uses direct TCP connections to share blocks and mempool transactions with other peers.
|
|
|
|
//!
|
|
|
|
//! The [`isolated`] APIs provide anonymised TCP and [Tor](https://crates.io/crates/arti)
|
|
|
|
//! connections to individual peers.
|
|
|
|
//! These isolated connections can be used to send user-generated transactions anonymously.
|
|
|
|
//!
|
|
|
|
//! ### Individual Peer Connections
|
|
|
|
//!
|
|
|
|
//! Each new peer connection spawns the following tasks:
|
|
|
|
//!
|
|
|
|
//! [`peer::Client`] Service:
|
|
|
|
//! * provides an interface for outbound requests to an individual peer
|
2022-06-02 08:07:35 -07:00
|
|
|
//! * accepts [`Request`]s assigned to this peer by the `PeerSet`
|
|
|
|
//! * sends each request to the peer as Zcash [`Message`][1]
|
|
|
|
//! * waits for the inbound response [`Message`][1] from the peer, and returns it as a [`Response`]
|
2022-01-20 05:43:23 -08:00
|
|
|
//!
|
|
|
|
//! [`peer::Connection`] Service:
|
|
|
|
//! * manages connection state: awaiting a request, or handling an inbound or outbound response
|
|
|
|
//! * provides an interface for inbound requests from an individual peer
|
2022-06-02 08:07:35 -07:00
|
|
|
//! * accepts inbound Zcash [`Message`][1]s from this peer
|
2022-01-20 05:43:23 -08:00
|
|
|
//! * handles each message as a [`Request`] to the inbound service
|
2022-06-02 08:07:35 -07:00
|
|
|
//! * sends the [`Response`] to the peer as Zcash [`Message`][1]s
|
2022-01-20 05:43:23 -08:00
|
|
|
//! * drops peer connections if the inbound request queue is overloaded
|
|
|
|
//!
|
|
|
|
//! Since the Zcash network protocol is bidirectional,
|
|
|
|
//! inbound and outbound connections are handled using the same logic.
|
|
|
|
//!
|
|
|
|
//! ### Connection Pool
|
|
|
|
//!
|
2022-06-13 18:22:16 -07:00
|
|
|
//! `PeerSet` Network Service:
|
2022-01-20 05:43:23 -08:00
|
|
|
//! * provides an interface for other services and tasks running within this node
|
|
|
|
//! to make requests to remote peers ("the rest of the network")
|
|
|
|
//! * accepts [`Request`]s from the local node
|
|
|
|
//! * sends each request to a [`peer::Client`] using randomised load-balancing
|
|
|
|
//! * returns the [`Response`] from the [`peer::Client`]
|
|
|
|
//!
|
|
|
|
//! Inbound Network Service:
|
|
|
|
//! * provides an interface for remote peers to request data held by this node
|
|
|
|
//! * accepts inbound Zcash [`Request`]s from [`peer::Connection`]s
|
|
|
|
//! * handles each message as a [`Request`] to the local node
|
|
|
|
//! * sends the [`Response`] to the [`peer::Connection`]
|
|
|
|
//!
|
|
|
|
//! Note: the inbound service is implemented by the [`zebra-network::init`] caller.
|
|
|
|
//!
|
|
|
|
//! Peer Inventory Service:
|
|
|
|
//! * tracks gossiped `inv` advertisements for each peer
|
|
|
|
//! * tracks missing inventory for each peer
|
2022-06-13 18:22:16 -07:00
|
|
|
//! * used by the `PeerSet` to route block and transaction requests
|
|
|
|
//! to peers that have the requested data
|
2022-01-20 05:43:23 -08:00
|
|
|
//!
|
|
|
|
//! ### Peer Discovery
|
|
|
|
//!
|
|
|
|
//! [`AddressBook`] Service:
|
|
|
|
//! * maintains a list of peer addresses and associated connection attempt metadata
|
|
|
|
//! * address book metadata is used to prioritise peer connection attempts
|
|
|
|
//!
|
|
|
|
//! Initial Seed Peer Task:
|
|
|
|
//! * initiates new outbound peer connections to seed peers, resolving them via DNS if required
|
|
|
|
//! * adds seed peer addresses to the [`AddressBook`]
|
|
|
|
//!
|
|
|
|
//! Peer Crawler Task:
|
2022-06-02 08:07:35 -07:00
|
|
|
//! * discovers new peer addresses by sending `Addr` requests to connected peers
|
2022-01-20 05:43:23 -08:00
|
|
|
//! * initiates new outbound peer connections in response to application demand
|
2022-06-02 08:07:35 -07:00
|
|
|
//!
|
|
|
|
//! [1]: protocol::external::Message
|
2019-09-09 18:35:56 -07:00
|
|
|
|
2022-03-27 16:42:47 -07:00
|
|
|
#![doc(html_favicon_url = "https://zfnd.org/wp-content/uploads/2022/03/zebra-favicon-128.png")]
|
|
|
|
#![doc(html_logo_url = "https://zfnd.org/wp-content/uploads/2022/03/zebra-icon.png")]
|
2020-02-26 21:10:08 -08:00
|
|
|
#![doc(html_root_url = "https://doc.zebra.zfnd.org/zebra_network")]
|
2020-02-05 12:31:03 -08:00
|
|
|
|
2019-10-10 18:15:24 -07:00
|
|
|
#[macro_use]
|
|
|
|
extern crate pin_project;
|
2019-10-08 13:57:24 -07:00
|
|
|
#[macro_use]
|
|
|
|
extern crate serde;
|
2019-09-14 07:00:36 -07:00
|
|
|
#[macro_use]
|
2019-09-23 18:11:05 -07:00
|
|
|
extern crate tracing;
|
2019-09-30 11:58:32 -07:00
|
|
|
#[macro_use]
|
|
|
|
extern crate bitflags;
|
2019-09-14 07:00:36 -07:00
|
|
|
|
2019-10-08 13:49:12 -07:00
|
|
|
/// Type alias to make working with tower traits easier.
|
|
|
|
///
|
|
|
|
/// Note: the 'static lifetime bound means that the *type* cannot have any
|
|
|
|
/// non-'static lifetimes, (e.g., when a type contains a borrow and is
|
|
|
|
/// parameterized by 'a), *not* that the object itself has 'static lifetime.
|
2020-09-18 11:20:55 -07:00
|
|
|
pub type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
|
2019-10-08 13:49:12 -07:00
|
|
|
|
2019-10-17 15:42:19 -07:00
|
|
|
mod address_book;
|
2021-11-04 04:34:00 -07:00
|
|
|
mod address_book_updater;
|
2019-10-16 19:26:39 -07:00
|
|
|
mod config;
|
2021-01-29 04:36:33 -08:00
|
|
|
pub mod constants;
|
2020-09-01 20:41:43 -07:00
|
|
|
mod isolated;
|
2019-10-16 19:26:39 -07:00
|
|
|
mod meta_addr;
|
|
|
|
mod peer;
|
|
|
|
mod peer_set;
|
2020-02-18 11:32:25 -08:00
|
|
|
mod policies;
|
2019-10-16 19:26:39 -07:00
|
|
|
mod protocol;
|
2019-09-24 11:25:06 -07:00
|
|
|
|
2022-01-24 17:46:31 -08:00
|
|
|
#[cfg(feature = "tor")]
|
|
|
|
pub use crate::isolated::tor::connect_isolated_tor;
|
|
|
|
|
2022-02-14 17:44:33 -08:00
|
|
|
#[cfg(all(feature = "tor", any(test, feature = "proptest-impl")))]
|
|
|
|
pub use crate::isolated::tor::connect_isolated_tor_with_inbound;
|
|
|
|
|
|
|
|
#[cfg(any(test, feature = "proptest-impl"))]
|
|
|
|
pub use crate::isolated::{
|
|
|
|
connect_isolated_tcp_direct_with_inbound, connect_isolated_with_inbound,
|
|
|
|
};
|
|
|
|
|
2019-10-17 12:46:08 -07:00
|
|
|
pub use crate::{
|
2019-10-17 15:42:19 -07:00
|
|
|
address_book::AddressBook,
|
2019-10-17 12:46:08 -07:00
|
|
|
config::Config,
|
2022-01-14 11:34:59 -08:00
|
|
|
isolated::{connect_isolated, connect_isolated_tcp_direct},
|
2021-02-17 17:18:32 -08:00
|
|
|
meta_addr::PeerAddrState,
|
2022-09-14 08:00:25 -07:00
|
|
|
peer::{Client, ConnectedAddr, ConnectionInfo, HandshakeError, PeerError, SharedPeerError},
|
2019-10-22 12:44:08 -07:00
|
|
|
peer_set::init,
|
2021-12-19 15:02:31 -08:00
|
|
|
policies::RetryLimit,
|
2022-09-14 08:00:25 -07:00
|
|
|
protocol::{
|
|
|
|
external::{Version, VersionMessage},
|
|
|
|
internal::{InventoryResponse, Request, Response},
|
|
|
|
},
|
2019-10-17 12:46:08 -07:00
|
|
|
};
|
|
|
|
|
2022-09-14 08:00:25 -07:00
|
|
|
/// Types used in the definition of [`Request`], [`Response`], and [`VersionMessage`].
|
2019-10-17 12:46:08 -07:00
|
|
|
pub mod types {
|
2022-09-14 08:00:25 -07:00
|
|
|
pub use crate::{
|
|
|
|
meta_addr::MetaAddr,
|
|
|
|
protocol::{
|
|
|
|
external::{AddrInVersion, Nonce},
|
|
|
|
types::PeerServices,
|
|
|
|
},
|
|
|
|
};
|
2022-02-14 17:44:33 -08:00
|
|
|
|
|
|
|
#[cfg(any(test, feature = "proptest-impl"))]
|
|
|
|
pub use crate::protocol::external::InventoryHash;
|
2019-10-17 12:46:08 -07:00
|
|
|
}
|