Skip to content

Commit 763b9f1

Browse files
authored
Merge pull request #38 from rustaceanrob/8-18-conf
Add `configure_me` dependency for configurations
2 parents de3f7be + 63ec59a commit 763b9f1

File tree

5 files changed

+113
-29
lines changed

5 files changed

+113
-29
lines changed

node/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
name = "node"
33
version = "0.1.0"
44
edition = "2021"
5+
build = "build.rs"
56

67
[dependencies]
78
accumulator = { path = "../accumulator/" }
@@ -11,8 +12,15 @@ hintfile = { path = "../hintfile/" }
1112
network = { path = "../network/" }
1213
p2p = { workspace = true }
1314

15+
configure_me = "0.4.0"
1416
tracing = "0.1"
1517
tracing-subscriber = "0.3"
1618

19+
[build-dependencies]
20+
configure_me_codegen = "0.4.0"
21+
22+
[package.metadata.configure_me]
23+
spec = "config_spec.toml"
24+
1725
[[bin]]
1826
name = "ibd"

node/build.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
extern crate configure_me_codegen;
2+
3+
fn main() -> Result<(), configure_me_codegen::Error> {
4+
configure_me_codegen::build_script_auto()
5+
}

node/config_spec.toml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[[param]]
2+
name = "hintfile"
3+
type = "String"
4+
default = "\"./bitcoin.hints\".into()"
5+
doc = "The path to your `bitcoin.hints` file that will be used for IBD"
6+
7+
[[param]]
8+
name = "blocks_dir"
9+
type = "String"
10+
default = "\"./blockfiles\".into()"
11+
doc = "Directory where you would like to store the bitcoin blocks"
12+
13+
[[param]]
14+
name = "network"
15+
type = "String"
16+
default = "\"bitcoin\".into()"
17+
doc = "The bitcoin network to operate on. Options are `bitcoin` or `signet`"
18+
19+
[[param]]
20+
name = "ping_timeout"
21+
type = "u64"
22+
default = "15"
23+
doc = "The time a peer has to respond to a `ping` message. Pings are sent aggressively throughout IBD to find slow peers."
24+
25+
[[param]]
26+
name = "tcp_timeout"
27+
type = "u64"
28+
default = "2"
29+
doc = "The maximum time to establish a connection"
30+
31+
[[param]]
32+
name = "read_timeout"
33+
type = "u64"
34+
default = "2"
35+
doc = "The maximum time to read from a TCP stream until the connection is killed."
36+
37+
[[param]]
38+
name = "write_timeout"
39+
type = "u64"
40+
default = "2"
41+
doc = "The maximum time to write to a TCP stream until the connection is killed."

node/src/bin/ibd.rs

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,62 @@
11
use std::{
22
fs::File,
3-
path::Path,
3+
path::PathBuf,
44
sync::{mpsc::channel, Arc, Mutex},
5-
time::Instant,
5+
time::{Duration, Instant},
66
};
77

88
use bitcoin::{consensus, BlockHash, Network};
99
use hintfile::Hints;
10-
use kernel::{ChainType, ChainstateManager, ChainstateManagerOptions, ContextBuilder};
10+
use kernel::{ChainstateManager, ChainstateManagerOptions, ContextBuilder};
1111

1212
use node::{
1313
bootstrap_dns, elapsed_time, get_blocks_for_range, hashes_from_chain, sync_block_headers,
14-
AccumulatorState,
14+
AccumulatorState, ChainExt,
1515
};
16+
use p2p::net::TimeoutParams;
1617

17-
const CHAIN_TYPE: ChainType = ChainType::SIGNET;
18-
const NETWORK: Network = Network::Signet;
1918
const TASKS: usize = 256;
20-
const BLOCK_FILE_PATH: &str = "./blockfiles";
19+
const PING_INTERVAL: Duration = Duration::from_secs(15);
20+
21+
configure_me::include_config!();
2122

2223
fn main() {
23-
let mut args = std::env::args();
24-
let _ = args.next();
25-
let hint_path = args.next().expect("Usage: <path_to_hints_file>");
26-
// Logging
24+
let (config, _) = Config::including_optional_config_files::<&[&str]>(&[]).unwrap_or_exit();
25+
let hint_path = config.hintfile;
26+
let blocks_dir = config.blocks_dir;
27+
let network = config
28+
.network
29+
.parse::<Network>()
30+
.expect("invalid network string");
31+
let ping_timeout = Duration::from_secs(config.ping_timeout);
32+
let tcp_timeout = Duration::from_secs(config.tcp_timeout);
33+
let read_timeout = Duration::from_secs(config.read_timeout);
34+
let write_timeout = Duration::from_secs(config.write_timeout);
35+
let mut timeout_conf = TimeoutParams::new();
36+
timeout_conf.read_timeout(read_timeout);
37+
timeout_conf.write_timeout(write_timeout);
38+
timeout_conf.tcp_handshake_timeout(tcp_timeout);
39+
timeout_conf.ping_interval(PING_INTERVAL);
2740
let subscriber = tracing_subscriber::FmtSubscriber::new();
2841
tracing::subscriber::set_global_default(subscriber).unwrap();
2942
let hintfile_start_time = Instant::now();
3043
tracing::info!("Reading in {hint_path}");
3144
let mut hintfile = File::open(hint_path).expect("invalid hintfile path");
3245
let hints = Arc::new(Hints::from_file(&mut hintfile));
3346
elapsed_time(hintfile_start_time);
34-
let block_file_path = Path::new(BLOCK_FILE_PATH);
35-
std::fs::create_dir(block_file_path).expect("could not create block file directory");
47+
let block_file_path = PathBuf::from(&blocks_dir);
48+
std::fs::create_dir(&block_file_path).expect("could not create block file directory");
3649
let stop_hash =
3750
consensus::deserialize::<BlockHash>(&hints.stop_hash()).expect("stop hash is not valid");
3851
tracing::info!("Assume valid hash: {stop_hash}");
3952
tracing::info!("Finding peers with DNS");
4053
let dns_start_time = Instant::now();
41-
let peers = bootstrap_dns(NETWORK);
54+
let peers = bootstrap_dns(network);
4255
elapsed_time(dns_start_time);
4356
tracing::info!("Initializing bitcoin kernel");
4457
let kernel_start_time = Instant::now();
4558
let ctx = ContextBuilder::new()
46-
.chain_type(CHAIN_TYPE)
59+
.chain_type(network.chain_type())
4760
.build()
4861
.unwrap();
4962
let options = ChainstateManagerOptions::new(&ctx, ".", "./blocks").unwrap();
@@ -52,7 +65,7 @@ fn main() {
5265
let tip = chainman.best_header().height();
5366
tracing::info!("Kernel best header: {tip}");
5467
let chain = Arc::new(chainman);
55-
sync_block_headers(stop_hash, &peers, Arc::clone(&chain), NETWORK);
68+
sync_block_headers(stop_hash, &peers, Arc::clone(&chain), network, timeout_conf);
5669
tracing::info!("Assume valid height: {}", chain.best_header().height());
5770
let (tx, rx) = channel();
5871
let main_routine_time = Instant::now();
@@ -67,11 +80,14 @@ fn main() {
6780
let tx = tx.clone();
6881
let peers = Arc::clone(&peers);
6982
let hints = Arc::clone(&hints);
83+
let block_file_path = block_file_path.clone();
7084
let block_task = std::thread::spawn(move || {
7185
get_blocks_for_range(
7286
task_id as u32,
73-
NETWORK,
74-
block_file_path,
87+
timeout_conf,
88+
ping_timeout,
89+
network,
90+
&block_file_path,
7591
chain,
7692
&hints,
7793
peers,

node/src/lib.rs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use bitcoin::{
2020
BlockHash, Network, OutPoint,
2121
};
2222
use hintfile::Hints;
23-
use kernel::ChainstateManager;
23+
use kernel::{ChainType, ChainstateManager};
2424
use network::dns::DnsQuery;
2525
use p2p::{
2626
handshake::ConnectionConfig,
@@ -79,6 +79,7 @@ pub fn sync_block_headers(
7979
hosts: &[SocketAddr],
8080
chainman: Arc<ChainstateManager>,
8181
network: Network,
82+
timeout_params: TimeoutParams,
8283
) {
8384
let mut rng = thread_rng();
8485
let then = Instant::now();
@@ -89,13 +90,10 @@ pub fn sync_block_headers(
8990
.copied()
9091
.expect("dns must return at least one peer");
9192
tracing::info!("Attempting connection to {random}");
92-
let mut timeout_conf = TimeoutParams::new();
93-
timeout_conf.read_timeout(Duration::from_secs(2));
94-
timeout_conf.write_timeout(Duration::from_secs(2));
9593
let conn = ConnectionConfig::new()
9694
.change_network(network)
9795
.decrease_version_requirement(ProtocolVersion::BIP0031_VERSION)
98-
.open_connection(random, timeout_conf);
96+
.open_connection(random, timeout_params);
9997
let (writer, mut reader, metrics) = match conn {
10098
Ok((writer, reader, metrics)) => (writer, reader, metrics),
10199
Err(_) => continue,
@@ -153,6 +151,8 @@ pub fn sync_block_headers(
153151
#[allow(clippy::too_many_arguments)]
154152
pub fn get_blocks_for_range(
155153
task_id: u32,
154+
timeout_params: TimeoutParams,
155+
ping_timeout: Duration,
156156
network: Network,
157157
block_dir: &Path,
158158
chain: Arc<ChainstateManager>,
@@ -161,10 +161,6 @@ pub fn get_blocks_for_range(
161161
updater: Sender<AccumulatorUpdate>,
162162
mut batch: Vec<BlockHash>,
163163
) {
164-
let mut timeout = TimeoutParams::new();
165-
timeout.read_timeout(Duration::from_secs(2));
166-
timeout.tcp_handshake_timeout(Duration::from_secs(2));
167-
timeout.ping_interval(Duration::from_secs(15));
168164
let mut rng = thread_rng();
169165
loop {
170166
let peer = {
@@ -179,7 +175,7 @@ pub fn get_blocks_for_range(
179175
.request_addr()
180176
.set_service_requirement(ServiceFlags::NETWORK)
181177
.decrease_version_requirement(ProtocolVersion::BIP0031_VERSION)
182-
.open_connection(peer, timeout);
178+
.open_connection(peer, timeout_params);
183179
let Ok((writer, mut reader, metrics)) = conn else {
184180
// tracing::warn!("Connection failed");
185181
continue;
@@ -269,7 +265,7 @@ pub fn get_blocks_for_range(
269265
_ => (),
270266
}
271267
if let Some(message_rate) = metrics.message_rate(TimedMessage::Block) {
272-
if message_rate.total_count() < 2 {
268+
if message_rate.total_count() < 100 {
273269
continue;
274270
}
275271
let Some(rate) = message_rate.messages_per_secs(Instant::now()) else {
@@ -280,6 +276,10 @@ pub fn get_blocks_for_range(
280276
break;
281277
}
282278
}
279+
if metrics.ping_timed_out(ping_timeout) {
280+
tracing::info!("{task_id} failed to respond to a ping");
281+
break;
282+
}
283283
}
284284
if batch.is_empty() {
285285
break;
@@ -304,3 +304,17 @@ pub fn hashes_from_chain(chain: Arc<ChainstateManager>, chunks: usize) -> Vec<Ve
304304
}
305305
hashes.chunks(chunks).map(|slice| slice.to_vec()).collect()
306306
}
307+
308+
pub trait ChainExt {
309+
fn chain_type(&self) -> ChainType;
310+
}
311+
312+
impl ChainExt for Network {
313+
fn chain_type(&self) -> ChainType {
314+
match self {
315+
Network::Bitcoin => ChainType::MAINNET,
316+
Network::Signet => ChainType::SIGNET,
317+
_ => unimplemented!("choose bitcoin or signet"),
318+
}
319+
}
320+
}

0 commit comments

Comments
 (0)