Skip to content

Commit 84c5a0c

Browse files
author
Ludo Galabru
committed
feat: scan inscription revealed
1 parent 7e952d2 commit 84c5a0c

File tree

4 files changed

+222
-186
lines changed

4 files changed

+222
-186
lines changed

components/chainhook-cli/src/cli/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -490,12 +490,13 @@ async fn handle_command(opts: Opts, ctx: Context) -> Result<(), String> {
490490
&hord_db_conn,
491491
&block_identifier,
492492
&transaction_identifier,
493+
0,
493494
&ctx,
494495
)?;
495496
info!(
496497
ctx.expect_logger(),
497498
"Satoshi #{} was minted in block #{} at offset {} and was transferred {} times.",
498-
traversal.ordinal_number, traversal.ordinal_block_number, traversal.ordinal_offset, traversal.transfers
499+
traversal.ordinal_number, traversal.get_ordinal_coinbase_height(), traversal.get_ordinal_coinbase_offset(), traversal.transfers
499500
);
500501
}
501502
FindCommand::Inscription(cmd) => {

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

+26-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ use chainhook_event_observer::hord::db::{
1212
fetch_and_cache_blocks_in_hord_db, find_all_inscriptions, find_compacted_block_at_block_height,
1313
find_latest_compacted_block_known, open_readonly_hord_db_conn, open_readwrite_hord_db_conn,
1414
};
15+
use chainhook_event_observer::hord::{
16+
update_storage_and_augment_bitcoin_block_with_inscription_reveal_data,
17+
update_storage_and_augment_bitcoin_block_with_inscription_transfer_data, Storage,
18+
};
1519
use chainhook_event_observer::indexer;
1620
use chainhook_event_observer::indexer::bitcoin::{
1721
retrieve_block_hash_with_retry, retrieve_full_block_breakdown_with_retry,
@@ -135,25 +139,44 @@ pub async fn scan_bitcoin_chain_with_predicate(
135139

136140
let event_observer_config = config.get_event_observer_config();
137141
let bitcoin_config = event_observer_config.get_bitcoin_config();
138-
142+
let mut traversals = HashMap::new();
139143
if is_predicate_evaluating_ordinals {
140-
for (cursor, _inscriptions) in inscriptions_cache.into_iter() {
144+
let hord_db_conn = open_readonly_hord_db_conn(&config.expected_cache_path(), ctx)?;
145+
146+
let mut storage = Storage::Memory(BTreeMap::new());
147+
for (cursor, local_traverals) in inscriptions_cache.into_iter() {
141148
// Only consider inscriptions in the interval specified
142149
if cursor < start_block || cursor > end_block {
143150
continue;
144151
}
152+
for (transaction_identifier, traversal_result) in local_traverals.into_iter() {
153+
traversals.insert(transaction_identifier, traversal_result);
154+
}
145155

146156
blocks_scanned += 1;
147157

148158
let block_hash = retrieve_block_hash_with_retry(&cursor, &bitcoin_config, ctx).await?;
149159
let block_breakdown =
150160
retrieve_full_block_breakdown_with_retry(&block_hash, &bitcoin_config, ctx).await?;
151-
let block = indexer::bitcoin::standardize_bitcoin_block(
161+
let mut block = indexer::bitcoin::standardize_bitcoin_block(
152162
block_breakdown,
153163
&event_observer_config.bitcoin_network,
154164
ctx,
155165
)?;
156166

167+
update_storage_and_augment_bitcoin_block_with_inscription_reveal_data(
168+
&mut block,
169+
&mut storage,
170+
&traversals,
171+
&hord_db_conn,
172+
&ctx,
173+
);
174+
175+
update_storage_and_augment_bitcoin_block_with_inscription_transfer_data(
176+
&mut block,
177+
&mut storage,
178+
&ctx,
179+
);
157180
let chain_event =
158181
BitcoinChainEvent::ChainUpdatedWithBlocks(BitcoinChainUpdatedWithBlocksData {
159182
new_blocks: vec![block],

components/chainhook-event-observer/src/hord/db/mod.rs

+56-98
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ use crate::{
2020
utils::Context,
2121
};
2222

23-
use super::{ord::height::Height, update_hord_db_and_augment_bitcoin_block};
23+
use super::{
24+
ord::{height::Height, sat::Sat},
25+
update_hord_db_and_augment_bitcoin_block,
26+
};
2427

2528
fn get_default_hord_db_file_path(base_dir: &PathBuf) -> PathBuf {
2629
let mut destination_path = base_dir.clone();
@@ -350,30 +353,50 @@ pub fn find_inscription_with_ordinal_number(
350353
return None;
351354
}
352355

353-
pub fn find_all_inscriptions(hord_db_conn: &Connection) -> BTreeMap<u64, Vec<(String, u64, u64)>> {
356+
pub fn find_all_inscriptions(
357+
hord_db_conn: &Connection,
358+
) -> BTreeMap<u64, Vec<(TransactionIdentifier, TraversalResult)>> {
354359
let args: &[&dyn ToSql] = &[];
355360
let mut stmt = hord_db_conn
356-
.prepare("SELECT inscription_id, inscription_number, ordinal_number, block_height FROM inscriptions ORDER BY inscription_number ASC")
361+
.prepare("SELECT inscription_number, ordinal_number, block_height, inscription_id FROM inscriptions ORDER BY inscription_number ASC")
357362
.unwrap();
358-
let mut results: BTreeMap<u64, Vec<(String, u64, u64)>> = BTreeMap::new();
363+
let mut results: BTreeMap<u64, Vec<(TransactionIdentifier, TraversalResult)>> = BTreeMap::new();
359364
let mut rows = stmt.query(args).unwrap();
360365
while let Ok(Some(row)) = rows.next() {
361-
let inscription_id: String = row.get(0).unwrap();
362-
let inscription_number: u64 = row.get(1).unwrap();
363-
let ordinal_number: u64 = row.get(2).unwrap();
364-
let block_height: u64 = row.get(3).unwrap();
366+
let inscription_number: u64 = row.get(0).unwrap();
367+
let ordinal_number: u64 = row.get(1).unwrap();
368+
let block_height: u64 = row.get(2).unwrap();
369+
let transaction_id = {
370+
let inscription_id: String = row.get(3).unwrap();
371+
TransactionIdentifier {
372+
hash: format!("0x{}", &inscription_id[0..inscription_id.len() - 2]),
373+
}
374+
};
375+
let traversal = TraversalResult {
376+
inscription_number,
377+
ordinal_number,
378+
transfers: 0,
379+
};
365380
results
366381
.entry(block_height)
367-
.and_modify(|v| v.push((inscription_id.clone(), inscription_number, ordinal_number)))
368-
.or_insert(vec![(inscription_id, inscription_number, ordinal_number)]);
382+
.and_modify(|v| v.push((transaction_id.clone(), traversal.clone())))
383+
.or_insert(vec![(transaction_id, traversal)]);
369384
}
370385
return results;
371386
}
372387

388+
#[derive(Clone, Debug)]
389+
pub struct WatchedSatpoint {
390+
pub inscription_id: String,
391+
pub inscription_number: u64,
392+
pub ordinal_number: u64,
393+
pub offset: u64,
394+
}
395+
373396
pub fn find_inscriptions_at_wached_outpoint(
374397
outpoint: &str,
375398
hord_db_conn: &Connection,
376-
) -> Vec<(String, u64, u64, u64)> {
399+
) -> Vec<WatchedSatpoint> {
377400
let args: &[&dyn ToSql] = &[&outpoint.to_sql().unwrap()];
378401
let mut stmt = hord_db_conn
379402
.prepare("SELECT inscription_id, inscription_number, ordinal_number, offset FROM inscriptions WHERE outpoint_to_watch = ? ORDER BY offset ASC")
@@ -385,7 +408,12 @@ pub fn find_inscriptions_at_wached_outpoint(
385408
let inscription_number: u64 = row.get(1).unwrap();
386409
let ordinal_number: u64 = row.get(2).unwrap();
387410
let offset: u64 = row.get(3).unwrap();
388-
results.push((inscription_id, inscription_number, ordinal_number, offset));
411+
results.push(WatchedSatpoint {
412+
inscription_id,
413+
inscription_number,
414+
ordinal_number,
415+
offset,
416+
});
389417
}
390418
return results;
391419
}
@@ -456,88 +484,6 @@ pub fn remove_entry_from_inscriptions(
456484
}
457485
}
458486

459-
// pub async fn update_hord_db(
460-
// bitcoin_config: &BitcoinConfig,
461-
// hord_db_path: &PathBuf,
462-
// start_block: u64,
463-
// end_block: u64,
464-
// _ctx: &Context,
465-
// network_thread: usize,
466-
// ) -> Result<(), String> {
467-
// let (block_tx, block_rx) = channel::<BitcoinBlockFullBreakdown>();
468-
// let first_inscription_block_height = 767430;
469-
// let ctx = _ctx.clone();
470-
// let network = bitcoin_config.network.clone();
471-
// let hord_db_path = hord_db_path.clone();
472-
// let handle = hiro_system_kit::thread_named("Inscriptions indexing")
473-
// .spawn(move || {
474-
// let mut cursor = first_inscription_block_height;
475-
// let mut inbox = HashMap::new();
476-
477-
// while let Ok(raw_block) = block_rx.recv() {
478-
// // Early return, only considering blocks after 1st inscription
479-
// if raw_block.height < first_inscription_block_height {
480-
// continue;
481-
// }
482-
// let block_height = raw_block.height;
483-
// inbox.insert(raw_block.height, raw_block);
484-
485-
// // In the context of ordinals, we're constrained to process blocks sequentially
486-
// // Blocks are processed by a threadpool and could be coming out of order.
487-
// // Inbox block for later if the current block is not the one we should be
488-
// // processing.
489-
// if block_height != cursor {
490-
// continue;
491-
// }
492-
493-
// // Is the action of processing a block allows us
494-
// // to process more blocks present in the inbox?
495-
// while let Some(next_block) = inbox.remove(&cursor) {
496-
// let mut new_block = match standardize_bitcoin_block(next_block, &network, &ctx)
497-
// {
498-
// Ok(block) => block,
499-
// Err(e) => {
500-
// ctx.try_log(|logger| {
501-
// slog::error!(logger, "Unable to standardize bitcoin block: {e}",)
502-
// });
503-
// return;
504-
// }
505-
// };
506-
507-
// if let Err(e) = update_hord_db_and_augment_bitcoin_block(
508-
// &mut new_block,
509-
// &hord_db_path,
510-
// &ctx,
511-
// ) {
512-
// ctx.try_log(|logger| {
513-
// slog::error!(
514-
// logger,
515-
// "Unable to augment bitcoin block with hord_db: {e}",
516-
// )
517-
// });
518-
// return;
519-
// }
520-
// cursor += 1;
521-
// }
522-
// }
523-
// })
524-
// .expect("unable to detach thread");
525-
526-
// fetch_and_cache_blocks_in_hord_db(
527-
// bitcoin_config,
528-
// hord_db_conn,
529-
// start_block,
530-
// end_block,
531-
// &_ctx,
532-
// network_thread,
533-
// )
534-
// .await?;
535-
536-
// let _ = handle.join();
537-
538-
// Ok(())
539-
// }
540-
541487
pub fn delete_data_in_hord_db(
542488
start_block: u64,
543489
end_block: u64,
@@ -698,17 +644,30 @@ pub async fn fetch_and_cache_blocks_in_hord_db(
698644
Ok(())
699645
}
700646

647+
#[derive(Clone)]
701648
pub struct TraversalResult {
702-
pub ordinal_block_number: u64,
703-
pub ordinal_offset: u64,
649+
pub inscription_number: u64,
704650
pub ordinal_number: u64,
705651
pub transfers: u32,
706652
}
707653

654+
impl TraversalResult {
655+
pub fn get_ordinal_coinbase_height(&self) -> u64 {
656+
let sat = Sat(self.ordinal_number);
657+
sat.height().n()
658+
}
659+
660+
pub fn get_ordinal_coinbase_offset(&self) -> u64 {
661+
let sat = Sat(self.ordinal_number);
662+
self.ordinal_number - sat.height().starting_sat().n()
663+
}
664+
}
665+
708666
pub fn retrieve_satoshi_point_using_local_storage(
709667
hord_db_conn: &Connection,
710668
block_identifier: &BlockIdentifier,
711669
transaction_identifier: &TransactionIdentifier,
670+
inscription_number: u64,
712671
ctx: &Context,
713672
) -> Result<TraversalResult, String> {
714673
ctx.try_log(|logger| {
@@ -851,8 +810,7 @@ pub fn retrieve_satoshi_point_using_local_storage(
851810
let ordinal_number = height.starting_sat().0 + ordinal_offset;
852811

853812
Ok(TraversalResult {
854-
ordinal_block_number: ordinal_block_number.into(),
855-
ordinal_offset,
813+
inscription_number,
856814
ordinal_number,
857815
transfers: hops,
858816
})

0 commit comments

Comments
 (0)