fix: add retry logic to work around unexpected responses from bitcoind

This commit is contained in:
Ludo Galabru
2023-06-23 14:53:21 -04:00
parent c5335a765c
commit 2ab6b32ff0
2 changed files with 60 additions and 20 deletions

View File

@@ -328,7 +328,7 @@ pub fn standardize_bitcoin_block(
block: BitcoinBlockFullBreakdown,
network: &BitcoinNetwork,
ctx: &Context,
) -> Result<BitcoinBlockData, String> {
) -> Result<BitcoinBlockData, (String, bool)> {
let mut transactions = vec![];
let block_height = block.height as u64;
let expected_magic_bytes = get_stacks_canonical_magic_bytes(&network);
@@ -364,24 +364,36 @@ pub fn standardize_bitcoin_block(
if input.is_coinbase() {
continue;
}
let prevout = input.prevout.as_ref().ok_or(format!(
"error retrieving prevout for transaction {}, input #{} (block #{})",
tx.txid, index, block.height
let prevout = input.prevout.as_ref().ok_or((
format!(
"error retrieving prevout for transaction {}, input #{} (block #{})",
tx.txid, index, block.height
),
true,
))?;
let txid = input.txid.as_ref().ok_or(format!(
"error retrieving txid for transaction {}, input #{} (block #{})",
tx.txid, index, block.height
let txid = input.txid.as_ref().ok_or((
format!(
"error retrieving txid for transaction {}, input #{} (block #{})",
tx.txid, index, block.height
),
true,
))?;
let vout = input.vout.ok_or(format!(
"error retrieving vout for transaction {}, input #{} (block #{})",
tx.txid, index, block.height
let vout = input.vout.ok_or((
format!(
"error retrieving vout for transaction {}, input #{} (block #{})",
tx.txid, index, block.height
),
true,
))?;
let script_sig = input.script_sig.ok_or(format!(
"error retrieving script_sig for transaction {}, input #{} (block #{})",
tx.txid, index, block.height
let script_sig = input.script_sig.ok_or((
format!(
"error retrieving script_sig for transaction {}, input #{} (block #{})",
tx.txid, index, block.height
),
true,
))?;
sats_in += prevout.value.to_sat();

View File

@@ -18,7 +18,9 @@ use crate::hord::{
revert_hord_db_with_augmented_bitcoin_block, update_hord_db_and_augment_bitcoin_block,
HordConfig,
};
use crate::indexer::bitcoin::{standardize_bitcoin_block, BitcoinBlockFullBreakdown};
use crate::indexer::bitcoin::{
download_and_parse_block_with_retry, standardize_bitcoin_block, BitcoinBlockFullBreakdown,
};
use crate::indexer::{Indexer, IndexerConfig};
use crate::utils::{send_request, Context};
@@ -702,17 +704,43 @@ pub async fn start_observer_commands_handler(
}
break;
}
ObserverCommand::ProcessBitcoinBlock(block_data) => {
let new_block =
match standardize_bitcoin_block(block_data, &config.bitcoin_network, &ctx) {
Ok(block) => block,
Err(e) => {
ObserverCommand::ProcessBitcoinBlock(mut block_data) => {
let block_hash = block_data.hash.to_string();
let new_block = loop {
match standardize_bitcoin_block(
block_data.clone(),
&config.bitcoin_network,
&ctx,
) {
Ok(block) => break block,
Err((e, retry)) => {
ctx.try_log(|logger| {
slog::error!(logger, "Error standardizing block: {}", e)
});
continue;
if retry {
block_data = match download_and_parse_block_with_retry(
&block_hash,
&config.get_bitcoin_config(),
&ctx,
)
.await
{
Ok(block) => block,
Err(e) => {
ctx.try_log(|logger| {
slog::warn!(
logger,
"unable to download_and_parse_block: {}",
e.to_string()
)
});
continue;
}
};
}
}
};
};
bitcoin_block_store.insert(new_block.block_identifier.clone(), new_block);
}
ObserverCommand::CacheBitcoinBlock(block) => {