From cbe4766797864bfe1e01b516d980927ba0b3e54d Mon Sep 17 00:00:00 2001 From: rustaceanrob Date: Tue, 10 Mar 2026 10:28:17 +0000 Subject: [PATCH] feat: Optionally request witness data Some applications like lightning network clients require witnesses. This provides an opt-in feature on the builder to do so. Co-authored-by: Alexander Shevtsov --- examples/bitcoin.rs | 2 ++ src/builder.rs | 8 +++++++- src/lib.rs | 9 +++++++++ src/network/outbound.rs | 8 ++++++-- src/network/peer.rs | 7 ++++++- src/network/peer_map.rs | 6 +++++- src/node.rs | 2 ++ 7 files changed, 37 insertions(+), 5 deletions(-) diff --git a/examples/bitcoin.rs b/examples/bitcoin.rs index 04f0233d..8f4bf474 100644 --- a/examples/bitcoin.rs +++ b/examples/bitcoin.rs @@ -34,6 +34,8 @@ async fn main() { .add_peers(seeds.into_iter().map(From::from)) // Connections over Tor are supported by Socks5 proxy // .socks5_proxy(bip157::Socks5Proxy::local()) + // Optionally request witness data when fetching a block + // .fetch_witness_data() // Create the node and client .build(); // Run the node on a separate task diff --git a/src/builder.rs b/src/builder.rs index 3af2073a..8040b15c 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -5,7 +5,7 @@ use bitcoin::Network; use super::{client::Client, node::Node}; use crate::chain::ChainState; use crate::network::ConnectionType; -use crate::{Config, FilterType}; +use crate::{BlockType, Config, FilterType}; use crate::{Socks5Proxy, TrustedPeer}; const MIN_PEERS: u8 = 1; @@ -137,6 +137,12 @@ impl Builder { self } + /// Request witness data when requesting blocks. + pub fn fetch_witness_data(mut self) -> Self { + self.config.block_type = BlockType::Witness; + self + } + /// Consume the node builder and receive a [`Node`] and [`Client`]. pub fn build(mut self) -> (Node, Client) { Node::new(self.network, core::mem::take(&mut self.config)) diff --git a/src/lib.rs b/src/lib.rs index c4315a81..2af34ffe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,6 +119,13 @@ pub enum FilterType { Basic, } +#[derive(Debug, Clone, Copy, Default)] +enum BlockType { + #[default] + Legacy, + Witness, +} + impl From for u8 { fn from(value: FilterType) -> Self { match value { @@ -335,6 +342,7 @@ struct Config { connection_type: ConnectionType, peer_timeout_config: PeerTimeoutConfig, filter_type: FilterType, + block_type: BlockType, } impl Default for Config { @@ -347,6 +355,7 @@ impl Default for Config { connection_type: Default::default(), peer_timeout_config: PeerTimeoutConfig::default(), filter_type: FilterType::default(), + block_type: BlockType::default(), } } } diff --git a/src/network/outbound.rs b/src/network/outbound.rs index 48b47eaf..f3a1a0f7 100644 --- a/src/network/outbound.rs +++ b/src/network/outbound.rs @@ -15,7 +15,7 @@ use bitcoin::{ BlockHash, Network, Transaction, Wtxid, }; -use crate::default_port_from_network; +use crate::{default_port_from_network, BlockType}; use super::{KYOTO_VERSION, PROTOCOL_VERSION, RUST_BITCOIN_VERSION}; @@ -23,6 +23,7 @@ use super::{KYOTO_VERSION, PROTOCOL_VERSION, RUST_BITCOIN_VERSION}; pub(in crate::network) struct MessageGenerator { pub network: Network, pub transport: Transport, + pub block_type: BlockType, } pub(in crate::network) enum Transport { @@ -50,7 +51,10 @@ impl MessageGenerator { } pub(in crate::network) fn block(&mut self, hash: BlockHash) -> Vec { - let inv = Inventory::Block(hash); + let inv = match self.block_type { + BlockType::Legacy => Inventory::Block(hash), + BlockType::Witness => Inventory::WitnessBlock(hash), + }; let msg = NetworkMessage::GetData(vec![inv]); self.serialize(msg) } diff --git a/src/network/peer.rs b/src/network/peer.rs index 34a18877..e8c40208 100644 --- a/src/network/peer.rs +++ b/src/network/peer.rs @@ -18,7 +18,7 @@ use tokio::{ time::{Instant, MissedTickBehavior}, }; -use crate::{broadcaster::BroadcastQueue, messages::Warning, Dialog, Info}; +use crate::{broadcaster::BroadcastQueue, messages::Warning, BlockType, Dialog, Info}; use super::{ error::PeerError, @@ -38,6 +38,7 @@ pub(crate) struct Peer { main_thread_sender: Sender, main_thread_recv: Receiver, network: Network, + block_type: BlockType, dialog: Arc, db: Arc>, timeout_config: PeerTimeoutConfig, @@ -51,6 +52,7 @@ impl Peer { nonce: PeerId, source: Record, network: Network, + block_type: BlockType, main_thread_sender: Sender, main_thread_recv: Receiver, dialog: Arc, @@ -64,6 +66,7 @@ impl Peer { main_thread_sender, main_thread_recv, network, + block_type, dialog, db, timeout_config, @@ -97,6 +100,7 @@ impl Peer { let outbound_messages = MessageGenerator { network: self.network, transport: Transport::V2 { encryptor }, + block_type: self.block_type, }; let reader = Reader::new(MessageParser::V2(reader, decryptor), tx); (outbound_messages, reader) @@ -104,6 +108,7 @@ impl Peer { let outbound_messages = MessageGenerator { network: self.network, transport: Transport::V1, + block_type: self.block_type, }; let reader = Reader::new(MessageParser::V1(reader, self.network), tx); (outbound_messages, reader) diff --git a/src/network/peer_map.rs b/src/network/peer_map.rs index dbc6f442..9416c624 100644 --- a/src/network/peer_map.rs +++ b/src/network/peer_map.rs @@ -25,7 +25,7 @@ use crate::{ chain::HeightMonitor, default_port_from_network, network::{dns::bootstrap_dns, error::PeerError, peer::Peer, PeerId, PeerTimeoutConfig}, - Dialog, TrustedPeer, + BlockType, Dialog, TrustedPeer, }; use super::{AddressBook, ConnectionType, MainThreadMessage, PeerThreadMessage}; @@ -51,6 +51,7 @@ pub(crate) struct PeerMap { current_id: PeerId, heights: Arc>, network: Network, + block_type: BlockType, mtx: Sender, map: HashMap, db: Arc>, @@ -65,6 +66,7 @@ impl PeerMap { pub fn new( mtx: Sender, network: Network, + block_type: BlockType, whitelist: Whitelist, dialog: Arc, connection_type: ConnectionType, @@ -76,6 +78,7 @@ impl PeerMap { current_id: PeerId(0), heights: height_monitor, network, + block_type, mtx, map: HashMap::new(), db: Arc::new(Mutex::new(AddressBook::new())), @@ -122,6 +125,7 @@ impl PeerMap { self.current_id, loaded_peer.clone(), self.network, + self.block_type, self.mtx.clone(), prx, Arc::clone(&self.dialog), diff --git a/src/node.rs b/src/node.rs index fcca2e8a..8e8d226e 100644 --- a/src/node.rs +++ b/src/node.rs @@ -75,6 +75,7 @@ impl Node { connection_type, peer_timeout_config, filter_type, + block_type, } = config; // Set up a communication channel between the node and client let (info_tx, info_rx) = mpsc::channel::(32); @@ -92,6 +93,7 @@ impl Node { let peer_map = PeerMap::new( mtx, network, + block_type, white_list, Arc::clone(&dialog), connection_type,