Skip to content

Commit f45006d

Browse files
committed
add skip_blocks to rpc blockchain
1 parent 3b024f4 commit f45006d

File tree

1 file changed

+52
-10
lines changed

1 file changed

+52
-10
lines changed

src/blockchain/rpc.rs

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ pub struct RpcBlockchain {
4444
wallet_name: String,
4545
/// This is a fixed Address used as a key to store information on the node
4646
satoshi_address: Address,
47+
/// Skip this many blocks of the blockchain at the first rescan, if None the rescan is done from the genesis block
48+
skip_blocks: Option<u32>,
4749
}
4850

4951
/// RpcBlockchain configuration options
@@ -57,15 +59,19 @@ pub struct RpcConfig {
5759
pub network: Network,
5860
/// The wallet name in the bitcoin node, consider using [wallet_name_from_descriptor] for this
5961
pub wallet_name: String,
62+
/// Skip this many blocks of the blockchain at the first rescan, if None the rescan is done from the genesis block
63+
pub skip_blocks: Option<u32>,
6064
}
6165

6266
impl RpcBlockchain {
6367
fn get_node_synced_height(&self) -> Result<u32, Error> {
6468
let info = self.client.get_address_info(&self.satoshi_address)?;
6569
if let Some(GetAddressInfoResultLabel::Simple(label)) = info.labels.first() {
66-
Ok(label.parse::<u32>().unwrap_or(0))
70+
Ok(label
71+
.parse::<u32>()
72+
.unwrap_or(self.skip_blocks.unwrap_or(0)))
6773
} else {
68-
Ok(0)
74+
Ok(self.skip_blocks.unwrap_or(0))
6975
}
7076
}
7177

@@ -124,7 +130,13 @@ impl Blockchain for RpcBlockchain {
124130

125131
//TODO if current_height == node_synced should check only the mempool
126132

127-
//TODO if it's a big rescan, spawn a thread that checks getwalletinfo and update progress
133+
//TODO if it's a big rescan, spawn a thread that checks getwalletinfo and update progress?
134+
// maybe better to call rescan in chunks (updating node_synced_height) so that in case of
135+
// interruption work can be partially recovered
136+
debug!(
137+
"rescan_blockchain from:{} to:{}",
138+
node_synced, current_height
139+
);
128140
self.client
129141
.rescan_blockchain(Some(node_synced as usize), Some(current_height as usize))?;
130142
progress_update.update(1.0, None)?;
@@ -137,7 +149,9 @@ impl Blockchain for RpcBlockchain {
137149
let known_utxos: HashSet<_> = db.iter_utxos()?.into_iter().collect();
138150

139151
//TODO list_since_blocks would be more efficient
140-
let current_utxo = self.client.list_unspent(Some(0), None, None, None, None)?;
152+
let current_utxo = self
153+
.client
154+
.list_unspent(Some(0), None, None, Some(true), None)?;
141155
debug!("current_utxo len {}", current_utxo.len());
142156
let current_txs = self
143157
.client
@@ -299,6 +313,7 @@ impl ConfigurableBlockchain for RpcBlockchain {
299313
capabilities,
300314
wallet_name,
301315
satoshi_address,
316+
skip_blocks: config.skip_blocks.clone(),
302317
})
303318
}
304319
}
@@ -359,6 +374,7 @@ fn local_rpc() -> RpcBlockchain {
359374
auth: Auth::CookieFile(bitcoind.cookie_file.clone()),
360375
network: Network::Regtest,
361376
wallet_name: "bdk-test".to_string(),
377+
skip_blocks: None,
362378
};
363379
RpcBlockchain::from_config(&config).unwrap()
364380
}
@@ -395,6 +411,7 @@ mod test {
395411
auth: Auth::CookieFile(bitcoind.cookie_file.clone()),
396412
network,
397413
wallet_name,
414+
skip_blocks: None,
398415
};
399416
RpcBlockchain::from_config(&config)
400417
}
@@ -412,8 +429,7 @@ mod test {
412429
let node_address = bitcoind.client.get_new_address(None, None).unwrap();
413430
let blockchain = create_rpc(&bitcoind, DESCRIPTOR_PUB, Network::Regtest).unwrap();
414431
let db = MemoryDatabase::new();
415-
let wallet =
416-
Wallet::new(DESCRIPTOR_PRIV, None, Network::Regtest, db, blockchain).unwrap();
432+
let wallet = Wallet::new(DESCRIPTOR_PRIV, None, Network::Regtest, db, blockchain).unwrap();
417433

418434
wallet.sync(noop_progress(), None).unwrap();
419435
generate(&bitcoind, 101);
@@ -425,13 +441,40 @@ mod test {
425441

426442
let mut builder = wallet.build_tx();
427443
builder.add_recipient(node_address.script_pubkey(), 50_000);
428-
let (mut psbt, details) = builder.finish().unwrap();
444+
let (mut psbt, details) = builder.finish().unwrap();
429445
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
430446
assert!(finalized, "Cannot finalize transaction");
431447
let tx = psbt.extract_tx();
432448
wallet.broadcast(tx).unwrap();
433449
wallet.sync(noop_progress(), None).unwrap();
434-
assert_eq!(wallet.get_balance().unwrap(), 100_000 - 50_000 - details.fees);
450+
assert_eq!(
451+
wallet.get_balance().unwrap(),
452+
100_000 - 50_000 - details.fees
453+
);
454+
drop(wallet);
455+
456+
// test skip_blocks
457+
generate(&bitcoind, 5);
458+
let config = RpcConfig {
459+
url: bitcoind.url.clone(),
460+
auth: Auth::CookieFile(bitcoind.cookie_file.clone()),
461+
network: Network::Regtest,
462+
wallet_name: "another-name".to_string(),
463+
skip_blocks: Some(103),
464+
};
465+
let blockchain_skip = RpcBlockchain::from_config(&config).unwrap();
466+
let db = MemoryDatabase::new();
467+
let wallet_skip =
468+
Wallet::new(DESCRIPTOR_PRIV, None, Network::Regtest, db, blockchain_skip).unwrap();
469+
send_to_address(&bitcoind, &address, 100_000);
470+
assert_eq!(
471+
"bcrt1q8dyvgt4vhr8ald4xuwewcxhdjha9a5k78wxm5t",
472+
address.to_string()
473+
);
474+
println!("address:{}", &address);
475+
generate(&bitcoind, 1); // TODO why this is needed even if list_unspent should include zero conf and unsafe?
476+
wallet_skip.sync(noop_progress(), None).unwrap();
477+
assert_eq!(wallet_skip.get_balance().unwrap(), 100_000);
435478
}
436479

437480
#[test]
@@ -450,8 +493,7 @@ mod test {
450493
let capabilities = rpc.get_capabilities();
451494
assert!(capabilities.contains(&Capability::FullHistory) && capabilities.len() == 1);
452495
let bitcoind_indexed = create_bitcoind(vec!["-txindex".to_string()]);
453-
let rpc_indexed =
454-
create_rpc(&bitcoind_indexed, DESCRIPTOR_PUB, Network::Regtest).unwrap();
496+
let rpc_indexed = create_rpc(&bitcoind_indexed, DESCRIPTOR_PUB, Network::Regtest).unwrap();
455497
assert_eq!(rpc_indexed.get_capabilities().len(), 3);
456498
let address = generate(&bitcoind_indexed, 101);
457499
let txid = send_to_address(&bitcoind_indexed, &address, 100_000);

0 commit comments

Comments
 (0)