diff --git a/src/bitcoin/d/mod.rs b/src/bitcoin/d/mod.rs index 539ff308..93f8af7b 100644 --- a/src/bitcoin/d/mod.rs +++ b/src/bitcoin/d/mod.rs @@ -957,11 +957,17 @@ impl BitcoinD { None } - pub fn get_block_stats(&self, blockhash: bitcoin::BlockHash) -> BlockStats { - let res = self.make_node_request( + pub fn get_block_stats(&self, blockhash: bitcoin::BlockHash) -> Option { + let res = match self.make_fallible_node_request( "getblockheader", ¶ms!(Json::String(blockhash.to_string()),), - ); + ) { + Ok(res) => res, + Err(e) => { + log::warn!("Error when fetching block header {}: {}", &blockhash, e); + return None; + } + }; let confirmations = res .get("confirmations") .and_then(Json::as_i64) @@ -989,14 +995,14 @@ impl BitcoinD { .and_then(Json::as_u64) .expect("Invalid median timestamp in `getblockheader` response: not an u64") as u32; - BlockStats { + Some(BlockStats { confirmations, previous_blockhash, height, blockhash, time, median_time_past, - } + }) } pub fn broadcast_tx(&self, tx: &bitcoin::Transaction) -> Result<(), BitcoindError> { diff --git a/src/bitcoin/d/utils.rs b/src/bitcoin/d/utils.rs index 2bc957cf..2087dbf6 100644 --- a/src/bitcoin/d/utils.rs +++ b/src/bitcoin/d/utils.rs @@ -28,15 +28,15 @@ pub fn block_before_date( ) -> Option where Fh: FnMut(i32) -> Option, - Fs: FnMut(bitcoin::BlockHash) -> BlockStats, + Fs: FnMut(bitcoin::BlockHash) -> Option, { log::debug!("Looking for the first block before {}", target_timestamp); let mut start_height = 0; let mut end_height = chain_tip.height; - let genesis_stats = get_stats(get_hash(0).expect("Genesis hash")); - let tip_stats = get_stats(chain_tip.hash); + let genesis_stats = get_stats(get_hash(0).expect("Genesis hash"))?; + let tip_stats = get_stats(chain_tip.hash)?; if !(genesis_stats.time..tip_stats.time).contains(&target_timestamp) { return None; } @@ -47,7 +47,7 @@ where let current_height = start_height + delta.checked_div(2).unwrap(); // We want the last block with a timestamp below, not the first with a higher one. let next_height = current_height.checked_add(1).unwrap(); - let next_stats = get_stats(get_hash(next_height)?); + let next_stats = get_stats(get_hash(next_height)?)?; log::debug!("Current next block: {:?}", next_stats); if target_timestamp > next_stats.time { @@ -85,13 +85,18 @@ mod tests { } // Inefficient dummy implementation of BitcoinD's self.get_block_stats - fn get_stats(chain: &[(BlockChainTip, BlockStats)], hash: bitcoin::BlockHash) -> BlockStats { - chain - .iter() - .find(|(tip, _)| tip.hash == hash) - .unwrap() - .1 - .clone() + fn get_stats( + chain: &[(BlockChainTip, BlockStats)], + hash: bitcoin::BlockHash, + ) -> Option { + Some( + chain + .iter() + .find(|(tip, _)| tip.hash == hash) + .unwrap() + .1 + .clone(), + ) } macro_rules! bh { diff --git a/src/bitcoin/mod.rs b/src/bitcoin/mod.rs index fcbffd91..ed2143b9 100644 --- a/src/bitcoin/mod.rs +++ b/src/bitcoin/mod.rs @@ -272,11 +272,11 @@ impl BitcoinInterface for d::BitcoinD { } fn common_ancestor(&self, tip: &BlockChainTip) -> Option { - let mut stats = self.get_block_stats(tip.hash); + let mut stats = self.get_block_stats(tip.hash)?; let mut ancestor = *tip; while stats.confirmations == -1 { - stats = self.get_block_stats(stats.previous_blockhash?); + stats = self.get_block_stats(stats.previous_blockhash?)?; ancestor = BlockChainTip { hash: stats.blockhash, height: stats.height, @@ -318,7 +318,7 @@ impl BitcoinInterface for d::BitcoinD { fn tip_time(&self) -> Option { let tip = self.chain_tip(); - Some(self.get_block_stats(tip.hash).time) + Some(self.get_block_stats(tip.hash)?.time) } fn wallet_transaction(