bitcoin_peers_crawler/lib.rs
1//! Bitcoin network peer discovery.
2//!
3//! This crate provides a high-performance, concurrent crawler for discovering peers on the bitcoin network.
4//!
5//! # Features
6//!
7//! * **Concurrent Crawling**: Efficiently crawls multiple peers simultaneously.
8//! * **Streaming Results**: Returns discovered peers as they're found via an async channel interface.
9//! * **Resource Control**: Configurable limits on concurrent connections and timeouts.
10//!
11//! # Quick Start
12//!
13//! ```
14//! use bitcoin::Network;
15//! use bitcoin::p2p::address::AddrV2;
16//! use bitcoin_peers_crawler::{Crawler, CrawlerBuilder, Peer};
17//! use tokio::time::{timeout, Duration};
18//! use std::net::Ipv4Addr;
19//!
20//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
21//! // Build a crawler with custom configuration.
22//! let crawler = CrawlerBuilder::new(Network::Bitcoin)
23//! .with_max_concurrent_tasks(16) // Increase concurrency
24//! .build();
25//!
26//! // Create a seed peer to start crawling from.
27//! let seed = Peer::new(
28//! AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)),
29//! 8333,
30//! );
31//!
32//! // Start crawling from the seed peer.
33//! let mut receiver = crawler.crawl(seed).await?;
34//!
35//! // Collect peers for 30 seconds.
36//! let mut discovered_peers = Vec::new();
37//! let duration = Duration::from_secs(30);
38//!
39//! if let Ok(result) = timeout(duration, async {
40//! while let Some(msg) = receiver.recv().await {
41//! match msg {
42//! bitcoin_peers_crawler::CrawlerMessage::Listening(peer) => {
43//! discovered_peers.push(peer);
44//! }
45//! _ => {} // Ignore non-listening peers
46//! }
47//! }
48//! }).await {
49//! result;
50//! }
51//!
52//! println!("Discovered {} peers", discovered_peers.len());
53//! # Ok(())
54//! # }
55//! ```
56//!
57//! # Configuration
58//!
59//! The [`CrawlerBuilder`] provides fine-grained control over crawler behavior:
60//!
61//! ```no_run
62//! use bitcoin::Network;
63//! use bitcoin_peers_crawler::{CrawlerBuilder, TransportPolicy};
64//!
65//! let crawler = CrawlerBuilder::new(Network::Bitcoin)
66//! .with_max_concurrent_tasks(32) // Aggressive concurrency
67//! .with_transport_policy(TransportPolicy::V2Required) // Require encrypted connections
68//! .with_protocol_version(70016) // Minimum protocol version
69//! .build();
70//! ```
71//!
72//! # Example: Finding V2-Capable Peers
73//!
74//! ```no_run
75//! use bitcoin::Network;
76//! use bitcoin::p2p::address::AddrV2;
77//! use bitcoin::p2p::ServiceFlags;
78//! use bitcoin_peers_crawler::{CrawlerBuilder, CrawlerMessage, Peer, PeerServices};
79//! use std::net::Ipv4Addr;
80//!
81//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
82//! let crawler = CrawlerBuilder::new(Network::Bitcoin).build();
83//!
84//! // Start from a known peer
85//! let seed = Peer::new(
86//! AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)),
87//! 8333,
88//! );
89//! let mut receiver = crawler.crawl(seed).await?;
90//!
91//! let mut v2_peers = Vec::new();
92//! while let Some(msg) = receiver.recv().await {
93//! if let CrawlerMessage::Listening(peer) = msg {
94//! // Check if peer advertises v2 transport support.
95//! if let PeerServices::Known(flags) = peer.services {
96//! if flags.has(ServiceFlags::P2P_V2) {
97//! v2_peers.push(peer);
98//! }
99//! }
100//!
101//! if v2_peers.len() >= 100 {
102//! break; // Found enough v2-capable peers
103//! }
104//! }
105//! }
106//! # Ok(())
107//! # }
108//! ```
109
110mod builder;
111mod connection;
112mod crawler;
113mod session;
114
115pub use builder::{CrawlerBuilder, CrawlerBuilderError};
116pub use crawler::{Crawler, CrawlerMessage};
117
118// Re-exports.
119pub use bitcoin_peers_connection::{
120 ConnectionError, Peer, PeerProtocolVersion, PeerServices, TransportPolicy, UserAgent,
121};