Skip to content

Commit 54a7412

Browse files
authored
Merge pull request #6405 from obycode/feat/btc-indexer-timeout
feat: make Bitcoin indexer use timeout from config
2 parents ed22100 + 1700547 commit 54a7412

File tree

5 files changed

+91
-38
lines changed

5 files changed

+91
-38
lines changed

stacks-node/Stacks.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ rpc_bind = "127.0.0.1:20443"
2121
# rpc_ssl = false
2222
# username = "helium-node"
2323
# password = "secret"
24-
# timeout = 30
24+
# timeout = 300
25+
# socket_timeout = 30
2526
# local_mining_public_key = "04ee0b1602eb18fef7986887a7e8769a30c9df981d33c8380d255edef003abdcd243a0eb74afdf6740e6c423e62aec631519a24cf5b1d62bf8a3e06ddc695dcb77"
2627
# satoshis_per_byte = 50
2728
# commit_anchor_block_within = 3000

stacks-node/src/burnchains/bitcoin_regtest_controller.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ pub fn make_bitcoin_indexer(
170170
username: burnchain_config.username,
171171
password: burnchain_config.password,
172172
timeout: burnchain_config.timeout,
173+
socket_timeout: burnchain_config.socket_timeout,
173174
spv_headers_path: config.get_spv_headers_file_path(),
174175
first_block: burnchain_params.first_block_height,
175176
magic_bytes: burnchain_config.magic_bytes,
@@ -178,7 +179,7 @@ pub fn make_bitcoin_indexer(
178179
};
179180

180181
let (_, network_type) = config.burnchain.get_bitcoin_network();
181-
let indexer_runtime = BitcoinIndexerRuntime::new(network_type);
182+
let indexer_runtime = BitcoinIndexerRuntime::new(network_type, indexer_config.timeout);
182183
BitcoinIndexer {
183184
config: indexer_config,
184185
runtime: indexer_runtime,
@@ -331,6 +332,7 @@ impl BitcoinRegtestController {
331332
username: burnchain_config.username,
332333
password: burnchain_config.password,
333334
timeout: burnchain_config.timeout,
335+
socket_timeout: burnchain_config.socket_timeout,
334336
spv_headers_path: config.get_spv_headers_file_path(),
335337
first_block: burnchain_params.first_block_height,
336338
magic_bytes: burnchain_config.magic_bytes,
@@ -339,7 +341,7 @@ impl BitcoinRegtestController {
339341
};
340342

341343
let (_, network_type) = config.burnchain.get_bitcoin_network();
342-
let indexer_runtime = BitcoinIndexerRuntime::new(network_type);
344+
let indexer_runtime = BitcoinIndexerRuntime::new(network_type, config.burnchain.timeout);
343345
let burnchain_indexer = BitcoinIndexer {
344346
config: indexer_config,
345347
runtime: indexer_runtime,
@@ -376,6 +378,7 @@ impl BitcoinRegtestController {
376378
username: burnchain_config.username,
377379
password: burnchain_config.password,
378380
timeout: burnchain_config.timeout,
381+
socket_timeout: burnchain_config.socket_timeout,
379382
spv_headers_path: config.get_spv_headers_file_path(),
380383
first_block: burnchain_params.first_block_height,
381384
magic_bytes: burnchain_config.magic_bytes,
@@ -384,7 +387,7 @@ impl BitcoinRegtestController {
384387
};
385388

386389
let (_, network_type) = config.burnchain.get_bitcoin_network();
387-
let indexer_runtime = BitcoinIndexerRuntime::new(network_type);
390+
let indexer_runtime = BitcoinIndexerRuntime::new(network_type, config.burnchain.timeout);
388391
let burnchain_indexer = BitcoinIndexer {
389392
config: indexer_config,
390393
runtime: indexer_runtime,

stacks-node/src/burnchains/rpc/bitcoin_rpc_client/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,14 +405,14 @@ impl BitcoinRpcClient {
405405
port: u16,
406406
auth: RpcAuth,
407407
wallet_name: String,
408-
timeout: u32,
408+
timeout: u64,
409409
client_id: String,
410410
) -> BitcoinRpcClientResult<Self> {
411411
let rpc_global_path = format!("http://{host}:{port}");
412412
let rpc_wallet_path = format!("{rpc_global_path}/wallet/{wallet_name}");
413413
let rpc_auth = auth;
414414

415-
let rpc_timeout = Duration::from_secs(u64::from(timeout));
415+
let rpc_timeout = Duration::from_secs(timeout);
416416

417417
let global_ep =
418418
RpcTransport::new(rpc_global_path, rpc_auth.clone(), Some(rpc_timeout.clone()))?;

stackslib/src/burnchains/bitcoin/indexer.rs

Lines changed: 65 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -102,17 +102,29 @@ pub fn get_bitcoin_stacks_epochs(network_id: BitcoinNetworkType) -> EpochList {
102102

103103
#[derive(Debug, Clone, PartialEq)]
104104
pub struct BitcoinIndexerConfig {
105-
// config fields
105+
/// Hostname or IP address of the Bitcoin node
106106
pub peer_host: String,
107+
/// Port number of the Bitcoin node
107108
pub peer_port: u16,
109+
/// Port number of the Bitcoin RPC interface
108110
pub rpc_port: u16,
111+
/// Whether to use SSL for the RPC interface
109112
pub rpc_ssl: bool,
113+
/// Username for the RPC interface
110114
pub username: Option<String>,
115+
/// Password for the RPC interface
111116
pub password: Option<String>,
112-
pub timeout: u32,
117+
/// Timeout for high-level message operations
118+
pub timeout: u64,
119+
/// Timeout for socket read/write operations
120+
pub socket_timeout: u64,
121+
/// Path to the SPV headers database
113122
pub spv_headers_path: String,
123+
/// The first block to index
114124
pub first_block: u64,
125+
/// Magic bytes for Stacks operations
115126
pub magic_bytes: MagicBytes,
127+
/// The epochs for this network
116128
pub epochs: Option<EpochList>,
117129
}
118130

@@ -144,7 +156,8 @@ impl BitcoinIndexerConfig {
144156
rpc_ssl: false,
145157
username: Some("blockstack".to_string()),
146158
password: Some("blockstacksystem".to_string()),
147-
timeout: 30,
159+
timeout: 300,
160+
socket_timeout: 30,
148161
spv_headers_path: "./headers.sqlite".to_string(),
149162
first_block,
150163
magic_bytes: BLOCKSTACK_MAGIC_MAINNET.clone(),
@@ -160,7 +173,8 @@ impl BitcoinIndexerConfig {
160173
rpc_ssl: false,
161174
username: Some("blockstack".to_string()),
162175
password: Some("blockstacksystem".to_string()),
163-
timeout: 30,
176+
timeout: 300,
177+
socket_timeout: 30,
164178
spv_headers_path,
165179
first_block: 0,
166180
magic_bytes: BLOCKSTACK_MAGIC_MAINNET.clone(),
@@ -177,7 +191,8 @@ impl BitcoinIndexerConfig {
177191
rpc_ssl: false,
178192
username: Some("blockstack".to_string()),
179193
password: Some("blockstacksystem".to_string()),
180-
timeout: 30,
194+
timeout: 300,
195+
socket_timeout: 30,
181196
spv_headers_path,
182197
first_block: 0,
183198
magic_bytes: BLOCKSTACK_MAGIC_MAINNET.clone(),
@@ -187,7 +202,7 @@ impl BitcoinIndexerConfig {
187202
}
188203

189204
impl BitcoinIndexerRuntime {
190-
pub fn new(network_id: BitcoinNetworkType) -> BitcoinIndexerRuntime {
205+
pub fn new(network_id: BitcoinNetworkType, timeout: u64) -> BitcoinIndexerRuntime {
191206
let mut rng = thread_rng();
192207
BitcoinIndexerRuntime {
193208
sock: None,
@@ -198,7 +213,7 @@ impl BitcoinIndexerRuntime {
198213
block_height: 0,
199214
last_getdata_send_time: 0,
200215
last_getheaders_send_time: 0,
201-
timeout: 300,
216+
timeout,
202217
}
203218
}
204219
}
@@ -237,19 +252,23 @@ impl BitcoinIndexer {
237252
)
238253
.unwrap_or_else(|_| panic!("Failed to open {working_dir_path:?}"));
239254

255+
let config =
256+
BitcoinIndexerConfig::default_regtest(working_dir_path.to_str().unwrap().to_string());
257+
let timeout = config.timeout;
240258
BitcoinIndexer {
241-
config: BitcoinIndexerConfig::default_regtest(
242-
working_dir_path.to_str().unwrap().to_string(),
243-
),
244-
runtime: BitcoinIndexerRuntime::new(BitcoinNetworkType::Regtest),
259+
config,
260+
runtime: BitcoinIndexerRuntime::new(BitcoinNetworkType::Regtest, timeout),
245261
should_keep_running: None,
246262
}
247263
}
248264

249265
pub fn dup(&self) -> BitcoinIndexer {
250266
BitcoinIndexer {
251267
config: self.config.clone(),
252-
runtime: BitcoinIndexerRuntime::new(self.runtime.network_id),
268+
runtime: BitcoinIndexerRuntime::new(
269+
self.runtime.network_id,
270+
self.config.timeout.into(),
271+
),
253272
should_keep_running: self.should_keep_running.clone(),
254273
}
255274
}
@@ -268,13 +287,13 @@ impl BitcoinIndexer {
268287
})?;
269288

270289
// set timeout
271-
s.set_read_timeout(Some(Duration::from_secs(self.runtime.timeout)))
290+
s.set_read_timeout(Some(Duration::from_secs(self.config.socket_timeout)))
272291
.map_err(|_e| {
273292
test_debug!("Failed to set TCP read timeout: {_e:?}");
274293
btc_error::ConnectionError
275294
})?;
276295

277-
s.set_write_timeout(Some(Duration::from_secs(self.runtime.timeout)))
296+
s.set_write_timeout(Some(Duration::from_secs(self.config.socket_timeout)))
278297
.map_err(|_e| {
279298
test_debug!("Failed to set TCP write timeout: {_e:?}");
280299
btc_error::ConnectionError
@@ -1334,9 +1353,11 @@ mod test {
13341353

13351354
assert_eq!(spv_client_reorg.read_block_headers(2, 10).unwrap().len(), 2);
13361355

1356+
let config = BitcoinIndexerConfig::test_default(path_1.to_string());
1357+
let timeout = config.timeout;
13371358
let mut indexer = BitcoinIndexer::new(
1338-
BitcoinIndexerConfig::test_default(path_1.to_string()),
1339-
BitcoinIndexerRuntime::new(BitcoinNetworkType::Regtest),
1359+
config,
1360+
BitcoinIndexerRuntime::new(BitcoinNetworkType::Regtest, timeout),
13401361
None,
13411362
);
13421363
let common_ancestor_height = indexer
@@ -1507,9 +1528,11 @@ mod test {
15071528

15081529
assert_eq!(spv_client_reorg.read_block_headers(2, 10).unwrap().len(), 2);
15091530

1531+
let config = BitcoinIndexerConfig::test_default(path_1.to_string());
1532+
let timeout = config.timeout;
15101533
let mut indexer = BitcoinIndexer::new(
1511-
BitcoinIndexerConfig::test_default(path_1.to_string()),
1512-
BitcoinIndexerRuntime::new(BitcoinNetworkType::Regtest),
1534+
config,
1535+
BitcoinIndexerRuntime::new(BitcoinNetworkType::Regtest, timeout),
15131536
None,
15141537
);
15151538
let common_ancestor_height = indexer
@@ -1583,7 +1606,8 @@ mod test {
15831606
rpc_ssl: false,
15841607
username: Some("blockstack".to_string()),
15851608
password: Some("blockstacksystem".to_string()),
1586-
timeout: 30,
1609+
timeout: 300,
1610+
socket_timeout: 30,
15871611
spv_headers_path: db_path.to_string(),
15881612
first_block: 0,
15891613
magic_bytes: MagicBytes([105, 100]),
@@ -1594,7 +1618,12 @@ mod test {
15941618
fs::remove_file(&indexer_conf.spv_headers_path).unwrap();
15951619
}
15961620

1597-
let mut indexer = BitcoinIndexer::new(indexer_conf, BitcoinIndexerRuntime::new(mode), None);
1621+
let timeout = indexer_conf.timeout;
1622+
let mut indexer = BitcoinIndexer::new(
1623+
indexer_conf,
1624+
BitcoinIndexerRuntime::new(mode, timeout),
1625+
None,
1626+
);
15981627
let last_block = indexer.sync_headers(0, None).unwrap();
15991628
eprintln!("sync'ed to block {}", last_block);
16001629

@@ -3162,9 +3191,11 @@ mod test {
31623191
},
31633192
];
31643193

3194+
let config = BitcoinIndexerConfig::test_default(db_path.to_string());
3195+
let timeout = config.timeout;
31653196
let mut indexer = BitcoinIndexer::new(
3166-
BitcoinIndexerConfig::test_default(db_path.to_string()),
3167-
BitcoinIndexerRuntime::new(BitcoinNetworkType::Mainnet),
3197+
config,
3198+
BitcoinIndexerRuntime::new(BitcoinNetworkType::Mainnet, timeout),
31683199
None,
31693200
);
31703201

@@ -3323,9 +3354,11 @@ mod test {
33233354
let total_work_before_idempotent = spv_client.update_chain_work().unwrap();
33243355
assert_eq!(total_work_before, total_work_before_idempotent);
33253356

3357+
let config = BitcoinIndexerConfig::test_default(db_path.to_string());
3358+
let timeout = config.timeout;
33263359
let mut indexer = BitcoinIndexer::new(
3327-
BitcoinIndexerConfig::test_default(db_path.to_string()),
3328-
BitcoinIndexerRuntime::new(BitcoinNetworkType::Mainnet),
3360+
config,
3361+
BitcoinIndexerRuntime::new(BitcoinNetworkType::Mainnet, timeout),
33293362
None,
33303363
);
33313364

@@ -3462,9 +3495,11 @@ mod test {
34623495
spv_client.test_write_block_headers(0, headers).unwrap();
34633496
assert_eq!(spv_client.get_highest_header_height().unwrap(), 2);
34643497

3498+
let config = BitcoinIndexerConfig::test_default(db_path.to_string());
3499+
let timeout = config.timeout;
34653500
let mut indexer = BitcoinIndexer::new(
3466-
BitcoinIndexerConfig::test_default(db_path.to_string()),
3467-
BitcoinIndexerRuntime::new(BitcoinNetworkType::Regtest),
3501+
config,
3502+
BitcoinIndexerRuntime::new(BitcoinNetworkType::Regtest, timeout),
34683503
None,
34693504
);
34703505

@@ -3489,9 +3524,11 @@ mod test {
34893524
}
34903525

34913526
let should_keep_running = Arc::new(AtomicBool::new(true));
3527+
let config = BitcoinIndexerConfig::test_default(db_path);
3528+
let timeout = config.timeout;
34923529
let mut indexer = BitcoinIndexer::new(
3493-
BitcoinIndexerConfig::test_default(db_path),
3494-
BitcoinIndexerRuntime::new(BitcoinNetworkType::Mainnet),
3530+
config,
3531+
BitcoinIndexerRuntime::new(BitcoinNetworkType::Mainnet, timeout),
34953532
Some(should_keep_running.clone()),
34963533
);
34973534

stackslib/src/config/mod.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,9 +1348,15 @@ pub struct BurnchainConfig {
13481348
/// Timeout duration, in seconds, for RPC calls made to the bitcoin node.
13491349
/// Configures the timeout on the underlying HTTP client.
13501350
/// ---
1351-
/// @default: `60`
1351+
/// @default: `300`
13521352
/// @units: seconds
1353-
pub timeout: u32,
1353+
pub timeout: u64,
1354+
/// Timeout duration, in seconds, for socket operations (read/write) with the bitcoin node.
1355+
/// Controls how long the node will wait for socket operations to complete before timing out.
1356+
/// ---
1357+
/// @default: `30`
1358+
/// @units: seconds
1359+
pub socket_timeout: u64,
13541360
/// The network "magic bytes" used to identify packets for the specific bitcoin
13551361
/// network instance (e.g., mainnet, testnet, regtest). Must match the magic
13561362
/// bytes of the connected bitcoin node.
@@ -1651,7 +1657,8 @@ impl BurnchainConfig {
16511657
rpc_ssl: false,
16521658
username: None,
16531659
password: None,
1654-
timeout: 60,
1660+
timeout: 300,
1661+
socket_timeout: 30,
16551662
magic_bytes: BLOCKSTACK_MAGIC_MAINNET,
16561663
local_mining_public_key: None,
16571664
process_exit_at_block_height: None,
@@ -1752,7 +1759,9 @@ pub struct BurnchainConfigFile {
17521759
pub username: Option<String>,
17531760
pub password: Option<String>,
17541761
/// Timeout, in seconds, for communication with bitcoind
1755-
pub timeout: Option<u32>,
1762+
pub timeout: Option<u64>,
1763+
/// Socket timeout, in seconds, for socket operations with bitcoind
1764+
pub socket_timeout: Option<u64>,
17561765
pub magic_bytes: Option<String>,
17571766
pub local_mining_public_key: Option<String>,
17581767
pub process_exit_at_block_height: Option<u64>,
@@ -1940,6 +1949,9 @@ impl BurnchainConfigFile {
19401949
username: self.username,
19411950
password: self.password,
19421951
timeout: self.timeout.unwrap_or(default_burnchain_config.timeout),
1952+
socket_timeout: self
1953+
.socket_timeout
1954+
.unwrap_or(default_burnchain_config.socket_timeout),
19431955
magic_bytes: self
19441956
.magic_bytes
19451957
.map(|magic_ascii| {

0 commit comments

Comments
 (0)