diff --git a/Cargo.toml b/Cargo.toml index 65c1bf3..9f38098 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,3 +81,8 @@ path = "example/rescan.rs" name = "tor" path = "example/tor.rs" required-features = ["tor"] + +[[example]] +name = "managed" +path = "example/managed.rs" +required-features = ["filter-control"] diff --git a/example/managed.rs b/example/managed.rs new file mode 100644 index 0000000..db2e824 --- /dev/null +++ b/example/managed.rs @@ -0,0 +1,78 @@ +//! Kyoto supports checking filters directly, as protocols like silent payments will have +//! many possible scripts to check. Enable the `filter-control` feature to check filters +//! manually in your program. + +use kyoto::core::messages::NodeMessage; +use kyoto::{chain::checkpoints::HeaderCheckpoint, core::builder::NodeBuilder}; +use kyoto::{AddrV2, Address, Network, ServiceFlags, TrustedPeer}; +use std::collections::HashSet; +use std::{net::Ipv4Addr, str::FromStr}; + +const NETWORK: Network = Network::Signet; +const RECOVERY_HEIGHT: u32 = 170_000; +const ADDR: &str = "tb1q9pvjqz5u5sdgpatg3wn0ce438u5cyv85lly0pc"; + +#[tokio::main] +async fn main() { + // Add third-party logging + let subscriber = tracing_subscriber::FmtSubscriber::new(); + tracing::subscriber::set_global_default(subscriber).unwrap(); + // Use a predefined checkpoint + let checkpoint = HeaderCheckpoint::closest_checkpoint_below_height(RECOVERY_HEIGHT, NETWORK); + // Add Bitcoin scripts to scan the blockchain for + let address = Address::from_str(ADDR) + .unwrap() + .require_network(NETWORK) + .unwrap() + .into(); + let mut addresses = HashSet::new(); + addresses.insert(address); + // Add preferred peers to connect to + let peer = TrustedPeer::new( + AddrV2::Ipv4(Ipv4Addr::new(23, 137, 57, 100)), + None, + ServiceFlags::P2P_V2, + ); + // Create a new node builder + let builder = NodeBuilder::new(NETWORK); + // Add node preferences and build the node/client + let (node, client) = builder + // Add the peers + .add_peer(peer) + // Only scan blocks strictly after an anchor checkpoint + .anchor_checkpoint(checkpoint) + // The number of connections we would like to maintain + .num_required_peers(1) + // Create the node and client + .build_node() + .unwrap(); + + tokio::task::spawn(async move { node.run().await }); + + let (sender, mut receiver) = client.split(); + // Continually listen for events until the node is synced to its peers. + loop { + if let Ok(message) = receiver.recv().await { + match message { + NodeMessage::Dialog(d) => tracing::info!("{d}"), + NodeMessage::Warning(e) => tracing::warn!("{e}"), + NodeMessage::Synced(_) => break, + NodeMessage::ConnectionsMet => { + tracing::info!("Connected to all required peers"); + } + NodeMessage::IndexedFilter(mut filter) => { + let height = filter.height(); + tracing::info!("Checking filter {}", height); + if filter.contains_any(&addresses).await { + let hash = filter.block_hash(); + tracing::info!("Found script at {}!", hash); + break; + } + } + _ => (), + } + } + } + let _ = sender.shutdown().await; + tracing::info!("Shutting down"); +} diff --git a/example/signet.rs b/example/signet.rs index 68687d8..f33a197 100644 --- a/example/signet.rs +++ b/example/signet.rs @@ -1,6 +1,4 @@ -//! The following configuration is likely a common set-up for most users. -//! New peers are stored in a local database, and the node connects to multiple peers -//! to improve the anonymity set when broadcasting transactions to the Bitcoin network. +//! Usual sync on Signet. use kyoto::core::messages::NodeMessage; use kyoto::{chain::checkpoints::HeaderCheckpoint, core::builder::NodeBuilder}; @@ -13,6 +11,7 @@ use std::{ const NETWORK: Network = Network::Signet; const RECOVERY_HEIGHT: u32 = 170_000; +const ADDR: &str = "tb1q9pvjqz5u5sdgpatg3wn0ce438u5cyv85lly0pc"; #[tokio::main] async fn main() { @@ -22,7 +21,7 @@ async fn main() { // Use a predefined checkpoint let checkpoint = HeaderCheckpoint::closest_checkpoint_below_height(RECOVERY_HEIGHT, NETWORK); // Add Bitcoin scripts to scan the blockchain for - let address = Address::from_str("tb1q9pvjqz5u5sdgpatg3wn0ce438u5cyv85lly0pc") + let address = Address::from_str(ADDR) .unwrap() .require_network(NETWORK) .unwrap() diff --git a/example/testnet4.rs b/example/testnet4.rs index 4c1272e..093d37f 100644 --- a/example/testnet4.rs +++ b/example/testnet4.rs @@ -1,3 +1,5 @@ +//! Usual sync on Testnet. + use kyoto::core::messages::NodeMessage; use kyoto::{chain::checkpoints::HeaderCheckpoint, core::builder::NodeBuilder}; use kyoto::{Address, Network, PeerStoreSizeConfig, TrustedPeer}; diff --git a/example/tor.rs b/example/tor.rs index ac2f2e1..f24e5ae 100644 --- a/example/tor.rs +++ b/example/tor.rs @@ -1,5 +1,6 @@ -//! This example demonstrates a limited resource device running with no default features. -//! Note that, without DNS enabled, at least one peer must be provided when building the node. +//! Kyoto allows for use of the Tor protocol to connect to peers. +//! To do so, the `arti` project is used to build a Tor client. +//! Enable Tor connections via the `tor` feature. use kyoto::chain::checkpoints::SIGNET_HEADER_CP; use kyoto::core::messages::NodeMessage;