From 9b45f908b89569fc09ea97edf132a46ba4904d87 Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Thu, 25 May 2023 07:09:35 -0400 Subject: [PATCH 01/12] feat: attempt to support cursed inscriptions --- .../src/hord/db/mod.rs | 35 ++- .../chainhook-event-observer/src/hord/mod.rs | 275 +++++++++++------- .../src/indexer/bitcoin/mod.rs | 6 +- components/chainhook-types-rs/src/rosetta.rs | 5 +- 4 files changed, 194 insertions(+), 127 deletions(-) diff --git a/components/chainhook-event-observer/src/hord/db/mod.rs b/components/chainhook-event-observer/src/hord/db/mod.rs index 7ca02d03f..7b7a5efb0 100644 --- a/components/chainhook-event-observer/src/hord/db/mod.rs +++ b/components/chainhook-event-observer/src/hord/db/mod.rs @@ -362,7 +362,7 @@ pub fn find_latest_inscription_number_at_block_height( block_height: &u64, inscriptions_db_conn: &Connection, _ctx: &Context, -) -> Result, String> { +) -> Result, String> { let args: &[&dyn ToSql] = &[&block_height.to_sql().unwrap()]; let mut stmt = inscriptions_db_conn .prepare( @@ -373,25 +373,28 @@ pub fn find_latest_inscription_number_at_block_height( .query(args) .map_err(|e| format!("unable to query inscriptions: {}", e.to_string()))?; while let Ok(Some(row)) = rows.next() { - let inscription_number: u64 = row.get(0).unwrap(); + let inscription_number: i64 = row.get(0).unwrap(); return Ok(Some(inscription_number)); } Ok(None) } -pub fn find_latest_inscription_number( +pub fn find_latest_cursed_inscription_number_at_block_height( + block_height: &u64, inscriptions_db_conn: &Connection, _ctx: &Context, -) -> Result, String> { - let args: &[&dyn ToSql] = &[]; +) -> Result, String> { + let args: &[&dyn ToSql] = &[&block_height.to_sql().unwrap()]; let mut stmt = inscriptions_db_conn .prepare( - "SELECT inscription_number FROM inscriptions ORDER BY inscription_number DESC LIMIT 1", + "SELECT inscription_number FROM inscriptions WHERE block_height < ? ORDER BY inscription_number ASC LIMIT 1", ) - .unwrap(); - let mut rows = stmt.query(args).unwrap(); + .map_err(|e| format!("unable to query inscriptions: {}", e.to_string()))?; + let mut rows = stmt + .query(args) + .map_err(|e| format!("unable to query inscriptions: {}", e.to_string()))?; while let Ok(Some(row)) = rows.next() { - let inscription_number: u64 = row.get(0).unwrap(); + let inscription_number: i64 = row.get(0).unwrap(); return Ok(Some(inscription_number)); } Ok(None) @@ -428,7 +431,7 @@ pub fn find_inscription_with_id( while let Ok(Some(row)) = rows.next() { let inscription_block_hash: String = row.get(2).unwrap(); if block_hash.eq(&inscription_block_hash) { - let inscription_number: u64 = row.get(0).unwrap(); + let inscription_number: i64 = row.get(0).unwrap(); let ordinal_number: u64 = row.get(1).unwrap(); let traversal = TraversalResult { inscription_number, @@ -451,7 +454,7 @@ pub fn find_all_inscriptions( let mut results: BTreeMap> = BTreeMap::new(); let mut rows = stmt.query(args).unwrap(); while let Ok(Some(row)) = rows.next() { - let inscription_number: u64 = row.get(0).unwrap(); + let inscription_number: i64 = row.get(0).unwrap(); let ordinal_number: u64 = row.get(1).unwrap(); let block_height: u64 = row.get(2).unwrap(); let transaction_id = { @@ -476,7 +479,7 @@ pub fn find_all_inscriptions( #[derive(Clone, Debug)] pub struct WatchedSatpoint { pub inscription_id: String, - pub inscription_number: u64, + pub inscription_number: i64, pub ordinal_number: u64, pub offset: u64, } @@ -503,7 +506,7 @@ pub fn find_watched_satpoint_for_inscription( .map_err(|e| format!("unable to query inscriptions table: {}", e.to_string()))?; while let Ok(Some(row)) = rows.next() { let inscription_id: String = row.get(0).unwrap(); - let inscription_number: u64 = row.get(1).unwrap(); + let inscription_number: i64 = row.get(1).unwrap(); let ordinal_number: u64 = row.get(2).unwrap(); let offset: u64 = row.get(3).unwrap(); let block_height: u64 = row.get(4).unwrap(); @@ -537,7 +540,7 @@ pub fn find_inscriptions_at_wached_outpoint( .map_err(|e| format!("unable to query inscriptions table: {}", e.to_string()))?; while let Ok(Some(row)) = rows.next() { let inscription_id: String = row.get(0).unwrap(); - let inscription_number: u64 = row.get(1).unwrap(); + let inscription_number: i64 = row.get(1).unwrap(); let ordinal_number: u64 = row.get(2).unwrap(); let offset: u64 = row.get(3).unwrap(); results.push(WatchedSatpoint { @@ -813,7 +816,7 @@ pub async fn fetch_and_cache_blocks_in_hord_db( #[derive(Clone, Debug)] pub struct TraversalResult { - pub inscription_number: u64, + pub inscription_number: i64, pub ordinal_number: u64, pub transfers: u32, } @@ -834,7 +837,7 @@ pub fn retrieve_satoshi_point_using_lazy_storage( blocks_db: &DB, block_identifier: &BlockIdentifier, transaction_identifier: &TransactionIdentifier, - inscription_number: u64, + inscription_number: i64, traversals_cache: Arc< DashMap<(u32, [u8; 8]), LazyBlockTransaction, BuildHasherDefault>, >, diff --git a/components/chainhook-event-observer/src/hord/mod.rs b/components/chainhook-event-observer/src/hord/mod.rs index 4eb4f776f..fcb9c75a8 100644 --- a/components/chainhook-event-observer/src/hord/mod.rs +++ b/components/chainhook-event-observer/src/hord/mod.rs @@ -36,21 +36,23 @@ use crate::{ }; use self::db::{ - find_inscription_with_id, find_latest_inscription_number_at_block_height, - open_readonly_hord_db_conn_rocks_db, remove_entry_from_blocks, remove_entry_from_inscriptions, - LazyBlock, LazyBlockTransaction, TraversalResult, WatchedSatpoint, + find_inscription_with_id, find_latest_cursed_inscription_number_at_block_height, + find_latest_inscription_number_at_block_height, open_readonly_hord_db_conn_rocks_db, + remove_entry_from_blocks, remove_entry_from_inscriptions, LazyBlock, LazyBlockTransaction, + TraversalResult, WatchedSatpoint, }; use self::inscription::InscriptionParser; use self::ord::inscription_id::InscriptionId; -pub fn try_parse_ordinal_operation( +pub fn parse_ordinal_operations( tx: &BitcoinTransactionFullBreakdown, _block_height: u64, _ctx: &Context, -) -> Option { +) -> Vec { // This should eventually become a loop once/if there is settlement on https://github.com/casey/ord/issues/2000. - if let Some(first_input) = tx.vin.get(0) { - if let Some(ref witnesses) = first_input.txinwitness { + let mut operations = vec![]; + for (input_index, input) in tx.vin.iter().enumerate() { + if let Some(ref witnesses) = input.txinwitness { for bytes in witnesses.iter() { let script = Script::from(bytes.to_vec()); let parser = InscriptionParser { @@ -64,7 +66,7 @@ pub fn try_parse_ordinal_operation( let inscription_id = InscriptionId { txid: tx.txid.clone(), - index: 0, + index: input_index as u32, }; let inscription_output_value = tx @@ -85,27 +87,53 @@ pub fn try_parse_ordinal_operation( None }; - return Some(OrdinalOperation::InscriptionRevealed( - OrdinalInscriptionRevealData { - content_type: inscription.content_type().unwrap_or("unknown").to_string(), - content_bytes: format!("0x{}", hex::encode(&inscription_content_bytes)), - content_length: inscription_content_bytes.len(), - inscription_id: inscription_id.to_string(), - inscriber_address, - inscription_output_value, - inscription_fee: 0, - inscription_number: 0, - ordinal_number: 0, - ordinal_block_height: 0, - ordinal_offset: 0, - transfers_pre_inscription: 0, - satpoint_post_inscription: format!("{}:0:0", tx.txid.clone()), - }, - )); + if input_index == 0 { + operations.push(OrdinalOperation::InscriptionRevealed( + OrdinalInscriptionRevealData { + content_type: inscription + .content_type() + .unwrap_or("unknown") + .to_string(), + content_bytes: format!("0x{}", hex::encode(&inscription_content_bytes)), + content_length: inscription_content_bytes.len(), + inscription_id: inscription_id.to_string(), + inscriber_address, + inscription_output_value, + inscription_fee: 0, + inscription_number: 0, + ordinal_number: 0, + ordinal_block_height: 0, + ordinal_offset: 0, + transfers_pre_inscription: 0, + satpoint_post_inscription: format!("{}:0:0", tx.txid.clone()), + }, + )) + } else { + operations.push(OrdinalOperation::CursedInscriptionRevealed( + OrdinalInscriptionRevealData { + content_type: inscription + .content_type() + .unwrap_or("unknown") + .to_string(), + content_bytes: format!("0x{}", hex::encode(&inscription_content_bytes)), + content_length: inscription_content_bytes.len(), + inscription_id: inscription_id.to_string(), + inscriber_address, + inscription_output_value, + inscription_fee: 0, + inscription_number: 0, + ordinal_number: 0, + ordinal_block_height: 0, + ordinal_offset: 0, + transfers_pre_inscription: 0, + satpoint_post_inscription: format!("{}:0:0", tx.txid.clone()), + }, + )) + } } } } - None + operations } pub fn get_inscriptions_revealed_in_block( @@ -135,7 +163,8 @@ pub fn revert_hord_db_with_augmented_bitcoin_block( let tx = &block.transactions[block.transactions.len() - tx_index]; for ordinal_event in tx.metadata.ordinal_operations.iter() { match ordinal_event { - OrdinalOperation::InscriptionRevealed(data) => { + OrdinalOperation::InscriptionRevealed(data) + | OrdinalOperation::CursedInscriptionRevealed(data) => { // We remove any new inscription created remove_entry_from_inscriptions( &data.inscription_id, @@ -376,6 +405,27 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( return; } }; + + let mut latest_cursed_inscription_number = + match find_latest_cursed_inscription_number_at_block_height( + &block.block_identifier.index, + &inscription_db_conn, + &ctx, + ) { + Ok(None) => -1, + Ok(Some(inscription_number)) => inscription_number + 1, + Err(e) => { + ctx.try_log(|logger| { + slog::error!( + logger, + "unable to retrieve inscription number: {}", + e.to_string() + ); + }); + return; + } + }; + let mut sats_overflow = vec![]; for new_tx in block.transactions.iter_mut().skip(1) { @@ -384,90 +434,105 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( for (ordinal_event_index, ordinal_event) in new_tx.metadata.ordinal_operations.iter_mut().enumerate() { - if let OrdinalOperation::InscriptionRevealed(inscription) = ordinal_event { - let inscription_number = latest_inscription_number; - let traversal = match traversals.get(&new_tx.transaction_identifier) { - Some(traversal) => traversal, - None => { - ctx.try_log(|logger| { - slog::info!( - logger, - "Unable to retrieve cached inscription data for inscription {}", - new_tx.transaction_identifier.hash - ); - }); - ordinals_events_indexes_to_discard.push_front(ordinal_event_index); - continue; - } - }; - inscription.ordinal_offset = traversal.get_ordinal_coinbase_offset(); - inscription.ordinal_block_height = traversal.get_ordinal_coinbase_height(); - inscription.ordinal_number = traversal.ordinal_number; - inscription.inscription_number = traversal.inscription_number; - inscription.transfers_pre_inscription = traversal.transfers; - inscription.inscription_fee = new_tx.metadata.fee; + let (inscription, is_cursed) = match ordinal_event { + OrdinalOperation::InscriptionRevealed(inscription) => (inscription, false), + OrdinalOperation::CursedInscriptionRevealed(inscription) => (inscription, true), + OrdinalOperation::InscriptionTransferred(_) => continue, + }; - match storage { - Storage::Sqlite(rw_hord_db_conn) => { - if traversal.ordinal_number > 0 { - if let Some(_entry) = find_inscription_with_ordinal_number( - &traversal.ordinal_number, - &inscription_db_conn, - &ctx, - ) { - ctx.try_log(|logger| { - slog::warn!( - logger, - "Transaction {} in block {} is overriding an existing inscription {}", - new_tx.transaction_identifier.hash, - block.block_identifier.index, - traversal.ordinal_number - ); - }); - ordinals_events_indexes_to_discard.push_front(ordinal_event_index); - continue; - } - } else { - // If the satoshi inscribed correspond to a sat overflow, we will store the inscription - // but exclude it from the block data - sats_overflow.push(inscription.clone()); + let inscription_number = if is_cursed { + latest_cursed_inscription_number + } else { + latest_inscription_number + }; + + let traversal = match traversals.get(&new_tx.transaction_identifier) { + Some(traversal) => traversal, + None => { + ctx.try_log(|logger| { + slog::info!( + logger, + "Unable to retrieve cached inscription data for inscription {}", + new_tx.transaction_identifier.hash + ); + }); + ordinals_events_indexes_to_discard.push_front(ordinal_event_index); + continue; + } + }; + inscription.ordinal_offset = traversal.get_ordinal_coinbase_offset(); + inscription.ordinal_block_height = traversal.get_ordinal_coinbase_height(); + inscription.ordinal_number = traversal.ordinal_number; + inscription.inscription_number = traversal.inscription_number; + inscription.transfers_pre_inscription = traversal.transfers; + inscription.inscription_fee = new_tx.metadata.fee; + + match storage { + Storage::Sqlite(rw_hord_db_conn) => { + if traversal.ordinal_number > 0 { + if let Some(_entry) = find_inscription_with_ordinal_number( + &traversal.ordinal_number, + &inscription_db_conn, + &ctx, + ) { + ctx.try_log(|logger| { + slog::warn!( + logger, + "Transaction {} in block {} is overriding an existing inscription {}", + new_tx.transaction_identifier.hash, + block.block_identifier.index, + traversal.ordinal_number + ); + }); ordinals_events_indexes_to_discard.push_front(ordinal_event_index); continue; } - latest_inscription_number += 1; - inscription.inscription_number = inscription_number; - ctx.try_log(|logger| { - slog::info!( - logger, - "Inscription {} (#{}) detected on Satoshi {} (block {}, {} transfers)", - inscription.inscription_id, - inscription.inscription_number, - inscription.ordinal_number, - block.block_identifier.index, - inscription.transfers_pre_inscription, - ); - }); - store_new_inscription( - &inscription, - &block.block_identifier, - &rw_hord_db_conn, - &ctx, - ); + } else { + // If the satoshi inscribed correspond to a sat overflow, we will store the inscription + // but exclude it from the block data + sats_overflow.push(inscription.clone()); + ordinals_events_indexes_to_discard.push_front(ordinal_event_index); + continue; } - Storage::Memory(map) => { - let outpoint = inscription.satpoint_post_inscription - [0..inscription.satpoint_post_inscription.len() - 2] - .to_string(); - map.insert( - outpoint, - vec![WatchedSatpoint { - inscription_id: inscription.inscription_id.clone(), - inscription_number: inscription.inscription_number, - ordinal_number: inscription.ordinal_number, - offset: 0, - }], + + if is_cursed { + latest_cursed_inscription_number -= 1; + } else { + latest_inscription_number += 1; + }; + + inscription.inscription_number = inscription_number; + ctx.try_log(|logger| { + slog::info!( + logger, + "Inscription {} (#{}) detected on Satoshi {} (block {}, {} transfers)", + inscription.inscription_id, + inscription.inscription_number, + inscription.ordinal_number, + block.block_identifier.index, + inscription.transfers_pre_inscription, ); - } + }); + store_new_inscription( + &inscription, + &block.block_identifier, + &rw_hord_db_conn, + &ctx, + ); + } + Storage::Memory(map) => { + let outpoint = inscription.satpoint_post_inscription + [0..inscription.satpoint_post_inscription.len() - 2] + .to_string(); + map.insert( + outpoint, + vec![WatchedSatpoint { + inscription_id: inscription.inscription_id.clone(), + inscription_number: inscription.inscription_number, + ordinal_number: inscription.ordinal_number, + offset: 0, + }], + ); } } } diff --git a/components/chainhook-event-observer/src/indexer/bitcoin/mod.rs b/components/chainhook-event-observer/src/indexer/bitcoin/mod.rs index 280505779..31df68543 100644 --- a/components/chainhook-event-observer/src/indexer/bitcoin/mod.rs +++ b/components/chainhook-event-observer/src/indexer/bitcoin/mod.rs @@ -6,6 +6,7 @@ use crate::chainhooks::types::{ get_canonical_pox_config, get_stacks_canonical_magic_bytes, PoxConfig, StacksOpcodes, }; +use crate::hord; use crate::observer::BitcoinConfig; use crate::utils::Context; use bitcoincore_rpc::bitcoin::hashes::hex::FromHex; @@ -23,7 +24,6 @@ use chainhook_types::{ StacksBlockCommitmentData, TransactionIdentifier, TransferSTXData, }; use hiro_system_kit::slog; - use serde::Deserialize; #[derive(Clone, PartialEq, Debug, Deserialize, Serialize)] @@ -355,9 +355,7 @@ pub fn standardize_bitcoin_block( let mut ordinal_operations = vec![]; #[cfg(feature = "ordinals")] - if let Some(op) = crate::hord::try_parse_ordinal_operation(&tx, block_height, ctx) { - ordinal_operations.push(op); - } + ordinal_operations.append(&mut hord::parse_ordinal_operations(&tx, block_height, ctx)); let mut inputs = vec![]; let mut sats_in = 0; diff --git a/components/chainhook-types-rs/src/rosetta.rs b/components/chainhook-types-rs/src/rosetta.rs index 01bb78a1e..63ce6f8a4 100644 --- a/components/chainhook-types-rs/src/rosetta.rs +++ b/components/chainhook-types-rs/src/rosetta.rs @@ -303,12 +303,13 @@ pub struct BitcoinTransactionMetadata { #[serde(rename_all = "snake_case")] pub enum OrdinalOperation { InscriptionRevealed(OrdinalInscriptionRevealData), + CursedInscriptionRevealed(OrdinalInscriptionRevealData), InscriptionTransferred(OrdinalInscriptionTransferData), } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct OrdinalInscriptionTransferData { - pub inscription_number: u64, + pub inscription_number: i64, pub inscription_id: String, pub ordinal_number: u64, pub updated_address: Option, @@ -322,7 +323,7 @@ pub struct OrdinalInscriptionRevealData { pub content_bytes: String, pub content_type: String, pub content_length: usize, - pub inscription_number: u64, + pub inscription_number: i64, pub inscription_fee: u64, pub inscription_output_value: u64, pub inscription_id: String, From af280b79295352ee7c1fa95f25369a251976244e Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Thu, 25 May 2023 15:29:19 -0400 Subject: [PATCH 02/12] chore: add helpers functions --- .../src/hord/db/mod.rs | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/components/chainhook-event-observer/src/hord/db/mod.rs b/components/chainhook-event-observer/src/hord/db/mod.rs index 7b7a5efb0..08cd3ddb5 100644 --- a/components/chainhook-event-observer/src/hord/db/mod.rs +++ b/components/chainhook-event-observer/src/hord/db/mod.rs @@ -833,6 +833,49 @@ impl TraversalResult { } } +pub fn format_satpoint_to_watch( + transaction_identifier: &TransactionIdentifier, + output_index: usize, + offset: u64, +) -> String { + format!( + "{}:{}:{}", + transaction_identifier.get_hash_bytes_str(), + output_index, + offset + ) +} + +pub fn parse_satpoint_to_watch(outpoint_to_watch: &str) -> (TransactionIdentifier, usize, u64) { + let comps: Vec<&str> = outpoint_to_watch.split(":").collect(); + let tx = TransactionIdentifier { + hash: format!("0x{}", comps[0]), + }; + let output_index = comps[1].to_string().parse::().unwrap(); + let offset = comps[2].to_string().parse::().unwrap(); + (tx, output_index, offset) +} + +pub fn format_outpoint_to_watch( + transaction_identifier: &TransactionIdentifier, + output_index: usize, +) -> String { + format!( + "{}:{}", + transaction_identifier.get_hash_bytes_str(), + output_index + ) +} + +pub fn parse_outpoint_to_watch(outpoint_to_watch: &str) -> (TransactionIdentifier, usize) { + let comps: Vec<&str> = outpoint_to_watch.split(":").collect(); + let tx = TransactionIdentifier { + hash: format!("0x{}", comps[0]), + }; + let output_index = comps[1].to_string().parse::().unwrap(); + (tx, output_index) +} + pub fn retrieve_satoshi_point_using_lazy_storage( blocks_db: &DB, block_identifier: &BlockIdentifier, From fd5da52df4f92a6a55a0149cf6b28f264afecc30 Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Thu, 25 May 2023 15:35:14 -0400 Subject: [PATCH 03/12] feat: handle transfer --- components/chainhook-cli/src/cli/mod.rs | 6 +- .../src/hord/db/mod.rs | 92 ++++++++++++-- .../chainhook-event-observer/src/hord/mod.rs | 112 +++++++++--------- components/chainhook-types-rs/src/rosetta.rs | 1 + 4 files changed, 142 insertions(+), 69 deletions(-) diff --git a/components/chainhook-cli/src/cli/mod.rs b/components/chainhook-cli/src/cli/mod.rs index be5d9d8b9..bb6fe3fef 100644 --- a/components/chainhook-cli/src/cli/mod.rs +++ b/components/chainhook-cli/src/cli/mod.rs @@ -15,9 +15,8 @@ use chainhook_event_observer::chainhooks::types::{ use chainhook_event_observer::hord::db::{ delete_data_in_hord_db, fetch_and_cache_blocks_in_hord_db, find_last_block_inserted, find_lazy_block_at_block_height, find_watched_satpoint_for_inscription, initialize_hord_db, - insert_entry_in_blocks, open_readonly_hord_db_conn, open_readonly_hord_db_conn_rocks_db, - open_readwrite_hord_db_conn, open_readwrite_hord_db_conn_rocks_db, - retrieve_satoshi_point_using_lazy_storage, LazyBlock, + open_readonly_hord_db_conn, open_readonly_hord_db_conn_rocks_db, open_readwrite_hord_db_conn, + open_readwrite_hord_db_conn_rocks_db, retrieve_satoshi_point_using_lazy_storage, }; use chainhook_event_observer::hord::{ new_traversals_lazy_cache, retrieve_inscribed_satoshi_points_from_block, @@ -643,6 +642,7 @@ async fn handle_command(opts: Opts, ctx: Context) -> Result<(), String> { &block_identifier, &transaction_identifier, 0, + 0, Arc::new(traversals_cache), &ctx, )?; diff --git a/components/chainhook-event-observer/src/hord/db/mod.rs b/components/chainhook-event-observer/src/hord/db/mod.rs index 08cd3ddb5..17271cc14 100644 --- a/components/chainhook-event-observer/src/hord/db/mod.rs +++ b/components/chainhook-event-observer/src/hord/db/mod.rs @@ -425,7 +425,7 @@ pub fn find_inscription_with_id( ) -> Option { let args: &[&dyn ToSql] = &[&inscription_id.to_sql().unwrap()]; let mut stmt = inscriptions_db_conn - .prepare("SELECT inscription_number, ordinal_number, block_hash FROM inscriptions WHERE inscription_id = ?") + .prepare("SELECT inscription_number, ordinal_number, block_hash, offset, outpoint_to_watch FROM inscriptions WHERE inscription_id = ?") .unwrap(); let mut rows = stmt.query(args).unwrap(); while let Ok(Some(row)) = rows.next() { @@ -433,9 +433,13 @@ pub fn find_inscription_with_id( if block_hash.eq(&inscription_block_hash) { let inscription_number: i64 = row.get(0).unwrap(); let ordinal_number: u64 = row.get(1).unwrap(); + let inscription_offset: u64 = row.get(3).unwrap(); + let outpoint_to_watch: String = row.get(4).unwrap(); let traversal = TraversalResult { inscription_number, ordinal_number, + inscription_offset, + outpoint_to_watch, transfers: 0, }; return Some(traversal); @@ -449,7 +453,7 @@ pub fn find_all_inscriptions( ) -> BTreeMap> { let args: &[&dyn ToSql] = &[]; let mut stmt = inscriptions_db_conn - .prepare("SELECT inscription_number, ordinal_number, block_height, inscription_id FROM inscriptions ORDER BY inscription_number ASC") + .prepare("SELECT inscription_number, ordinal_number, block_height, inscription_id, offset, outpoint_to_watch FROM inscriptions ORDER BY inscription_number ASC") .unwrap(); let mut results: BTreeMap> = BTreeMap::new(); let mut rows = stmt.query(args).unwrap(); @@ -463,10 +467,14 @@ pub fn find_all_inscriptions( hash: format!("0x{}", &inscription_id[0..inscription_id.len() - 2]), } }; + let inscription_offset: u64 = row.get(4).unwrap(); + let outpoint_to_watch: String = row.get(5).unwrap(); let traversal = TraversalResult { inscription_number, ordinal_number, transfers: 0, + inscription_offset, + outpoint_to_watch, }; results .entry(block_height) @@ -817,6 +825,8 @@ pub async fn fetch_and_cache_blocks_in_hord_db( #[derive(Clone, Debug)] pub struct TraversalResult { pub inscription_number: i64, + pub inscription_offset: u64, + pub outpoint_to_watch: String, pub ordinal_number: u64, pub transfers: u32, } @@ -880,6 +890,7 @@ pub fn retrieve_satoshi_point_using_lazy_storage( blocks_db: &DB, block_identifier: &BlockIdentifier, transaction_identifier: &TransactionIdentifier, + input_index: usize, inscription_number: i64, traversals_cache: Arc< DashMap<(u32, [u8; 8]), LazyBlockTransaction, BuildHasherDefault>, @@ -894,16 +905,13 @@ pub fn retrieve_satoshi_point_using_lazy_storage( block_identifier.index ) }); - + let mut inscription_localized = false; + let mut inscription_offset = 0; + let mut inscription_output_index: usize = 0; let mut ordinal_offset = 0; let mut ordinal_block_number = block_identifier.index as u32; - let txid = { - let bytes = hex::decode(&transaction_identifier.hash[2..]).unwrap(); - [ - bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], - ] - }; - let mut tx_cursor = (txid, 0); + let txid = transaction_identifier.get_8_hash_bytes(); + let mut tx_cursor = (txid, input_index); let mut hops: u32 = 0; loop { hops += 1; @@ -916,6 +924,31 @@ pub fn retrieve_satoshi_point_using_lazy_storage( if let Some(cached_tx) = traversals_cache.get(&(ordinal_block_number, tx_cursor.0)) { let tx = cached_tx.value(); + + if !inscription_localized { + inscription_localized = true; + let mut sats_ranges = vec![]; + let mut bound = 0; + for output_value in tx.outputs.iter() { + sats_ranges.push((bound, bound + output_value)); + bound += output_value; + } + let mut input_offset = 0; + for (i, input) in tx.inputs.iter().enumerate() { + if i == input_index { + break; + } + input_offset += input.txin_value; + } + + for (i, (min, max)) in sats_ranges.into_iter().enumerate() { + if input_offset >= min && input_offset < max { + inscription_output_index = i; + inscription_offset = input_offset - min; + } + } + } + let mut next_found_in_cache = false; let mut sats_out = 0; for (index, output_value) in tx.outputs.iter().enumerate() { @@ -955,6 +988,11 @@ pub fn retrieve_satoshi_point_using_lazy_storage( inscription_number: 0, ordinal_number: 0, transfers: 0, + inscription_offset, + outpoint_to_watch: format_outpoint_to_watch( + &transaction_identifier, + inscription_output_index, + ), }); } } @@ -1022,6 +1060,30 @@ pub fn retrieve_satoshi_point_using_lazy_storage( None => unreachable!(), }; + if !inscription_localized { + inscription_localized = true; + let mut sats_ranges = vec![]; + let mut bound = 0; + for output_value in lazy_tx.outputs.iter() { + sats_ranges.push((bound, bound + output_value)); + bound += output_value; + } + let mut input_offset = 0; + for (i, input) in lazy_tx.inputs.iter().enumerate() { + if i == input_index { + break; + } + input_offset += input.txin_value; + } + + for (i, (min, max)) in sats_ranges.into_iter().enumerate() { + if input_offset >= min && input_offset < max { + inscription_output_index = i; + inscription_offset = input_offset - min; + } + } + } + let mut sats_out = 0; for (index, output_value) in lazy_tx.outputs.iter().enumerate() { if index == tx_cursor.1 { @@ -1056,6 +1118,11 @@ pub fn retrieve_satoshi_point_using_lazy_storage( inscription_number: 0, ordinal_number: 0, transfers: 0, + inscription_offset, + outpoint_to_watch: format_outpoint_to_watch( + &transaction_identifier, + inscription_output_index, + ), }); } } @@ -1068,6 +1135,11 @@ pub fn retrieve_satoshi_point_using_lazy_storage( inscription_number, ordinal_number, transfers: hops, + inscription_offset, + outpoint_to_watch: format_outpoint_to_watch( + &transaction_identifier, + inscription_output_index, + ), }) } diff --git a/components/chainhook-event-observer/src/hord/mod.rs b/components/chainhook-event-observer/src/hord/mod.rs index fcb9c75a8..99de797fb 100644 --- a/components/chainhook-event-observer/src/hord/mod.rs +++ b/components/chainhook-event-observer/src/hord/mod.rs @@ -22,6 +22,7 @@ use std::sync::mpsc::channel; use std::sync::Arc; use threadpool::ThreadPool; +use crate::hord::db::format_outpoint_to_watch; use crate::indexer::bitcoin::BitcoinTransactionFullBreakdown; use crate::{ hord::{ @@ -87,48 +88,27 @@ pub fn parse_ordinal_operations( None }; + let payload = OrdinalInscriptionRevealData { + content_type: inscription.content_type().unwrap_or("unknown").to_string(), + content_bytes: format!("0x{}", hex::encode(&inscription_content_bytes)), + content_length: inscription_content_bytes.len(), + inscription_id: inscription_id.to_string(), + inscriber_address, + inscription_output_value, + inscription_fee: 0, + inscription_input_index: input_index, + inscription_number: 0, + ordinal_number: 0, + ordinal_block_height: 0, + ordinal_offset: 0, + transfers_pre_inscription: 0, + satpoint_post_inscription: format!("{}:0:0", tx.txid.clone()), + }; + if input_index == 0 { - operations.push(OrdinalOperation::InscriptionRevealed( - OrdinalInscriptionRevealData { - content_type: inscription - .content_type() - .unwrap_or("unknown") - .to_string(), - content_bytes: format!("0x{}", hex::encode(&inscription_content_bytes)), - content_length: inscription_content_bytes.len(), - inscription_id: inscription_id.to_string(), - inscriber_address, - inscription_output_value, - inscription_fee: 0, - inscription_number: 0, - ordinal_number: 0, - ordinal_block_height: 0, - ordinal_offset: 0, - transfers_pre_inscription: 0, - satpoint_post_inscription: format!("{}:0:0", tx.txid.clone()), - }, - )) + operations.push(OrdinalOperation::InscriptionRevealed(payload)); } else { - operations.push(OrdinalOperation::CursedInscriptionRevealed( - OrdinalInscriptionRevealData { - content_type: inscription - .content_type() - .unwrap_or("unknown") - .to_string(), - content_bytes: format!("0x{}", hex::encode(&inscription_content_bytes)), - content_length: inscription_content_bytes.len(), - inscription_id: inscription_id.to_string(), - inscriber_address, - inscription_output_value, - inscription_fee: 0, - inscription_number: 0, - ordinal_number: 0, - ordinal_block_height: 0, - ordinal_offset: 0, - transfers_pre_inscription: 0, - satpoint_post_inscription: format!("{}:0:0", tx.txid.clone()), - }, - )) + operations.push(OrdinalOperation::CursedInscriptionRevealed(payload)); } } } @@ -221,23 +201,38 @@ pub fn retrieve_inscribed_satoshi_points_from_block( for tx in block.transactions.iter().skip(1) { // Have a new inscription been revealed, if so, are looking at a re-inscription for ordinal_event in tx.metadata.ordinal_operations.iter() { - if let OrdinalOperation::InscriptionRevealed(inscription_data) = ordinal_event { - if let Some(inscriptions_db_conn) = inscriptions_db_conn { - if let Some(traversal) = find_inscription_with_id( - &inscription_data.inscription_id, - &block.block_identifier.hash, - inscriptions_db_conn, - ctx, - ) { - traversals.insert(tx.transaction_identifier.clone(), traversal); - } else { - // Enqueue for traversals - transactions_ids.push(tx.transaction_identifier.clone()); - } + let (inscription_data, _is_cursed) = match ordinal_event { + OrdinalOperation::InscriptionRevealed(inscription_data) => { + (inscription_data, false) + } + OrdinalOperation::CursedInscriptionRevealed(inscription_data) => { + (inscription_data, false) + } + OrdinalOperation::InscriptionTransferred(_) => { + continue; + } + }; + if let Some(inscriptions_db_conn) = inscriptions_db_conn { + if let Some(traversal) = find_inscription_with_id( + &inscription_data.inscription_id, + &block.block_identifier.hash, + inscriptions_db_conn, + ctx, + ) { + traversals.insert(tx.transaction_identifier.clone(), traversal); } else { // Enqueue for traversals - transactions_ids.push(tx.transaction_identifier.clone()); + transactions_ids.push(( + tx.transaction_identifier.clone(), + inscription_data.inscription_input_index, + )); } + } else { + // Enqueue for traversals + transactions_ids.push(( + tx.transaction_identifier.clone(), + inscription_data.inscription_input_index, + )); } } } @@ -249,7 +244,7 @@ pub fn retrieve_inscribed_satoshi_points_from_block( let mut rng = thread_rng(); transactions_ids.shuffle(&mut rng); - for transaction_id in transactions_ids.into_iter() { + for (transaction_id, input_index) in transactions_ids.into_iter() { let moved_traversal_tx = traversal_tx.clone(); let moved_ctx = ctx.clone(); let block_identifier = block.block_identifier.clone(); @@ -262,6 +257,7 @@ pub fn retrieve_inscribed_satoshi_points_from_block( &blocks_db, &block_identifier, &transaction_id, + input_index, 0, local_cache, &moved_ctx, @@ -466,6 +462,10 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( inscription.inscription_number = traversal.inscription_number; inscription.transfers_pre_inscription = traversal.transfers; inscription.inscription_fee = new_tx.metadata.fee; + inscription.satpoint_post_inscription = format!( + "{}:{}", + traversal.outpoint_to_watch, traversal.inscription_offset + ); match storage { Storage::Sqlite(rw_hord_db_conn) => { @@ -644,7 +644,7 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_transfer_data( ) = match post_transfer_output { Some(index) => { let outpoint = - format!("{}:{}", &new_tx.transaction_identifier.hash[2..], index); + format_outpoint_to_watch(&new_tx.transaction_identifier, index); let offset = (sats_in_offset + watched_satpoint.offset) - sats_out_offset; let script_pub_key_hex = new_tx.metadata.outputs[index].get_script_pubkey_hex(); diff --git a/components/chainhook-types-rs/src/rosetta.rs b/components/chainhook-types-rs/src/rosetta.rs index 63ce6f8a4..e21bef3c1 100644 --- a/components/chainhook-types-rs/src/rosetta.rs +++ b/components/chainhook-types-rs/src/rosetta.rs @@ -327,6 +327,7 @@ pub struct OrdinalInscriptionRevealData { pub inscription_fee: u64, pub inscription_output_value: u64, pub inscription_id: String, + pub inscription_input_index: usize, pub inscriber_address: Option, pub ordinal_number: u64, pub ordinal_block_height: u64, From a030926fb9ce09c2ce43454f8281b1c632991d1f Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Thu, 25 May 2023 15:35:31 -0400 Subject: [PATCH 04/12] refactor: use helpers --- .../chainhook-event-observer/src/hord/db/mod.rs | 17 ++++------------- .../src/observer/mod.rs | 3 ++- components/chainhook-types-rs/src/rosetta.rs | 17 +++++++++++++++++ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/components/chainhook-event-observer/src/hord/db/mod.rs b/components/chainhook-event-observer/src/hord/db/mod.rs index 17271cc14..d7274a7f1 100644 --- a/components/chainhook-event-observer/src/hord/db/mod.rs +++ b/components/chainhook-event-observer/src/hord/db/mod.rs @@ -1378,13 +1378,9 @@ impl LazyBlock { buffer.write(&outputs_len.to_be_bytes())?; } // Coinbase transaction txid - 8 first bytes - let coinbase_txid = { - let txid = - hex::decode(&block.transactions[0].transaction_identifier.hash[2..]).unwrap(); - [ - txid[0], txid[1], txid[2], txid[3], txid[4], txid[5], txid[6], txid[7], - ] - }; + let coinbase_txid = block.transactions[0] + .transaction_identifier + .get_8_hash_bytes(); buffer.write_all(&coinbase_txid)?; // Coinbase transaction value let mut coinbase_value = 0; @@ -1395,12 +1391,7 @@ impl LazyBlock { // For each transaction: for tx in block.transactions.iter().skip(1) { // txid - 8 first bytes - let txid = { - let txid = hex::decode(&tx.transaction_identifier.hash[2..]).unwrap(); - [ - txid[0], txid[1], txid[2], txid[3], txid[4], txid[5], txid[6], txid[7], - ] - }; + let txid = tx.transaction_identifier.get_8_hash_bytes(); buffer.write_all(&txid)?; // For each transaction input: for input in tx.metadata.inputs.iter() { diff --git a/components/chainhook-event-observer/src/observer/mod.rs b/components/chainhook-event-observer/src/observer/mod.rs index fe5a1b2d3..1442bdfc4 100644 --- a/components/chainhook-event-observer/src/observer/mod.rs +++ b/components/chainhook-event-observer/src/observer/mod.rs @@ -521,7 +521,8 @@ pub fn get_bitcoin_proof( transaction_identifier: &TransactionIdentifier, block_identifier: &BlockIdentifier, ) -> Result { - let txid = Txid::from_str(&transaction_identifier.hash[2..]).expect("unable to build txid"); + let txid = + Txid::from_str(&transaction_identifier.get_hash_bytes_str()).expect("unable to build txid"); let block_hash = BlockHash::from_str(&block_identifier.hash[2..]).expect("unable to build block_hash"); diff --git a/components/chainhook-types-rs/src/rosetta.rs b/components/chainhook-types-rs/src/rosetta.rs index e21bef3c1..05a63afd9 100644 --- a/components/chainhook-types-rs/src/rosetta.rs +++ b/components/chainhook-types-rs/src/rosetta.rs @@ -404,6 +404,23 @@ pub struct TransactionIdentifier { pub hash: String, } +impl TransactionIdentifier { + pub fn get_hash_bytes_str(&self) -> &str { + &self.hash[2..] + } + + pub fn get_hash_bytes(&self) -> Vec { + hex::decode(&self.get_hash_bytes_str()).unwrap() + } + + pub fn get_8_hash_bytes(&self) -> [u8; 8] { + let bytes = self.get_hash_bytes(); + [ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + ] + } +} + #[derive( Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, strum::EnumIter, strum::IntoStaticStr, )] From fe260635132ae685ecaf2d2dbdc054d6ea4549bf Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Thu, 25 May 2023 16:40:07 -0400 Subject: [PATCH 05/12] fix: additional adjustments --- components/chainhook-cli/src/scan/bitcoin.rs | 12 +-- .../src/hord/db/mod.rs | 24 ++++- .../chainhook-event-observer/src/hord/mod.rs | 101 +++++++++--------- 3 files changed, 76 insertions(+), 61 deletions(-) diff --git a/components/chainhook-cli/src/scan/bitcoin.rs b/components/chainhook-cli/src/scan/bitcoin.rs index 540dd8359..45fb8d9a1 100644 --- a/components/chainhook-cli/src/scan/bitcoin.rs +++ b/components/chainhook-cli/src/scan/bitcoin.rs @@ -61,7 +61,7 @@ pub async fn scan_bitcoin_chainstate_via_http_using_predicate( let (mut end_block, floating_end_block) = match predicate_spec.end_block { Some(end_block) => (end_block, false), None => match bitcoin_rpc.get_blockchain_info() { - Ok(result) => (result.blocks, true), + Ok(result) => (result.blocks - 1, true), Err(e) => { return Err(format!( "unable to retrieve Bitcoin chain tip ({})", @@ -184,19 +184,19 @@ pub async fn scan_bitcoin_chainstate_via_http_using_predicate( } }; - update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( + let _ = update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( &mut block, &mut storage, &traversals, &hord_db_conn, &ctx, - ); + )?; let _ = update_storage_and_augment_bitcoin_block_with_inscription_transfer_data( &mut block, &mut storage, &ctx, - ); + )?; let inscriptions_revealed = get_inscriptions_revealed_in_block(&block) .iter() @@ -234,7 +234,7 @@ pub async fn scan_bitcoin_chainstate_via_http_using_predicate( if cursor == end_block && floating_end_block { end_block = match bitcoin_rpc.get_blockchain_info() { - Ok(result) => result.blocks, + Ok(result) => result.blocks - 1, Err(_e) => { continue; } @@ -294,7 +294,7 @@ pub async fn scan_bitcoin_chainstate_via_http_using_predicate( if cursor == end_block && floating_end_block { end_block = match bitcoin_rpc.get_blockchain_info() { - Ok(result) => result.blocks, + Ok(result) => result.blocks - 1, Err(_e) => { continue; } diff --git a/components/chainhook-event-observer/src/hord/db/mod.rs b/components/chainhook-event-observer/src/hord/db/mod.rs index d7274a7f1..51b23118c 100644 --- a/components/chainhook-event-observer/src/hord/db/mod.rs +++ b/components/chainhook-event-observer/src/hord/db/mod.rs @@ -299,15 +299,31 @@ pub fn delete_blocks_in_block_range( .expect("unable to insert metadata"); } -pub fn store_new_inscription( +pub fn insert_entry_in_inscriptions( inscription_data: &OrdinalInscriptionRevealData, block_identifier: &BlockIdentifier, - hord_db_conn: &Connection, + inscriptions_db_conn_rw: &Connection, ctx: &Context, ) { - if let Err(e) = hord_db_conn.execute( + let (tx, output_index, offset) = + parse_satpoint_to_watch(&inscription_data.satpoint_post_inscription); + let outpoint_to_watch = format_outpoint_to_watch(&tx, output_index); + if let Err(e) = inscriptions_db_conn_rw.execute( "INSERT INTO inscriptions (inscription_id, outpoint_to_watch, ordinal_number, inscription_number, offset, block_height, block_hash) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)", - rusqlite::params![&inscription_data.inscription_id, &inscription_data.satpoint_post_inscription[0..inscription_data.satpoint_post_inscription.len()-2], &inscription_data.ordinal_number, &inscription_data.inscription_number, 0, &block_identifier.index, &block_identifier.hash], + rusqlite::params![&inscription_data.inscription_id, &outpoint_to_watch, &inscription_data.ordinal_number, &inscription_data.inscription_number, offset, &block_identifier.index, &block_identifier.hash], + ) { + ctx.try_log(|logger| slog::error!(logger, "{}", e.to_string())); + } +} + +pub fn insert_entry_in_transfers( + block_height: u32, + inscriptions_db_conn_rw: &Connection, + ctx: &Context, +) { + if let Err(e) = inscriptions_db_conn_rw.execute( + "INSERT INTO transfers (block_height) VALUES (?1)", + rusqlite::params![&block_height], ) { ctx.try_log(|logger| slog::error!(logger, "{}", e.to_string())); } diff --git a/components/chainhook-event-observer/src/hord/mod.rs b/components/chainhook-event-observer/src/hord/mod.rs index 99de797fb..249a857db 100644 --- a/components/chainhook-event-observer/src/hord/mod.rs +++ b/components/chainhook-event-observer/src/hord/mod.rs @@ -28,8 +28,8 @@ use crate::{ hord::{ db::{ find_inscription_with_ordinal_number, find_inscriptions_at_wached_outpoint, - insert_entry_in_blocks, retrieve_satoshi_point_using_lazy_storage, - store_new_inscription, update_transfered_inscription, + insert_entry_in_blocks, insert_entry_in_inscriptions, insert_entry_in_transfers, + retrieve_satoshi_point_using_lazy_storage, update_transfered_inscription, }, ord::height::Height, }, @@ -39,8 +39,8 @@ use crate::{ use self::db::{ find_inscription_with_id, find_latest_cursed_inscription_number_at_block_height, find_latest_inscription_number_at_block_height, open_readonly_hord_db_conn_rocks_db, - remove_entry_from_blocks, remove_entry_from_inscriptions, LazyBlock, LazyBlockTransaction, - TraversalResult, WatchedSatpoint, + parse_satpoint_to_watch, remove_entry_from_blocks, remove_entry_from_inscriptions, LazyBlock, + LazyBlockTransaction, TraversalResult, WatchedSatpoint, }; use self::inscription::InscriptionParser; use self::ord::inscription_id::InscriptionId; @@ -353,20 +353,31 @@ pub fn update_hord_db_and_augment_bitcoin_block( ); let mut storage = Storage::Sqlite(inscriptions_db_conn_rw); - update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( - new_block, - &mut storage, - &traversals, - &inscriptions_db_conn_rw, - &ctx, - ); + let any_inscription_revealed = + update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( + new_block, + &mut storage, + &traversals, + &inscriptions_db_conn_rw, + &ctx, + )?; // Have inscriptions been transfered? - update_storage_and_augment_bitcoin_block_with_inscription_transfer_data( - new_block, - &mut storage, - &ctx, - )?; + let any_inscription_transferred = + update_storage_and_augment_bitcoin_block_with_inscription_transfer_data( + new_block, + &mut storage, + &ctx, + )?; + + if any_inscription_revealed || any_inscription_transferred { + insert_entry_in_transfers( + new_block.block_identifier.index as u32, + inscriptions_db_conn_rw, + ctx, + ) + } + Ok(()) } @@ -382,24 +393,16 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( traversals: &HashMap, inscription_db_conn: &Connection, ctx: &Context, -) { +) -> Result { + let mut storage_updated = false; + let mut latest_inscription_number = match find_latest_inscription_number_at_block_height( &block.block_identifier.index, &inscription_db_conn, &ctx, - ) { - Ok(None) => 0, - Ok(Some(inscription_number)) => inscription_number + 1, - Err(e) => { - ctx.try_log(|logger| { - slog::error!( - logger, - "unable to retrieve inscription number: {}", - e.to_string() - ); - }); - return; - } + )? { + None => 0, + Some(inscription_number) => inscription_number + 1, }; let mut latest_cursed_inscription_number = @@ -407,19 +410,9 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( &block.block_identifier.index, &inscription_db_conn, &ctx, - ) { - Ok(None) => -1, - Ok(Some(inscription_number)) => inscription_number + 1, - Err(e) => { - ctx.try_log(|logger| { - slog::error!( - logger, - "unable to retrieve inscription number: {}", - e.to_string() - ); - }); - return; - } + )? { + None => -1, + Some(inscription_number) => inscription_number - 1, }; let mut sats_overflow = vec![]; @@ -513,7 +506,7 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( inscription.transfers_pre_inscription, ); }); - store_new_inscription( + insert_entry_in_inscriptions( &inscription, &block.block_identifier, &rw_hord_db_conn, @@ -521,20 +514,21 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( ); } Storage::Memory(map) => { - let outpoint = inscription.satpoint_post_inscription - [0..inscription.satpoint_post_inscription.len() - 2] - .to_string(); + let (tx, output_index, offset) = + parse_satpoint_to_watch(&inscription.satpoint_post_inscription); + let outpoint = format_outpoint_to_watch(&tx, output_index); map.insert( outpoint, vec![WatchedSatpoint { inscription_id: inscription.inscription_id.clone(), inscription_number: inscription.inscription_number, ordinal_number: inscription.ordinal_number, - offset: 0, + offset, }], ); } } + storage_updated = true; } for index in ordinals_events_indexes_to_discard.into_iter() { @@ -558,16 +552,19 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( inscription.transfers_pre_inscription, ); }); - store_new_inscription( + insert_entry_in_inscriptions( &inscription, &block.block_identifier, &rw_hord_db_conn, &ctx, ); + storage_updated = true; } _ => {} } } + + Ok(storage_updated) } /// For each input of each transaction in the block, we retrieve the UTXO spent (outpoint_pre_transfer) @@ -581,7 +578,8 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_transfer_data( block: &mut BitcoinBlockData, storage: &mut Storage, ctx: &Context, -) -> Result<(), String> { +) -> Result { + let mut storage_updated = false; let mut cumulated_fees = 0; let first_sat_post_subsidy = Height(block.block_identifier.index).starting_sat().0; let coinbase_txid = &block.transactions[0].transaction_identifier.hash.clone(); @@ -720,6 +718,7 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_transfer_data( .or_insert(vec![watched_satpoint.clone()]); } }; + storage_updated = true; let satpoint_post_transfer = format!("{}:{}", outpoint_post_transfer, offset_post_transfer); @@ -744,5 +743,5 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_transfer_data( } cumulated_fees += new_tx.metadata.fee; } - Ok(()) + Ok(storage_updated) } From b50bbc1bf7a6cb41cf224f1b01cb6ba1b02907b8 Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Tue, 30 May 2023 20:07:50 -0400 Subject: [PATCH 06/12] fix: only avoid override for blessed inscriptions --- components/chainhook-event-observer/src/hord/db/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/chainhook-event-observer/src/hord/db/mod.rs b/components/chainhook-event-observer/src/hord/db/mod.rs index 51b23118c..558cda10e 100644 --- a/components/chainhook-event-observer/src/hord/db/mod.rs +++ b/components/chainhook-event-observer/src/hord/db/mod.rs @@ -423,7 +423,7 @@ pub fn find_inscription_with_ordinal_number( ) -> Option { let args: &[&dyn ToSql] = &[&ordinal_number.to_sql().unwrap()]; let mut stmt = inscriptions_db_conn - .prepare("SELECT inscription_id FROM inscriptions WHERE ordinal_number = ?") + .prepare("SELECT inscription_id FROM inscriptions WHERE ordinal_number = ? AND inscription_number > 0") .unwrap(); let mut rows = stmt.query(args).unwrap(); while let Ok(Some(row)) = rows.next() { From 2af31a8e644abc8132db1091985f8ea6ba2bbc91 Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Tue, 30 May 2023 20:25:31 -0400 Subject: [PATCH 07/12] fix: rocket_okapi version --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 089eae48f..8ab6e21c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3403,9 +3403,9 @@ dependencies = [ [[package]] name = "rocket_okapi" -version = "0.8.0-rc.2" +version = "0.8.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489f4f5b120762f7974e65b919fc462d0660fd8b839026d8985b850fe5acccb0" +checksum = "0025aa04994af8cd8e1fcdd5a73579a395c941ae090ecb0a39b41cca7e237a20" dependencies = [ "either", "log", @@ -3419,9 +3419,9 @@ dependencies = [ [[package]] name = "rocket_okapi_codegen" -version = "0.8.0-rc.2" +version = "0.8.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54f94d1ffe41472e08463d7a2674f1db04dc4df745285e8369b33d3cfd6b0308" +checksum = "dc114779fc27afb78179233e966f469e47fd7a98dc15181cff2574cdddb65612" dependencies = [ "darling", "proc-macro2", From 969d3cf57c5ce87f8b1876a1910948205d32eeb3 Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Tue, 30 May 2023 20:33:46 -0400 Subject: [PATCH 08/12] chore: update rocket - v0.5 rc3 --- Cargo.lock | 406 ++++++++++-------- .../chainhook-event-observer/Cargo.toml | 4 +- 2 files changed, 217 insertions(+), 193 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ab6e21c3..7612919d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,41 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "aead" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" -dependencies = [ - "generic-array 0.14.6", -] - -[[package]] -name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if 1.0.0", - "cipher", - "cpufeatures", - "opaque-debug 0.3.0", -] - -[[package]] -name = "aes-gcm" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle 2.4.1", -] - [[package]] name = "ahash" version = "0.3.8" @@ -147,7 +112,7 @@ checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -158,7 +123,7 @@ checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -278,7 +243,7 @@ version = "0.64.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cexpr", "clang-sys", "lazy_static", @@ -289,7 +254,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn", + "syn 1.0.105", ] [[package]] @@ -359,6 +324,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6776fc96284a0bb647b615056fc496d1fe1644a7ab01829818a6d91cae888b84" + [[package]] name = "block-buffer" version = "0.7.3" @@ -607,15 +578,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array 0.14.6", -] - [[package]] name = "clang-sys" version = "1.6.1" @@ -633,7 +595,7 @@ version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "bitflags", + "bitflags 1.3.2", "textwrap 0.11.0", "unicode-width", ] @@ -645,7 +607,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "atty", - "bitflags", + "bitflags 1.3.2", "clap_derive", "clap_lex", "indexmap", @@ -674,7 +636,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -858,18 +820,11 @@ checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" [[package]] name = "cookie" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" +checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" dependencies = [ - "aes-gcm", - "base64 0.13.1", - "hkdf", - "hmac 0.12.1", "percent-encoding", - "rand 0.8.5", - "sha2 0.10.6", - "subtle 2.4.1", "time 0.3.17", "version_check", ] @@ -1117,15 +1072,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ctr" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" -dependencies = [ - "cipher", -] - [[package]] name = "ctrlc" version = "3.2.3" @@ -1174,7 +1120,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 1.0.105", ] [[package]] @@ -1191,7 +1137,7 @@ checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -1215,7 +1161,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 1.0.105", ] [[package]] @@ -1226,7 +1172,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -1266,9 +1212,9 @@ dependencies = [ [[package]] name = "devise" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c7580b072f1c8476148f16e0a0d5dedddab787da98d86c5082c5e9ed8ab595" +checksum = "d6eacefd3f541c66fc61433d65e54e0e46e0a029a819a7dbbc7a7b489e8a85f8" dependencies = [ "devise_codegen", "devise_core", @@ -1276,9 +1222,9 @@ dependencies = [ [[package]] name = "devise_codegen" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123c73e7a6e51b05c75fe1a1b2f4e241399ea5740ed810b0e3e6cacd9db5e7b2" +checksum = "9c8cf4b8dd484ede80fd5c547592c46c3745a617c8af278e2b72bea86b2dfed6" dependencies = [ "devise_core", "quote", @@ -1286,15 +1232,15 @@ dependencies = [ [[package]] name = "devise_core" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841ef46f4787d9097405cac4e70fb8644fc037b526e8c14054247c0263c400d0" +checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a" dependencies = [ - "bitflags", + "bitflags 2.3.1", "proc-macro2", - "proc-macro2-diagnostics", + "proc-macro2-diagnostics 0.10.0", "quote", - "syn", + "syn 2.0.18", ] [[package]] @@ -1407,7 +1353,7 @@ checksum = "c375b9c5eadb68d0a6efee2999fef292f45854c3444c86f09d8ab086ba942b0e" dependencies = [ "num-traits", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -1421,6 +1367,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "errno-dragonfly" version = "0.1.2" @@ -1475,7 +1432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb21c69b9fea5e15dbc1049e4b77145dd0ba1c84019c488102de0dc4ea4b0a27" dependencies = [ "cfg-if 1.0.0", - "rustix", + "rustix 0.36.5", "windows-sys 0.42.0", ] @@ -1614,7 +1571,7 @@ checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -1712,16 +1669,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "ghash" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" -dependencies = [ - "opaque-debug 0.3.0", - "polyval", -] - [[package]] name = "gimli" version = "0.27.2" @@ -1809,12 +1756,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" [[package]] name = "hex" @@ -1851,15 +1795,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "hkdf" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" -dependencies = [ - "hmac 0.12.1", -] - [[package]] name = "hmac" version = "0.7.1" @@ -2072,12 +2007,13 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.3" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ + "hermit-abi 0.3.1", "libc", - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] @@ -2088,14 +2024,14 @@ checksum = "ec947b7a4ce12e3b87e353abae7ce124d025b6c7d6c5aea5cc0bcf92e9510ded" [[package]] name = "is-terminal" -version = "0.4.2" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.1", "io-lifetimes", - "rustix", - "windows-sys 0.42.0", + "rustix 0.37.19", + "windows-sys 0.48.0", ] [[package]] @@ -2172,9 +2108,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.138" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "libloading" @@ -2350,6 +2286,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f" +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + [[package]] name = "lock_api" version = "0.4.9" @@ -2543,7 +2485,7 @@ version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cc", "cfg-if 1.0.0", "libc", @@ -2557,7 +2499,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" dependencies = [ "autocfg", - "bitflags", + "bitflags 1.3.2", "cfg-if 1.0.0", "libc", ] @@ -2677,7 +2619,7 @@ version = "0.10.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if 1.0.0", "foreign-types", "libc", @@ -2694,7 +2636,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -2823,9 +2765,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82a5ca643c2303ecb740d506539deba189e16f2754040a42901cd8105d0282d0" dependencies = [ "proc-macro2", - "proc-macro2-diagnostics", + "proc-macro2-diagnostics 0.9.1", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -2873,7 +2815,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -2922,18 +2864,6 @@ dependencies = [ "plotters-backend", ] -[[package]] -name = "polyval" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "opaque-debug 0.3.0", - "universal-hash", -] - [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2963,7 +2893,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.105", "version_check", ] @@ -2986,9 +2916,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" dependencies = [ "unicode-ident", ] @@ -3001,7 +2931,20 @@ checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", + "version_check", + "yansi", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "606c4ba35817e2922a308af55ad51bab3645b59eae5c570d4a6cf07e36bd493b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", "version_check", "yansi", ] @@ -3017,9 +2960,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.21" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" dependencies = [ "proc-macro2", ] @@ -3172,7 +3115,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -3203,7 +3146,7 @@ checksum = "abfa8511e9e94fd3de6585a3d3cd00e01ed556dc9814829280af0e8dc72a8f36" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -3321,20 +3264,20 @@ dependencies = [ [[package]] name = "rocket" -version = "0.5.0-rc.2" +version = "0.5.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ead083fce4a405feb349cf09abdf64471c6077f14e0ce59364aa90d4b99317" +checksum = "58734f7401ae5cfd129685b48f61182331745b357b96f2367f01aebaf1cc9cc9" dependencies = [ "async-stream", "async-trait", "atomic", - "atty", "binascii", "bytes", "either", "figment", "futures", "indexmap", + "is-terminal", "log", "memchr", "multer", @@ -3360,9 +3303,9 @@ dependencies = [ [[package]] name = "rocket_codegen" -version = "0.5.0-rc.2" +version = "0.5.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6aeb6bb9c61e9cd2c00d70ea267bf36f76a4cc615e5908b349c2f9d93999b47" +checksum = "7093353f14228c744982e409259fb54878ba9563d08214f2d880d59ff2fc508b" dependencies = [ "devise", "glob", @@ -3370,15 +3313,15 @@ dependencies = [ "proc-macro2", "quote", "rocket_http", - "syn", + "syn 2.0.18", "unicode-xid", ] [[package]] name = "rocket_http" -version = "0.5.0-rc.2" +version = "0.5.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ded65d127954de3c12471630bf4b81a2792f065984461e65b91d0fdaafc17a2" +checksum = "936012c99162a03a67f37f9836d5f938f662e26f2717809761a9ac46432090f4" dependencies = [ "cookie", "either", @@ -3403,9 +3346,9 @@ dependencies = [ [[package]] name = "rocket_okapi" -version = "0.8.0-rc.1" +version = "0.8.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0025aa04994af8cd8e1fcdd5a73579a395c941ae090ecb0a39b41cca7e237a20" +checksum = "742098674565c8f0c35c77444f90344aafedebb71cfee9cdbf0185acc6b9cdb7" dependencies = [ "either", "log", @@ -3419,15 +3362,15 @@ dependencies = [ [[package]] name = "rocket_okapi_codegen" -version = "0.8.0-rc.1" +version = "0.8.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc114779fc27afb78179233e966f469e47fd7a98dc15181cff2574cdddb65612" +checksum = "8c43f8edc57d88750a220b0ec1870a36c1106204ec99cc35131b49de3b954a4a" dependencies = [ "darling", "proc-macro2", "quote", "rocket_http", - "syn", + "syn 1.0.105", ] [[package]] @@ -3450,7 +3393,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.0", - "syn", + "syn 1.0.105", ] [[package]] @@ -3461,7 +3404,7 @@ checksum = "32c6cfaae58c048728261723a72b80a0aa9f3768e9a7da3b302a24d262525219" dependencies = [ "quote", "rustc_version 0.3.3", - "syn", + "syn 1.0.105", ] [[package]] @@ -3470,7 +3413,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85127183a999f7db96d1a976a309eebbfb6ea3b0b400ddd8340190129de6eb7a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -3525,14 +3468,28 @@ version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588" dependencies = [ - "bitflags", - "errno", + "bitflags 1.3.2", + "errno 0.2.8", "io-lifetimes", "libc", - "linux-raw-sys", + "linux-raw-sys 0.1.3", "windows-sys 0.42.0", ] +[[package]] +name = "rustix" +version = "0.37.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +dependencies = [ + "bitflags 1.3.2", + "errno 0.3.1", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + [[package]] name = "rustls" version = "0.20.7" @@ -3566,7 +3523,7 @@ version = "9.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db7826789c0e25614b03e5a54a0717a86f9ff6e6e5247f92b369472869320039" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if 1.0.0", "clipboard-win", "dirs-next", @@ -3631,7 +3588,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn", + "syn 1.0.105", ] [[package]] @@ -3688,7 +3645,7 @@ version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -3792,7 +3749,7 @@ checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -3803,7 +3760,7 @@ checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -4160,7 +4117,7 @@ dependencies = [ "quote", "serde", "serde_derive", - "syn", + "syn 1.0.105", ] [[package]] @@ -4176,7 +4133,7 @@ dependencies = [ "serde_derive", "serde_json", "sha1", - "syn", + "syn 1.0.105", ] [[package]] @@ -4216,7 +4173,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn", + "syn 1.0.105", ] [[package]] @@ -4242,6 +4199,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "take_mut" version = "0.2.2" @@ -4325,7 +4293,7 @@ checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -4421,7 +4389,7 @@ dependencies = [ "proc-macro2", "quote", "standback", - "syn", + "syn 1.0.105", ] [[package]] @@ -4499,7 +4467,7 @@ checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -4599,7 +4567,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -4717,16 +4685,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" -[[package]] -name = "universal-hash" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" -dependencies = [ - "generic-array 0.14.6", - "subtle 2.4.1", -] - [[package]] name = "untrusted" version = "0.7.1" @@ -4854,7 +4812,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.105", "wasm-bindgen-shared", ] @@ -4888,7 +4846,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4991,21 +4949,51 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm", + "windows_aarch64_gnullvm 0.42.0", "windows_aarch64_msvc 0.42.0", "windows_i686_gnu 0.42.0", "windows_i686_msvc 0.42.0", "windows_x86_64_gnu 0.42.0", - "windows_x86_64_gnullvm", + "windows_x86_64_gnullvm 0.42.0", "windows_x86_64_msvc 0.42.0", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" @@ -5024,6 +5012,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + [[package]] name = "windows_i686_gnu" version = "0.36.1" @@ -5042,6 +5036,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + [[package]] name = "windows_i686_msvc" version = "0.36.1" @@ -5060,6 +5060,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" @@ -5078,12 +5084,24 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" @@ -5102,6 +5120,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + [[package]] name = "winreg" version = "0.10.1" diff --git a/components/chainhook-event-observer/Cargo.toml b/components/chainhook-event-observer/Cargo.toml index 2764fffbf..6c58a7dd3 100644 --- a/components/chainhook-event-observer/Cargo.toml +++ b/components/chainhook-event-observer/Cargo.toml @@ -21,7 +21,7 @@ hiro-system-kit = "0.1.0" # clarity-repl = { version = "1", path = "../../../clarinet/components/clarity-repl" } # hiro-system-kit = { version = "0.1.0", path = "../../../clarinet/components/hiro-system-kit" } chainhook-types = { version = "1.0.3", path = "../chainhook-types-rs" } -rocket = { version = "=0.5.0-rc.2", features = ["json"] } +rocket = { version = "=0.5.0-rc.3", features = ["json"] } bitcoincore-rpc = "0.16.0" bitcoincore-rpc-json = "0.16.0" base64 = "0.13.0" @@ -37,7 +37,7 @@ clap_generate = { version = "3.0.3", optional = true } toml = { version = "0.5.6", features = ["preserve_order"], optional = true } ctrlc = { version = "3.2.2", optional = true } schemars = { version = "0.8.10" } -rocket_okapi = "0.8.0-rc.1" +rocket_okapi = "0.8.0-rc.3" crossbeam-channel = "0.5.6" chrono = { version = "0.4.19", optional = true } anyhow = { version = "1.0.56", features = ["backtrace"], optional = true } From 4fe71f2622440d4c187e022631d1fb87e426596a Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Thu, 1 Jun 2023 13:14:18 -0400 Subject: [PATCH 09/12] fix: remove support for p2wsh inscription reveal support --- .../chainhook-event-observer/src/hord/mod.rs | 111 +++++++++--------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/components/chainhook-event-observer/src/hord/mod.rs b/components/chainhook-event-observer/src/hord/mod.rs index 249a857db..8b7204d1f 100644 --- a/components/chainhook-event-observer/src/hord/mod.rs +++ b/components/chainhook-event-observer/src/hord/mod.rs @@ -4,6 +4,7 @@ pub mod ord; use bitcoincore_rpc::bitcoin::hashes::hex::FromHex; use bitcoincore_rpc::bitcoin::{Address, Network, Script}; +use bitcoincore_rpc_json::bitcoin::Witness; use chainhook_types::{ BitcoinBlockData, OrdinalInscriptionRevealData, OrdinalInscriptionTransferData, OrdinalOperation, TransactionIdentifier, @@ -47,69 +48,73 @@ use self::ord::inscription_id::InscriptionId; pub fn parse_ordinal_operations( tx: &BitcoinTransactionFullBreakdown, - _block_height: u64, - _ctx: &Context, + block_height: u64, + ctx: &Context, ) -> Vec { // This should eventually become a loop once/if there is settlement on https://github.com/casey/ord/issues/2000. let mut operations = vec![]; for (input_index, input) in tx.vin.iter().enumerate() { - if let Some(ref witnesses) = input.txinwitness { - for bytes in witnesses.iter() { - let script = Script::from(bytes.to_vec()); - let parser = InscriptionParser { - instructions: script.instructions().peekable(), - }; - - let inscription = match parser.parse_script() { - Ok(inscription) => inscription, - Err(_) => continue, - }; + if let Some(ref witness_data) = input.txinwitness { + let witness = Witness::from_vec(witness_data.clone()); + let inscription = match InscriptionParser::parse(&witness) { + Ok(inscription) => inscription, + Err(e) => { + ctx.try_log(|logger| { + slog::warn!( + logger, + "Inscription parsing error at block {}: #{:?}", + block_height, + e + ) + }); + continue; + } + }; - let inscription_id = InscriptionId { - txid: tx.txid.clone(), - index: input_index as u32, - }; + let inscription_id = InscriptionId { + txid: tx.txid.clone(), + index: input_index as u32, + }; - let inscription_output_value = tx - .vout - .get(0) - .and_then(|o| Some(o.value.to_sat())) - .unwrap_or(0); + let inscription_output_value = tx + .vout + .get(0) + .and_then(|o| Some(o.value.to_sat())) + .unwrap_or(0); - let no_content_bytes = vec![]; - let inscription_content_bytes = inscription.body().unwrap_or(&no_content_bytes); + let no_content_bytes = vec![]; + let inscription_content_bytes = inscription.body().unwrap_or(&no_content_bytes); - let inscriber_address = if let Ok(authors) = Address::from_script( - &tx.vout[0].script_pub_key.script().unwrap(), - bitcoincore_rpc::bitcoin::Network::Bitcoin, - ) { - Some(authors.to_string()) - } else { - None - }; + let inscriber_address = if let Ok(authors) = Address::from_script( + &tx.vout[0].script_pub_key.script().unwrap(), + bitcoincore_rpc::bitcoin::Network::Bitcoin, + ) { + Some(authors.to_string()) + } else { + None + }; - let payload = OrdinalInscriptionRevealData { - content_type: inscription.content_type().unwrap_or("unknown").to_string(), - content_bytes: format!("0x{}", hex::encode(&inscription_content_bytes)), - content_length: inscription_content_bytes.len(), - inscription_id: inscription_id.to_string(), - inscriber_address, - inscription_output_value, - inscription_fee: 0, - inscription_input_index: input_index, - inscription_number: 0, - ordinal_number: 0, - ordinal_block_height: 0, - ordinal_offset: 0, - transfers_pre_inscription: 0, - satpoint_post_inscription: format!("{}:0:0", tx.txid.clone()), - }; + let payload = OrdinalInscriptionRevealData { + content_type: inscription.content_type().unwrap_or("unknown").to_string(), + content_bytes: format!("0x{}", hex::encode(&inscription_content_bytes)), + content_length: inscription_content_bytes.len(), + inscription_id: inscription_id.to_string(), + inscriber_address, + inscription_output_value, + inscription_fee: 0, + inscription_input_index: input_index, + inscription_number: 0, + ordinal_number: 0, + ordinal_block_height: 0, + ordinal_offset: 0, + transfers_pre_inscription: 0, + satpoint_post_inscription: format!("{}:0:0", tx.txid.clone()), + }; - if input_index == 0 { - operations.push(OrdinalOperation::InscriptionRevealed(payload)); - } else { - operations.push(OrdinalOperation::CursedInscriptionRevealed(payload)); - } + if input_index == 0 { + operations.push(OrdinalOperation::InscriptionRevealed(payload)); + } else { + operations.push(OrdinalOperation::CursedInscriptionRevealed(payload)); } } } From dcb805485f341bf40a9a39dc85b935ddf1fec029 Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Thu, 1 Jun 2023 17:34:48 -0400 Subject: [PATCH 10/12] feat: improving curse approach --- .../src/hord/inscription.rs | 18 ++++-- .../chainhook-event-observer/src/hord/mod.rs | 56 ++++++++++++------- components/chainhook-types-rs/src/rosetta.rs | 8 +++ 3 files changed, 57 insertions(+), 25 deletions(-) diff --git a/components/chainhook-event-observer/src/hord/inscription.rs b/components/chainhook-event-observer/src/hord/inscription.rs index 67ba8bbe9..eaef1a2fe 100644 --- a/components/chainhook-event-observer/src/hord/inscription.rs +++ b/components/chainhook-event-observer/src/hord/inscription.rs @@ -2,6 +2,7 @@ use std::collections::BTreeMap; use std::str::FromStr; use bitcoincore_rpc::bitcoin::Transaction; +use chainhook_types::OrdinalInscriptionCurseType; use { bitcoincore_rpc::bitcoin::{ blockdata::{ @@ -21,8 +22,9 @@ const CONTENT_TYPE_TAG: &[u8] = &[1]; #[derive(Debug, PartialEq, Clone)] pub struct Inscription { - body: Option>, - content_type: Option>, + pub body: Option>, + pub content_type: Option>, + pub curse: Option, } impl Inscription { @@ -143,12 +145,20 @@ impl<'a> InscriptionParser<'a> { for tag in fields.keys() { if let Some(lsb) = tag.first() { if lsb % 2 == 0 { - return Err(InscriptionError::UnrecognizedEvenField); + return Ok(Some(Inscription { + body, + content_type, + curse: Some(OrdinalInscriptionCurseType::Tag(*lsb)), + })); } } } - return Ok(Some(Inscription { body, content_type })); + return Ok(Some(Inscription { + body, + content_type, + curse: None, + })); } Ok(None) diff --git a/components/chainhook-event-observer/src/hord/mod.rs b/components/chainhook-event-observer/src/hord/mod.rs index 8b7204d1f..bd5a2cccc 100644 --- a/components/chainhook-event-observer/src/hord/mod.rs +++ b/components/chainhook-event-observer/src/hord/mod.rs @@ -6,8 +6,8 @@ use bitcoincore_rpc::bitcoin::hashes::hex::FromHex; use bitcoincore_rpc::bitcoin::{Address, Network, Script}; use bitcoincore_rpc_json::bitcoin::Witness; use chainhook_types::{ - BitcoinBlockData, OrdinalInscriptionRevealData, OrdinalInscriptionTransferData, - OrdinalOperation, TransactionIdentifier, + BitcoinBlockData, OrdinalInscriptionCurseType, OrdinalInscriptionRevealData, + OrdinalInscriptionTransferData, OrdinalOperation, TransactionIdentifier, }; use dashmap::DashMap; use fxhash::{FxBuildHasher, FxHasher}; @@ -56,18 +56,28 @@ pub fn parse_ordinal_operations( for (input_index, input) in tx.vin.iter().enumerate() { if let Some(ref witness_data) = input.txinwitness { let witness = Witness::from_vec(witness_data.clone()); - let inscription = match InscriptionParser::parse(&witness) { + let mut inscription = match InscriptionParser::parse(&witness) { Ok(inscription) => inscription, - Err(e) => { - ctx.try_log(|logger| { - slog::warn!( - logger, - "Inscription parsing error at block {}: #{:?}", - block_height, - e - ) - }); - continue; + Err(_e) => { + let mut cursed_inscription = None; + for bytes in witness_data.iter() { + let script = Script::from(bytes.to_vec()); + let parser = InscriptionParser { + instructions: script.instructions().peekable(), + }; + + let mut inscription = match parser.parse_script() { + Ok(inscription) => inscription, + Err(_) => continue, + }; + inscription.curse = Some(OrdinalInscriptionCurseType::P2wsh); + cursed_inscription = Some(inscription); + break; + } + match cursed_inscription { + Some(inscription) => inscription, + None => continue, + } } }; @@ -82,9 +92,6 @@ pub fn parse_ordinal_operations( .and_then(|o| Some(o.value.to_sat())) .unwrap_or(0); - let no_content_bytes = vec![]; - let inscription_content_bytes = inscription.body().unwrap_or(&no_content_bytes); - let inscriber_address = if let Ok(authors) = Address::from_script( &tx.vout[0].script_pub_key.script().unwrap(), bitcoincore_rpc::bitcoin::Network::Bitcoin, @@ -94,6 +101,13 @@ pub fn parse_ordinal_operations( None }; + if input_index > 0 { + inscription.curse = Some(OrdinalInscriptionCurseType::Batch); + } + + let no_content_bytes = vec![]; + let inscription_content_bytes = inscription.body().take().unwrap_or(&no_content_bytes); + let payload = OrdinalInscriptionRevealData { content_type: inscription.content_type().unwrap_or("unknown").to_string(), content_bytes: format!("0x{}", hex::encode(&inscription_content_bytes)), @@ -109,13 +123,13 @@ pub fn parse_ordinal_operations( ordinal_offset: 0, transfers_pre_inscription: 0, satpoint_post_inscription: format!("{}:0:0", tx.txid.clone()), + curse_type: inscription.curse.take(), }; - if input_index == 0 { - operations.push(OrdinalOperation::InscriptionRevealed(payload)); - } else { - operations.push(OrdinalOperation::CursedInscriptionRevealed(payload)); - } + operations.push(match &payload.curse_type { + Some(_) => OrdinalOperation::CursedInscriptionRevealed(payload), + None => OrdinalOperation::InscriptionRevealed(payload), + }); } } operations diff --git a/components/chainhook-types-rs/src/rosetta.rs b/components/chainhook-types-rs/src/rosetta.rs index 05a63afd9..5e7de7182 100644 --- a/components/chainhook-types-rs/src/rosetta.rs +++ b/components/chainhook-types-rs/src/rosetta.rs @@ -318,6 +318,13 @@ pub struct OrdinalInscriptionTransferData { pub post_transfer_output_value: Option, } +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +pub enum OrdinalInscriptionCurseType { + Tag(u8), + Batch, + P2wsh, +} + #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct OrdinalInscriptionRevealData { pub content_bytes: String, @@ -334,6 +341,7 @@ pub struct OrdinalInscriptionRevealData { pub ordinal_offset: u64, pub transfers_pre_inscription: u32, pub satpoint_post_inscription: String, + pub curse_type: Option, } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] From 9b987c51a98b30ca1c40f301cdcfcf87a897f47d Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Sun, 4 Jun 2023 10:40:58 -0400 Subject: [PATCH 11/12] fix: more pessimism on retries --- components/chainhook-event-observer/src/hord/db/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/chainhook-event-observer/src/hord/db/mod.rs b/components/chainhook-event-observer/src/hord/db/mod.rs index 558cda10e..dcbf0bdc5 100644 --- a/components/chainhook-event-observer/src/hord/db/mod.rs +++ b/components/chainhook-event-observer/src/hord/db/mod.rs @@ -269,7 +269,7 @@ pub fn find_lazy_block_at_block_height( Ok(Some(res)) => return Some(LazyBlock::new(res)), _ => { attempt += 1; - std::thread::sleep(std::time::Duration::from_secs(1)); + std::thread::sleep(std::time::Duration::from_secs(2)); if attempt > retry { return None; } @@ -1013,7 +1013,7 @@ pub fn retrieve_satoshi_point_using_lazy_storage( } } - let lazy_block = match find_lazy_block_at_block_height(ordinal_block_number, 3, &blocks_db) + let lazy_block = match find_lazy_block_at_block_height(ordinal_block_number, 10, &blocks_db) { Some(block) => block, None => { From 8a120040e70991cbc961b5d79bc838c99087bcdd Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Sun, 4 Jun 2023 11:43:45 -0400 Subject: [PATCH 12/12] fix: off by one issue on sats overflow --- .../chainhook-event-observer/src/hord/mod.rs | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/components/chainhook-event-observer/src/hord/mod.rs b/components/chainhook-event-observer/src/hord/mod.rs index bd5a2cccc..6e59b034d 100644 --- a/components/chainhook-event-observer/src/hord/mod.rs +++ b/components/chainhook-event-observer/src/hord/mod.rs @@ -481,28 +481,28 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( match storage { Storage::Sqlite(rw_hord_db_conn) => { - if traversal.ordinal_number > 0 { - if let Some(_entry) = find_inscription_with_ordinal_number( - &traversal.ordinal_number, - &inscription_db_conn, - &ctx, - ) { - ctx.try_log(|logger| { - slog::warn!( - logger, - "Transaction {} in block {} is overriding an existing inscription {}", - new_tx.transaction_identifier.hash, - block.block_identifier.index, - traversal.ordinal_number - ); - }); - ordinals_events_indexes_to_discard.push_front(ordinal_event_index); - continue; - } - } else { + if traversal.ordinal_number == 0 { // If the satoshi inscribed correspond to a sat overflow, we will store the inscription - // but exclude it from the block data + // and assign an inscription number after the other inscriptions, to mimick the + // bug in ord. sats_overflow.push(inscription.clone()); + continue; + } + + if let Some(_entry) = find_inscription_with_ordinal_number( + &traversal.ordinal_number, + &inscription_db_conn, + &ctx, + ) { + ctx.try_log(|logger| { + slog::warn!( + logger, + "Transaction {} in block {} is overriding an existing inscription {}", + new_tx.transaction_identifier.hash, + block.block_identifier.index, + traversal.ordinal_number + ); + }); ordinals_events_indexes_to_discard.push_front(ordinal_event_index); continue; } @@ -558,7 +558,6 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( for inscription in sats_overflow.iter_mut() { match storage { Storage::Sqlite(rw_hord_db_conn) => { - latest_inscription_number += 1; inscription.inscription_number = latest_inscription_number; ctx.try_log(|logger| { slog::info!( @@ -577,6 +576,7 @@ pub fn update_storage_and_augment_bitcoin_block_with_inscription_reveal_data( &rw_hord_db_conn, &ctx, ); + latest_inscription_number += 1; storage_updated = true; } _ => {}