Skip to content

Commit f6be49e

Browse files
author
Ludo Galabru
committed
feat: ability to target blocks
1 parent 8464b82 commit f6be49e

File tree

2 files changed

+80
-108
lines changed

2 files changed

+80
-108
lines changed

components/hord-cli/src/scan/bitcoin.rs

+76-104
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
use crate::config::{Config, PredicatesApi};
2-
use crate::core::protocol::sequencing::{
3-
update_storage_and_augment_bitcoin_block_with_inscription_reveal_data_tx,
4-
update_storage_and_augment_bitcoin_block_with_inscription_transfer_data_tx,
5-
};
2+
use crate::core::pipeline::processors::inscription_indexing::re_augment_block_with_ordinals_operations;
63
use crate::core::{self, get_inscriptions_revealed_in_block};
7-
use crate::db::{
8-
find_all_inscriptions_in_block, get_any_entry_in_ordinal_activities,
9-
open_readonly_hord_db_conn, InscriptionHeigthHint,
10-
};
4+
use crate::db::{get_any_entry_in_ordinal_activities, open_readonly_hord_db_conn};
115
use crate::download::download_ordinals_dataset_if_required;
126
use crate::service::{
137
open_readwrite_predicates_db_conn_or_panic, update_predicate_status, PredicateStatus,
@@ -19,15 +13,15 @@ use chainhook_sdk::chainhooks::bitcoin::{
1913
evaluate_bitcoin_chainhooks_on_chain_event, handle_bitcoin_hook_action,
2014
BitcoinChainhookOccurrence, BitcoinTriggerChainhook,
2115
};
22-
use chainhook_sdk::chainhooks::types::{BitcoinChainhookSpecification, BitcoinPredicateType};
16+
use chainhook_sdk::chainhooks::types::BitcoinChainhookSpecification;
2317
use chainhook_sdk::indexer::bitcoin::{
2418
build_http_client, download_and_parse_block_with_retry, retrieve_block_hash_with_retry,
2519
};
2620
use chainhook_sdk::observer::{gather_proofs, EventObserverConfig};
2721
use chainhook_sdk::types::{
2822
BitcoinBlockData, BitcoinChainEvent, BitcoinChainUpdatedWithBlocksData,
2923
};
30-
use chainhook_sdk::utils::{file_append, send_request, Context};
24+
use chainhook_sdk::utils::{file_append, send_request, BlockHeights, Context};
3125
use std::collections::HashMap;
3226

3327
// TODO(lgalabru): Re-introduce support for blocks[] !!! gracefully handle hints for non consecutive blocks
@@ -49,72 +43,69 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
4943
return Err(format!("Bitcoin RPC error: {}", message.to_string()));
5044
}
5145
};
46+
let mut floating_end_block = false;
5247

53-
let start_block = match predicate_spec.start_block {
54-
Some(start_block) => start_block,
55-
None => {
56-
return Err(
57-
"Bitcoin chainhook specification must include a field start_block in replay mode"
58-
.into(),
59-
);
60-
}
61-
};
62-
63-
let (mut end_block, floating_end_block) = match predicate_spec.end_block {
64-
Some(end_block) => (end_block, false),
65-
None => match bitcoin_rpc.get_blockchain_info() {
66-
Ok(result) => (result.blocks - 1, true),
67-
Err(e) => {
68-
return Err(format!(
69-
"unable to retrieve Bitcoin chain tip ({})",
70-
e.to_string()
71-
));
48+
let mut block_heights_to_scan = if let Some(ref blocks) = predicate_spec.blocks {
49+
BlockHeights::Blocks(blocks.clone()).get_sorted_entries()
50+
} else {
51+
let start_block = match predicate_spec.start_block {
52+
Some(start_block) => start_block,
53+
None => {
54+
return Err(
55+
"Bitcoin chainhook specification must include a field start_block in replay mode"
56+
.into(),
57+
);
7258
}
73-
},
59+
};
60+
let (end_block, update_end_block) = match predicate_spec.end_block {
61+
Some(end_block) => (end_block, false),
62+
None => match bitcoin_rpc.get_blockchain_info() {
63+
Ok(result) => (result.blocks - 1, true),
64+
Err(e) => {
65+
return Err(format!(
66+
"unable to retrieve Bitcoin chain tip ({})",
67+
e.to_string()
68+
));
69+
}
70+
},
71+
};
72+
floating_end_block = update_end_block;
73+
BlockHeights::BlockRange(start_block, end_block).get_sorted_entries()
7474
};
7575

7676
// Are we dealing with an ordinals-based predicate?
7777
// If so, we could use the ordinal storage to provide a set of hints.
78-
let mut inscriptions_db_conn = None;
79-
80-
if let BitcoinPredicateType::OrdinalsProtocol(_) = &predicate_spec.predicate {
81-
inscriptions_db_conn = Some(open_readonly_hord_db_conn(
82-
&config.expected_cache_path(),
83-
ctx,
84-
)?);
85-
}
78+
let inscriptions_db_conn = open_readonly_hord_db_conn(&config.expected_cache_path(), ctx)?;
8679

8780
info!(
8881
ctx.expect_logger(),
8982
"Starting predicate evaluation on Bitcoin blocks",
9083
);
91-
92-
let mut blocks_scanned = 0;
9384
let mut actions_triggered = 0;
94-
let occurrences_found = 0u64;
9585
let mut err_count = 0;
9686

9787
let event_observer_config = config.get_event_observer_config();
9888
let bitcoin_config = event_observer_config.get_bitcoin_config();
99-
let mut traversals = HashMap::new();
89+
let number_of_blocks_to_scan = block_heights_to_scan.len() as u64;
90+
let mut number_of_blocks_scanned = 0;
91+
let mut number_of_blocks_sent = 0u64;
10092
let http_client = build_http_client();
10193

102-
let mut cursor = start_block.saturating_sub(1);
94+
while let Some(current_block_height) = block_heights_to_scan.pop_front() {
95+
number_of_blocks_scanned += 1;
10396

104-
let mut inscription_height_hint = InscriptionHeigthHint::new();
105-
106-
while cursor <= end_block {
107-
cursor += 1;
108-
blocks_scanned += 1;
109-
110-
if let Some(ref inscriptions_db_conn) = inscriptions_db_conn {
111-
if !get_any_entry_in_ordinal_activities(&cursor, &inscriptions_db_conn, &ctx) {
112-
continue;
113-
}
97+
if !get_any_entry_in_ordinal_activities(&current_block_height, &inscriptions_db_conn, &ctx)
98+
{
99+
continue;
114100
}
115101

116-
let block_hash =
117-
retrieve_block_hash_with_retry(&http_client, &cursor, &bitcoin_config, ctx).await?;
102+
let block_hash = retrieve_block_hash_with_retry(
103+
&http_client,
104+
&current_block_height,
105+
&bitcoin_config,
106+
ctx,
107+
)
108+
.await?;
118109
let block_breakdown =
119110
download_and_parse_block_with_retry(&http_client, &block_hash, &bitcoin_config, ctx)
120111
.await?;
@@ -127,49 +118,26 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
127118
Err((e, _)) => {
128119
warn!(
129120
ctx.expect_logger(),
130-
"Unable to standardize block#{} {}: {}", cursor, block_hash, e
121+
"Unable to standardize block#{} {}: {}", current_block_height, block_hash, e
131122
);
132123
continue;
133124
}
134125
};
135126

136-
if let Some(ref mut inscriptions_db_conn) = inscriptions_db_conn {
137-
// Evaluating every single block is required for also keeping track of transfers.
138-
let local_traverals =
139-
find_all_inscriptions_in_block(&cursor, &inscriptions_db_conn, &ctx);
140-
for (key, traversal_result) in local_traverals.into_iter() {
141-
traversals.insert(key, traversal_result);
142-
}
143-
144-
let transaction = inscriptions_db_conn.transaction().unwrap();
145-
let empty_ctx = Context::empty();
146-
let _ = update_storage_and_augment_bitcoin_block_with_inscription_reveal_data_tx(
147-
&mut block,
148-
&transaction,
149-
&traversals,
150-
&mut inscription_height_hint,
151-
&empty_ctx,
152-
)?;
153-
154-
let _ = update_storage_and_augment_bitcoin_block_with_inscription_transfer_data_tx(
155-
&mut block,
156-
&transaction,
157-
&empty_ctx,
158-
)?;
127+
let empty_ctx = Context::empty();
128+
re_augment_block_with_ordinals_operations(&mut block, &inscriptions_db_conn, &empty_ctx);
159129

160-
let inscriptions_revealed = get_inscriptions_revealed_in_block(&block)
161-
.iter()
162-
.map(|d| d.inscription_number.to_string())
163-
.collect::<Vec<String>>();
130+
let inscriptions_revealed = get_inscriptions_revealed_in_block(&block)
131+
.iter()
132+
.map(|d| d.inscription_number.to_string())
133+
.collect::<Vec<String>>();
164134

165-
info!(
166-
ctx.expect_logger(),
167-
"Processing block #{} through {} predicate (inscriptions revealed: [{}])",
168-
cursor,
169-
predicate_spec.uuid,
170-
inscriptions_revealed.join(", ")
171-
);
172-
}
135+
info!(
136+
ctx.expect_logger(),
137+
"Processing block #{current_block_height} through {} predicate (inscriptions revealed: [{}])",
138+
predicate_spec.uuid,
139+
inscriptions_revealed.join(", ")
140+
);
173141

174142
match process_block_with_predicates(
175143
block,
@@ -188,12 +156,12 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
188156
}
189157

190158
if let PredicatesApi::On(ref api_config) = config.http_api {
191-
if blocks_scanned % 50 == 0 {
159+
if number_of_blocks_scanned % 50 == 0 {
192160
let status = PredicateStatus::Scanning(ScanningData {
193-
start_block,
194-
end_block,
195-
cursor,
196-
occurrences_found,
161+
number_of_blocks_to_scan,
162+
number_of_blocks_scanned,
163+
number_of_blocks_sent,
164+
current_block_height,
197165
});
198166
let mut predicates_db_conn =
199167
open_readwrite_predicates_db_conn_or_panic(api_config, &ctx);
@@ -206,9 +174,13 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
206174
}
207175
}
208176

209-
if cursor == end_block && floating_end_block {
210-
end_block = match bitcoin_rpc.get_blockchain_info() {
211-
Ok(result) => result.blocks - 1,
177+
if block_heights_to_scan.is_empty() && floating_end_block {
178+
match bitcoin_rpc.get_blockchain_info() {
179+
Ok(result) => {
180+
for entry in (current_block_height + 1)..result.blocks {
181+
block_heights_to_scan.push_back(entry);
182+
}
183+
}
212184
Err(_e) => {
213185
continue;
214186
}
@@ -217,15 +189,15 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
217189
}
218190
info!(
219191
ctx.expect_logger(),
220-
"{blocks_scanned} blocks scanned, {actions_triggered} actions triggered"
192+
"{number_of_blocks_scanned} blocks scanned, {actions_triggered} actions triggered"
221193
);
222194

223195
if let PredicatesApi::On(ref api_config) = config.http_api {
224196
let status = PredicateStatus::Scanning(ScanningData {
225-
start_block,
226-
end_block,
227-
cursor,
228-
occurrences_found,
197+
number_of_blocks_to_scan,
198+
number_of_blocks_scanned,
199+
number_of_blocks_sent,
200+
current_block_height: 0,
229201
});
230202
let mut predicates_db_conn = open_readwrite_predicates_db_conn_or_panic(api_config, &ctx);
231203
update_predicate_status(&predicate_spec.key(), status, &mut predicates_db_conn, &ctx)

components/hord-cli/src/service/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -595,10 +595,10 @@ pub enum PredicateStatus {
595595

596596
#[derive(Debug, Clone, Serialize, Deserialize)]
597597
pub struct ScanningData {
598-
pub start_block: u64,
599-
pub cursor: u64,
600-
pub end_block: u64,
601-
pub occurrences_found: u64,
598+
pub number_of_blocks_to_scan: u64,
599+
pub number_of_blocks_scanned: u64,
600+
pub number_of_blocks_sent: u64,
601+
pub current_block_height: u64,
602602
}
603603

604604
#[derive(Debug, Clone, Serialize, Deserialize)]

0 commit comments

Comments
 (0)