mirror of
https://github.com/alexgo-io/bitcoin-indexer.git
synced 2026-04-30 04:35:04 +08:00
fix: pointer ignored
This commit is contained in:
@@ -164,6 +164,8 @@ struct ScanTransactionCommand {
|
||||
pub block_height: u64,
|
||||
/// Inscription Id
|
||||
pub transaction_id: String,
|
||||
/// Input index
|
||||
pub input_index: usize,
|
||||
/// Target Regtest network
|
||||
#[clap(
|
||||
long = "regtest",
|
||||
@@ -675,10 +677,11 @@ async fn handle_command(opts: Opts, ctx: &Context) -> Result<(), String> {
|
||||
.await?;
|
||||
let transaction_identifier = TransactionIdentifier::new(&cmd.transaction_id);
|
||||
let cache = new_traversals_lazy_cache(100);
|
||||
let (res, mut back_trace) = compute_satoshi_number(
|
||||
let (res, _, mut back_trace) = compute_satoshi_number(
|
||||
&config.get_ordhook_config().db_path,
|
||||
&block.block_identifier,
|
||||
&transaction_identifier,
|
||||
cmd.input_index,
|
||||
0,
|
||||
&Arc::new(cache),
|
||||
config.resources.ulimit,
|
||||
@@ -687,8 +690,8 @@ async fn handle_command(opts: Opts, ctx: &Context) -> Result<(), String> {
|
||||
ctx,
|
||||
)?;
|
||||
back_trace.reverse();
|
||||
for (block_height, tx) in back_trace.iter() {
|
||||
println!("{}\t{}", block_height, hex::encode(tx));
|
||||
for (block_height, tx, index) in back_trace.iter() {
|
||||
println!("{}\t{}:{}", block_height, hex::encode(tx), index);
|
||||
}
|
||||
println!("{:?}", res);
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ pub fn process_block(
|
||||
block: &mut BitcoinBlockData,
|
||||
next_blocks: &Vec<BitcoinBlockData>,
|
||||
sequence_cursor: &mut SequenceCursor,
|
||||
cache_l1: &mut BTreeMap<(TransactionIdentifier, usize), TraversalResult>,
|
||||
cache_l1: &mut BTreeMap<(TransactionIdentifier, usize, u64), TraversalResult>,
|
||||
cache_l2: &Arc<DashMap<(u32, [u8; 8]), TransactionBytesCursor, BuildHasherDefault<FxHasher>>>,
|
||||
inscriptions_db_tx: &Transaction,
|
||||
ordhook_config: &OrdhookConfig,
|
||||
|
||||
@@ -8,8 +8,8 @@ use chainhook_sdk::{
|
||||
bitcoincore_rpc_json::bitcoin::{Address, Network, ScriptBuf},
|
||||
types::{
|
||||
BitcoinBlockData, BitcoinNetwork, BitcoinTransactionData, BlockIdentifier,
|
||||
OrdinalInscriptionCurseType, OrdinalInscriptionNumber, OrdinalOperation,
|
||||
TransactionIdentifier,
|
||||
OrdinalInscriptionCurseType, OrdinalInscriptionNumber,
|
||||
OrdinalInscriptionTransferDestination, OrdinalOperation, TransactionIdentifier,
|
||||
},
|
||||
utils::Context,
|
||||
};
|
||||
@@ -23,8 +23,8 @@ use crate::{
|
||||
db::{
|
||||
find_blessed_inscription_with_ordinal_number, find_nth_classic_neg_number_at_block_height,
|
||||
find_nth_classic_pos_number_at_block_height, find_nth_jubilee_number_at_block_height,
|
||||
format_inscription_id, format_satpoint_to_watch, update_inscriptions_with_block,
|
||||
update_sequence_metadata_with_block, TransactionBytesCursor, TraversalResult,
|
||||
format_inscription_id, update_inscriptions_with_block, update_sequence_metadata_with_block,
|
||||
TransactionBytesCursor, TraversalResult,
|
||||
},
|
||||
ord::height::Height,
|
||||
};
|
||||
@@ -37,7 +37,9 @@ use crate::db::find_all_inscriptions_in_block;
|
||||
|
||||
use super::{
|
||||
inscription_parsing::get_inscriptions_revealed_in_block,
|
||||
inscription_tracking::augment_transaction_with_ordinals_transfers_data,
|
||||
inscription_tracking::{
|
||||
augment_transaction_with_ordinals_transfers_data, compute_satpoint_post_transfer,
|
||||
},
|
||||
satoshi_numbering::compute_satoshi_number,
|
||||
};
|
||||
|
||||
@@ -67,7 +69,7 @@ use super::{
|
||||
pub fn parallelize_inscription_data_computations(
|
||||
block: &BitcoinBlockData,
|
||||
next_blocks: &Vec<BitcoinBlockData>,
|
||||
cache_l1: &mut BTreeMap<(TransactionIdentifier, usize), TraversalResult>,
|
||||
cache_l1: &mut BTreeMap<(TransactionIdentifier, usize, u64), TraversalResult>,
|
||||
cache_l2: &Arc<DashMap<(u32, [u8; 8]), TransactionBytesCursor, BuildHasherDefault<FxHasher>>>,
|
||||
inscriptions_db_tx: &Transaction,
|
||||
ordhook_config: &OrdhookConfig,
|
||||
@@ -118,20 +120,27 @@ pub fn parallelize_inscription_data_computations(
|
||||
|
||||
let handle = hiro_system_kit::thread_named("Worker")
|
||||
.spawn(move || {
|
||||
while let Ok(Some((transaction_id, block_identifier, input_index, prioritary))) =
|
||||
rx.recv()
|
||||
while let Ok(Some((
|
||||
transaction_id,
|
||||
block_identifier,
|
||||
input_index,
|
||||
inscription_pointer,
|
||||
prioritary,
|
||||
))) = rx.recv()
|
||||
{
|
||||
let traversal: Result<(TraversalResult, _), String> = compute_satoshi_number(
|
||||
&moved_ordhook_db_path,
|
||||
&block_identifier,
|
||||
&transaction_id,
|
||||
input_index,
|
||||
&local_cache,
|
||||
ulimit,
|
||||
memory_available,
|
||||
false,
|
||||
&moved_ctx,
|
||||
);
|
||||
let traversal: Result<(TraversalResult, u64, _), String> =
|
||||
compute_satoshi_number(
|
||||
&moved_ordhook_db_path,
|
||||
&block_identifier,
|
||||
&transaction_id,
|
||||
input_index,
|
||||
inscription_pointer,
|
||||
&local_cache,
|
||||
ulimit,
|
||||
memory_available,
|
||||
false,
|
||||
&moved_ctx,
|
||||
);
|
||||
let _ = moved_traversal_tx.send((traversal, prioritary, thread_index));
|
||||
}
|
||||
})
|
||||
@@ -144,8 +153,11 @@ pub fn parallelize_inscription_data_computations(
|
||||
let mut round_robin_thread_index = 0;
|
||||
for key in l1_cache_hits.iter() {
|
||||
if let Some(entry) = cache_l1.get(key) {
|
||||
let _ =
|
||||
traversal_tx.send((Ok((entry.clone(), vec![])), true, round_robin_thread_index));
|
||||
let _ = traversal_tx.send((
|
||||
Ok((entry.clone(), key.2, vec![])),
|
||||
true,
|
||||
round_robin_thread_index,
|
||||
));
|
||||
round_robin_thread_index = (round_robin_thread_index + 1) % thread_pool_capacity;
|
||||
}
|
||||
}
|
||||
@@ -173,11 +185,12 @@ pub fn parallelize_inscription_data_computations(
|
||||
let mut priority_queue = VecDeque::new();
|
||||
let mut warmup_queue = VecDeque::new();
|
||||
|
||||
for (transaction_id, input_index) in transactions_ids.into_iter() {
|
||||
for (transaction_id, input_index, inscription_pointer) in transactions_ids.into_iter() {
|
||||
priority_queue.push_back((
|
||||
transaction_id,
|
||||
block.block_identifier.clone(),
|
||||
input_index,
|
||||
inscription_pointer,
|
||||
true,
|
||||
));
|
||||
}
|
||||
@@ -197,13 +210,14 @@ pub fn parallelize_inscription_data_computations(
|
||||
traversals_received += 1;
|
||||
}
|
||||
match traversal_result {
|
||||
Ok((traversal, _)) => {
|
||||
Ok((traversal, inscription_pointer, _)) => {
|
||||
inner_ctx.try_log(|logger| {
|
||||
info!(
|
||||
logger,
|
||||
"Completed ordinal number retrieval for Satpoint {}:{}:0 (block: #{}:{}, transfers: {}, progress: {traversals_received}/{expected_traversals}, priority queue: {prioritary}, thread: {thread_index})",
|
||||
"Completed ordinal number retrieval for Satpoint {}:{}:{} (block: #{}:{}, transfers: {}, progress: {traversals_received}/{expected_traversals}, priority queue: {prioritary}, thread: {thread_index})",
|
||||
traversal.transaction_identifier_inscription.hash,
|
||||
traversal.inscription_input_index,
|
||||
inscription_pointer,
|
||||
traversal.get_ordinal_coinbase_height(),
|
||||
traversal.get_ordinal_coinbase_offset(),
|
||||
traversal.transfers
|
||||
@@ -213,6 +227,7 @@ pub fn parallelize_inscription_data_computations(
|
||||
(
|
||||
traversal.transaction_identifier_inscription.clone(),
|
||||
traversal.inscription_input_index,
|
||||
inscription_pointer,
|
||||
),
|
||||
traversal,
|
||||
);
|
||||
@@ -248,11 +263,14 @@ pub fn parallelize_inscription_data_computations(
|
||||
});
|
||||
|
||||
transactions_ids.shuffle(&mut rng);
|
||||
for (transaction_id, input_index) in transactions_ids.into_iter() {
|
||||
for (transaction_id, input_index, inscription_pointer) in
|
||||
transactions_ids.into_iter()
|
||||
{
|
||||
warmup_queue.push_back((
|
||||
transaction_id,
|
||||
next_block.block_identifier.clone(),
|
||||
input_index,
|
||||
inscription_pointer,
|
||||
false,
|
||||
));
|
||||
}
|
||||
@@ -272,13 +290,14 @@ pub fn parallelize_inscription_data_computations(
|
||||
for tx in tx_thread_pool.iter() {
|
||||
// Empty the queue
|
||||
if let Ok((traversal_result, _prioritary, thread_index)) = traversal_rx.try_recv() {
|
||||
if let Ok((traversal, _)) = traversal_result {
|
||||
if let Ok((traversal, inscription_pointer, _)) = traversal_result {
|
||||
inner_ctx.try_log(|logger| {
|
||||
info!(
|
||||
logger,
|
||||
"Completed ordinal number retrieval for Satpoint {}:{}:0 (block: #{}:{}, transfers: {}, pre-retrieval, thread: {thread_index})",
|
||||
"Completed ordinal number retrieval for Satpoint {}:{}:{} (block: #{}:{}, transfers: {}, pre-retrieval, thread: {thread_index})",
|
||||
traversal.transaction_identifier_inscription.hash,
|
||||
traversal.inscription_input_index,
|
||||
inscription_pointer,
|
||||
traversal.get_ordinal_coinbase_height(),
|
||||
traversal.get_ordinal_coinbase_offset(),
|
||||
traversal.transfers
|
||||
@@ -288,6 +307,7 @@ pub fn parallelize_inscription_data_computations(
|
||||
(
|
||||
traversal.transaction_identifier_inscription.clone(),
|
||||
traversal.inscription_input_index,
|
||||
inscription_pointer,
|
||||
),
|
||||
traversal,
|
||||
);
|
||||
@@ -332,14 +352,14 @@ pub fn parallelize_inscription_data_computations(
|
||||
///
|
||||
fn get_transactions_to_process(
|
||||
block: &BitcoinBlockData,
|
||||
cache_l1: &mut BTreeMap<(TransactionIdentifier, usize), TraversalResult>,
|
||||
cache_l1: &mut BTreeMap<(TransactionIdentifier, usize, u64), TraversalResult>,
|
||||
inscriptions_db_tx: &Transaction,
|
||||
ctx: &Context,
|
||||
) -> (
|
||||
Vec<(TransactionIdentifier, usize)>,
|
||||
Vec<(TransactionIdentifier, usize)>,
|
||||
Vec<(TransactionIdentifier, usize, u64)>,
|
||||
Vec<(TransactionIdentifier, usize, u64)>,
|
||||
) {
|
||||
let mut transactions_ids: Vec<(TransactionIdentifier, usize)> = vec![];
|
||||
let mut transactions_ids: Vec<(TransactionIdentifier, usize, u64)> = vec![];
|
||||
let mut l1_cache_hits = vec![];
|
||||
|
||||
let known_transactions =
|
||||
@@ -357,6 +377,7 @@ fn get_transactions_to_process(
|
||||
let key = (
|
||||
tx.transaction_identifier.clone(),
|
||||
inscription_data.inscription_input_index,
|
||||
inscription_data.inscription_pointer,
|
||||
);
|
||||
if cache_l1.contains_key(&key) {
|
||||
l1_cache_hits.push(key);
|
||||
@@ -371,6 +392,7 @@ fn get_transactions_to_process(
|
||||
transactions_ids.push((
|
||||
tx.transaction_identifier.clone(),
|
||||
inscription_data.inscription_input_index,
|
||||
inscription_data.inscription_pointer,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -520,7 +542,7 @@ impl<'a> SequenceCursor<'a> {
|
||||
pub fn augment_block_with_ordinals_inscriptions_data_and_write_to_db_tx(
|
||||
block: &mut BitcoinBlockData,
|
||||
sequence_cursor: &mut SequenceCursor,
|
||||
inscriptions_data: &mut BTreeMap<(TransactionIdentifier, usize), TraversalResult>,
|
||||
inscriptions_data: &mut BTreeMap<(TransactionIdentifier, usize, u64), TraversalResult>,
|
||||
inscriptions_db_tx: &Transaction,
|
||||
ctx: &Context,
|
||||
) -> bool {
|
||||
@@ -563,7 +585,7 @@ pub fn augment_block_with_ordinals_inscriptions_data_and_write_to_db_tx(
|
||||
pub fn augment_block_with_ordinals_inscriptions_data(
|
||||
block: &mut BitcoinBlockData,
|
||||
sequence_cursor: &mut SequenceCursor,
|
||||
inscriptions_data: &mut BTreeMap<(TransactionIdentifier, usize), TraversalResult>,
|
||||
inscriptions_data: &mut BTreeMap<(TransactionIdentifier, usize, u64), TraversalResult>,
|
||||
reinscriptions_data: &mut HashMap<u64, String>,
|
||||
ctx: &Context,
|
||||
) -> bool {
|
||||
@@ -577,6 +599,9 @@ pub fn augment_block_with_ordinals_inscriptions_data(
|
||||
BitcoinNetwork::Testnet => Network::Testnet,
|
||||
BitcoinNetwork::Signet => Network::Signet,
|
||||
};
|
||||
let coinbase_subsidy = Height(block.block_identifier.index).subsidy();
|
||||
let coinbase_txid = &block.transactions[0].transaction_identifier.clone();
|
||||
let mut cumulated_fees = 0u64;
|
||||
|
||||
for (tx_index, tx) in block.transactions.iter_mut().enumerate() {
|
||||
any_event |= augment_transaction_with_ordinals_inscriptions_data(
|
||||
@@ -586,6 +611,9 @@ pub fn augment_block_with_ordinals_inscriptions_data(
|
||||
sequence_cursor,
|
||||
&network,
|
||||
inscriptions_data,
|
||||
coinbase_txid,
|
||||
coinbase_subsidy,
|
||||
&mut cumulated_fees,
|
||||
&mut sats_overflows,
|
||||
reinscriptions_data,
|
||||
ctx,
|
||||
@@ -637,14 +665,19 @@ fn augment_transaction_with_ordinals_inscriptions_data(
|
||||
block_identifier: &BlockIdentifier,
|
||||
sequence_cursor: &mut SequenceCursor,
|
||||
network: &Network,
|
||||
inscriptions_data: &mut BTreeMap<(TransactionIdentifier, usize), TraversalResult>,
|
||||
inscriptions_data: &mut BTreeMap<(TransactionIdentifier, usize, u64), TraversalResult>,
|
||||
coinbase_txid: &TransactionIdentifier,
|
||||
coinbase_subsidy: u64,
|
||||
cumulated_fees: &mut u64,
|
||||
sats_overflows: &mut VecDeque<(usize, usize)>,
|
||||
reinscriptions_data: &mut HashMap<u64, String>,
|
||||
ctx: &Context,
|
||||
) -> bool {
|
||||
let any_event = tx.metadata.ordinal_operations.is_empty() == false;
|
||||
let mut mutated_operations = vec![];
|
||||
mutated_operations.append(&mut tx.metadata.ordinal_operations);
|
||||
let mut inscription_subindex = 0;
|
||||
for (op_index, op) in tx.metadata.ordinal_operations.iter_mut().enumerate() {
|
||||
for (op_index, op) in mutated_operations.iter_mut().enumerate() {
|
||||
let (mut is_cursed, inscription) = match op {
|
||||
OrdinalOperation::InscriptionRevealed(inscription) => {
|
||||
(inscription.curse_type.as_ref().is_some(), inscription)
|
||||
@@ -654,9 +687,11 @@ fn augment_transaction_with_ordinals_inscriptions_data(
|
||||
|
||||
let transaction_identifier = tx.transaction_identifier.clone();
|
||||
let inscription_id = format_inscription_id(&transaction_identifier, inscription_subindex);
|
||||
let traversal = match inscriptions_data
|
||||
.get(&(transaction_identifier, inscription.inscription_input_index))
|
||||
{
|
||||
let traversal = match inscriptions_data.get(&(
|
||||
transaction_identifier,
|
||||
inscription.inscription_input_index,
|
||||
inscription.inscription_pointer,
|
||||
)) {
|
||||
Some(traversal) => traversal,
|
||||
None => {
|
||||
let err_msg = format!(
|
||||
@@ -698,7 +733,6 @@ fn augment_transaction_with_ordinals_inscriptions_data(
|
||||
|
||||
inscription.inscription_id = inscription_id;
|
||||
inscription.inscription_number = inscription_number;
|
||||
let outputs = &tx.metadata.outputs;
|
||||
inscription.ordinal_offset = traversal.get_ordinal_coinbase_offset();
|
||||
inscription.ordinal_block_height = traversal.get_ordinal_coinbase_height();
|
||||
inscription.ordinal_number = traversal.ordinal_number;
|
||||
@@ -709,33 +743,29 @@ fn augment_transaction_with_ordinals_inscriptions_data(
|
||||
Some(curse_type) => Some(curse_type),
|
||||
None => inscription.curse_type.take(),
|
||||
};
|
||||
inscription.satpoint_post_inscription = format_satpoint_to_watch(
|
||||
&traversal.transfer_data.transaction_identifier_location,
|
||||
traversal.transfer_data.output_index,
|
||||
traversal.transfer_data.inscription_offset_intra_output,
|
||||
|
||||
let (destination, satpoint_post_transfer, output_value) = compute_satpoint_post_transfer(
|
||||
&&*tx,
|
||||
traversal.inscription_input_index,
|
||||
inscription.inscription_pointer,
|
||||
network,
|
||||
coinbase_txid,
|
||||
coinbase_subsidy,
|
||||
cumulated_fees,
|
||||
ctx,
|
||||
);
|
||||
if let Some(output) = outputs.get(traversal.transfer_data.output_index) {
|
||||
inscription.inscription_output_value = output.value;
|
||||
inscription.inscriber_address = {
|
||||
let script_pub_key = output.get_script_pubkey_hex();
|
||||
match ScriptBuf::from_hex(&script_pub_key) {
|
||||
Ok(script) => match Address::from_script(&script, network.clone()) {
|
||||
Ok(a) => Some(a.to_string()),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
} else {
|
||||
ctx.try_log(|logger| {
|
||||
warn!(
|
||||
logger,
|
||||
"Database corrupted, skipping cursed inscription => {:?} / {:?}",
|
||||
traversal,
|
||||
outputs
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Compute satpoint_post_inscription
|
||||
inscription.satpoint_post_inscription = satpoint_post_transfer;
|
||||
|
||||
match destination {
|
||||
OrdinalInscriptionTransferDestination::SpentInFees => {}
|
||||
OrdinalInscriptionTransferDestination::Burnt(_) => {}
|
||||
OrdinalInscriptionTransferDestination::Transferred(address) => {
|
||||
inscription.inscription_output_value = output_value.unwrap_or(0);
|
||||
inscription.inscriber_address = Some(address);
|
||||
}
|
||||
};
|
||||
|
||||
if traversal.ordinal_number == 0 {
|
||||
// If the satoshi inscribed correspond to a sat overflow, we will store the inscription
|
||||
@@ -770,6 +800,10 @@ fn augment_transaction_with_ordinals_inscriptions_data(
|
||||
}
|
||||
inscription_subindex += 1;
|
||||
}
|
||||
tx.metadata
|
||||
.ordinal_operations
|
||||
.append(&mut mutated_operations);
|
||||
|
||||
any_event
|
||||
}
|
||||
|
||||
@@ -779,12 +813,17 @@ fn consolidate_transaction_with_pre_computed_inscription_data(
|
||||
tx: &mut BitcoinTransactionData,
|
||||
tx_index: usize,
|
||||
coinbase_txid: &TransactionIdentifier,
|
||||
coinbase_subsidy: u64,
|
||||
cumulated_fees: &mut u64,
|
||||
network: &Network,
|
||||
inscriptions_data: &mut BTreeMap<String, TraversalResult>,
|
||||
_ctx: &Context,
|
||||
ctx: &Context,
|
||||
) {
|
||||
let mut subindex = 0;
|
||||
for operation in tx.metadata.ordinal_operations.iter_mut() {
|
||||
let mut mutated_operations = vec![];
|
||||
mutated_operations.append(&mut tx.metadata.ordinal_operations);
|
||||
|
||||
for operation in mutated_operations.iter_mut() {
|
||||
let inscription = match operation {
|
||||
OrdinalOperation::InscriptionRevealed(ref mut inscription) => inscription,
|
||||
OrdinalOperation::InscriptionTransferred(_) => continue,
|
||||
@@ -805,42 +844,37 @@ fn consolidate_transaction_with_pre_computed_inscription_data(
|
||||
inscription.transfers_pre_inscription = traversal.transfers;
|
||||
inscription.inscription_fee = tx.metadata.fee;
|
||||
inscription.tx_index = tx_index;
|
||||
inscription.satpoint_post_inscription = format_satpoint_to_watch(
|
||||
&traversal.transfer_data.transaction_identifier_location,
|
||||
traversal.transfer_data.output_index,
|
||||
traversal.transfer_data.inscription_offset_intra_output,
|
||||
|
||||
// Compute satpoint_post_inscription
|
||||
let (destination, satpoint_post_transfer, output_value) = compute_satpoint_post_transfer(
|
||||
tx,
|
||||
traversal.inscription_input_index,
|
||||
inscription.inscription_pointer,
|
||||
network,
|
||||
coinbase_txid,
|
||||
coinbase_subsidy,
|
||||
cumulated_fees,
|
||||
ctx,
|
||||
);
|
||||
|
||||
inscription.satpoint_post_inscription = satpoint_post_transfer;
|
||||
|
||||
if inscription.inscription_number.classic < 0 {
|
||||
inscription.curse_type = Some(OrdinalInscriptionCurseType::Generic);
|
||||
}
|
||||
|
||||
if traversal
|
||||
.transfer_data
|
||||
.transaction_identifier_location
|
||||
.eq(coinbase_txid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(output) = tx
|
||||
.metadata
|
||||
.outputs
|
||||
.get(traversal.transfer_data.output_index)
|
||||
{
|
||||
inscription.inscription_output_value = output.value;
|
||||
inscription.inscriber_address = {
|
||||
let script_pub_key = output.get_script_pubkey_hex();
|
||||
match ScriptBuf::from_hex(&script_pub_key) {
|
||||
Ok(script) => match Address::from_script(&script, network.clone()) {
|
||||
Ok(a) => Some(a.to_string()),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
match destination {
|
||||
OrdinalInscriptionTransferDestination::SpentInFees => continue,
|
||||
OrdinalInscriptionTransferDestination::Burnt(_) => continue,
|
||||
OrdinalInscriptionTransferDestination::Transferred(address) => {
|
||||
inscription.inscription_output_value = output_value.unwrap_or(0);
|
||||
inscription.inscriber_address = Some(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
tx.metadata
|
||||
.ordinal_operations
|
||||
.append(&mut mutated_operations);
|
||||
}
|
||||
|
||||
/// Best effort to re-augment a `BitcoinBlockData` with data coming from `inscriptions` and `locations` tables.
|
||||
@@ -884,6 +918,8 @@ pub fn consolidate_block_with_pre_computed_ordinals_data(
|
||||
tx,
|
||||
tx_index,
|
||||
coinbase_txid,
|
||||
coinbase_subsidy,
|
||||
&mut cumulated_fees,
|
||||
&network,
|
||||
&mut inscriptions_data,
|
||||
ctx,
|
||||
|
||||
@@ -66,6 +66,87 @@ pub fn augment_block_with_ordinals_transfer_data(
|
||||
any_event
|
||||
}
|
||||
|
||||
pub fn compute_satpoint_post_transfer(
|
||||
tx: &BitcoinTransactionData,
|
||||
input_index: usize,
|
||||
inscription_pointer: u64,
|
||||
network: &Network,
|
||||
coinbase_txid: &TransactionIdentifier,
|
||||
coinbase_subsidy: u64,
|
||||
cumulated_fees: &mut u64,
|
||||
ctx: &Context,
|
||||
) -> (OrdinalInscriptionTransferDestination, String, Option<u64>) {
|
||||
let inputs: Vec<u64> = tx
|
||||
.metadata
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|o| o.previous_output.value)
|
||||
.collect::<_>();
|
||||
let outputs = tx.metadata.outputs.iter().map(|o| o.value).collect::<_>();
|
||||
let post_transfer_data =
|
||||
compute_next_satpoint_data(input_index, 0, &inputs, &outputs, inscription_pointer);
|
||||
|
||||
let (outpoint_post_transfer, offset_post_transfer, destination, post_transfer_output_value) =
|
||||
match post_transfer_data {
|
||||
SatPosition::Output((output_index, offset)) => {
|
||||
let outpoint = format_outpoint_to_watch(&tx.transaction_identifier, output_index);
|
||||
let script_pub_key_hex = tx.metadata.outputs[output_index].get_script_pubkey_hex();
|
||||
let updated_address = match ScriptBuf::from_hex(&script_pub_key_hex) {
|
||||
Ok(script) => match Address::from_script(&script, network.clone()) {
|
||||
Ok(address) => {
|
||||
OrdinalInscriptionTransferDestination::Transferred(address.to_string())
|
||||
}
|
||||
Err(e) => {
|
||||
ctx.try_log(|logger| {
|
||||
info!(
|
||||
logger,
|
||||
"unable to retrieve address from {script_pub_key_hex}: {}",
|
||||
e.to_string()
|
||||
)
|
||||
});
|
||||
OrdinalInscriptionTransferDestination::Burnt(script.to_string())
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
ctx.try_log(|logger| {
|
||||
info!(
|
||||
logger,
|
||||
"unable to retrieve address from {script_pub_key_hex}: {}",
|
||||
e.to_string()
|
||||
)
|
||||
});
|
||||
OrdinalInscriptionTransferDestination::Burnt(script_pub_key_hex.to_string())
|
||||
}
|
||||
};
|
||||
|
||||
(
|
||||
outpoint,
|
||||
offset,
|
||||
updated_address,
|
||||
Some(tx.metadata.outputs[output_index].value),
|
||||
)
|
||||
}
|
||||
SatPosition::Fee(offset) => {
|
||||
// Get Coinbase TX
|
||||
let total_offset = coinbase_subsidy + *cumulated_fees + offset;
|
||||
let outpoint = format_outpoint_to_watch(&coinbase_txid, 0);
|
||||
(
|
||||
outpoint,
|
||||
total_offset,
|
||||
OrdinalInscriptionTransferDestination::SpentInFees,
|
||||
None,
|
||||
)
|
||||
}
|
||||
};
|
||||
let satpoint_post_transfer = format!("{}:{}", outpoint_post_transfer, offset_post_transfer);
|
||||
|
||||
(
|
||||
destination,
|
||||
satpoint_post_transfer,
|
||||
post_transfer_output_value,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn augment_transaction_with_ordinals_transfers_data(
|
||||
tx: &mut BitcoinTransactionData,
|
||||
tx_index: usize,
|
||||
@@ -93,109 +174,17 @@ pub fn augment_transaction_with_ordinals_transfers_data(
|
||||
let satpoint_pre_transfer =
|
||||
format!("{}:{}", outpoint_pre_transfer, watched_satpoint.offset);
|
||||
|
||||
// Question is: are inscriptions moving to a new output,
|
||||
// burnt or lost in fees and transfered to the miner?
|
||||
|
||||
let inputs = tx
|
||||
.metadata
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|o| o.previous_output.value)
|
||||
.collect::<_>();
|
||||
let outputs = tx.metadata.outputs.iter().map(|o| o.value).collect::<_>();
|
||||
let post_transfer_data = compute_next_satpoint_data(
|
||||
input_index,
|
||||
watched_satpoint.offset,
|
||||
&inputs,
|
||||
&outputs,
|
||||
0,
|
||||
);
|
||||
|
||||
let (
|
||||
outpoint_post_transfer,
|
||||
offset_post_transfer,
|
||||
destination,
|
||||
post_transfer_output_value,
|
||||
) = match post_transfer_data {
|
||||
SatPosition::Output((output_index, offset)) => {
|
||||
let outpoint =
|
||||
format_outpoint_to_watch(&tx.transaction_identifier, output_index);
|
||||
let script_pub_key_hex =
|
||||
tx.metadata.outputs[output_index].get_script_pubkey_hex();
|
||||
let updated_address = match ScriptBuf::from_hex(&script_pub_key_hex) {
|
||||
Ok(script) => match Address::from_script(&script, network.clone()) {
|
||||
Ok(address) => OrdinalInscriptionTransferDestination::Transferred(
|
||||
address.to_string(),
|
||||
),
|
||||
Err(e) => {
|
||||
ctx.try_log(|logger| {
|
||||
info!(
|
||||
logger,
|
||||
"unable to retrieve address from {script_pub_key_hex}: {}",
|
||||
e.to_string()
|
||||
)
|
||||
});
|
||||
OrdinalInscriptionTransferDestination::Burnt(script.to_string())
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
ctx.try_log(|logger| {
|
||||
info!(
|
||||
logger,
|
||||
"unable to retrieve address from {script_pub_key_hex}: {}",
|
||||
e.to_string()
|
||||
)
|
||||
});
|
||||
OrdinalInscriptionTransferDestination::Burnt(
|
||||
script_pub_key_hex.to_string(),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
// At this point we know that inscriptions are being moved.
|
||||
ctx.try_log(|logger| {
|
||||
info!(
|
||||
logger,
|
||||
"Inscribed satoshi {} moved from {} to {} (block: {})",
|
||||
watched_satpoint.ordinal_number,
|
||||
satpoint_pre_transfer,
|
||||
outpoint,
|
||||
block_identifier.index,
|
||||
)
|
||||
});
|
||||
|
||||
(
|
||||
outpoint,
|
||||
offset,
|
||||
updated_address,
|
||||
Some(tx.metadata.outputs[output_index].value),
|
||||
)
|
||||
}
|
||||
SatPosition::Fee(offset) => {
|
||||
// Get Coinbase TX
|
||||
let total_offset = coinbase_subsidy + *cumulated_fees + offset;
|
||||
let outpoint = format_outpoint_to_watch(&coinbase_txid, 0);
|
||||
ctx.try_log(|logger| {
|
||||
info!(
|
||||
logger,
|
||||
"Inscribed satoshi {} spent in fees ({}+{}+{})",
|
||||
watched_satpoint.ordinal_number,
|
||||
coinbase_subsidy,
|
||||
cumulated_fees,
|
||||
offset
|
||||
)
|
||||
});
|
||||
(
|
||||
outpoint,
|
||||
total_offset,
|
||||
OrdinalInscriptionTransferDestination::SpentInFees,
|
||||
None,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let satpoint_post_transfer =
|
||||
format!("{}:{}", outpoint_post_transfer, offset_post_transfer);
|
||||
let (destination, satpoint_post_transfer, post_transfer_output_value) =
|
||||
compute_satpoint_post_transfer(
|
||||
&&*tx,
|
||||
input_index,
|
||||
0,
|
||||
network,
|
||||
coinbase_txid,
|
||||
coinbase_subsidy,
|
||||
cumulated_fees,
|
||||
ctx,
|
||||
);
|
||||
|
||||
let transfer_data = OrdinalInscriptionTransferData {
|
||||
ordinal_number: watched_satpoint.ordinal_number,
|
||||
|
||||
@@ -8,7 +8,6 @@ use std::sync::Arc;
|
||||
|
||||
use crate::db::{
|
||||
find_pinned_block_bytes_at_block_height, open_ordhook_db_conn_rocks_db_loop, BlockBytesCursor,
|
||||
TransferData,
|
||||
};
|
||||
|
||||
use crate::db::{TransactionBytesCursor, TraversalResult};
|
||||
@@ -19,6 +18,7 @@ pub fn compute_satoshi_number(
|
||||
block_identifier: &BlockIdentifier,
|
||||
transaction_identifier: &TransactionIdentifier,
|
||||
inscription_input_index: usize,
|
||||
inscription_pointer: u64,
|
||||
traversals_cache: &Arc<
|
||||
DashMap<(u32, [u8; 8]), TransactionBytesCursor, BuildHasherDefault<FxHasher>>,
|
||||
>,
|
||||
@@ -26,25 +26,20 @@ pub fn compute_satoshi_number(
|
||||
memory_available: usize,
|
||||
_back_tracking: bool,
|
||||
ctx: &Context,
|
||||
) -> Result<(TraversalResult, Vec<(u32, [u8; 8])>), String> {
|
||||
let mut inscription_offset_intra_output = 0;
|
||||
let mut inscription_output_index: usize = 0;
|
||||
let mut ordinal_offset = 0;
|
||||
let mut ordinal_block_number = block_identifier.index as u32;
|
||||
) -> Result<(TraversalResult, u64, Vec<(u32, [u8; 8], usize)>), String> {
|
||||
let mut ordinal_offset = inscription_pointer;
|
||||
let ordinal_block_number = block_identifier.index as u32;
|
||||
let txid = transaction_identifier.get_8_hash_bytes();
|
||||
let mut back_track = vec![];
|
||||
let blocks_db =
|
||||
open_ordhook_db_conn_rocks_db_loop(false, &blocks_db_dir, ulimit, memory_available, &ctx);
|
||||
|
||||
let (sats_ranges, inscription_offset_cross_outputs) = match traversals_cache
|
||||
let (mut tx_cursor, mut ordinal_block_number) = match traversals_cache
|
||||
.get(&(block_identifier.index as u32, txid.clone()))
|
||||
{
|
||||
Some(entry) => {
|
||||
let tx = entry.value();
|
||||
(
|
||||
tx.get_sat_ranges(),
|
||||
tx.get_cumulated_sats_in_until_input_index(inscription_input_index),
|
||||
)
|
||||
((tx.inputs[inscription_input_index].txin.clone(), tx.inputs[inscription_input_index].vout.into()), tx.inputs[inscription_input_index].block_height)
|
||||
}
|
||||
None => loop {
|
||||
match find_pinned_block_bytes_at_block_height(ordinal_block_number, 3, &blocks_db, &ctx)
|
||||
@@ -56,12 +51,7 @@ pub fn compute_satoshi_number(
|
||||
let cursor = BlockBytesCursor::new(&block_bytes.as_ref());
|
||||
match cursor.find_and_serialize_transaction_with_txid(&txid) {
|
||||
Some(tx) => {
|
||||
let sats_ranges = tx.get_sat_ranges();
|
||||
let inscription_offset_cross_outputs =
|
||||
tx.get_cumulated_sats_in_until_input_index(inscription_input_index);
|
||||
traversals_cache.insert((ordinal_block_number, txid.clone()), tx);
|
||||
back_track.push((ordinal_block_number, txid.clone()));
|
||||
break (sats_ranges, inscription_offset_cross_outputs);
|
||||
break ((tx.inputs[inscription_input_index].txin.clone(), tx.inputs[inscription_input_index].vout.into()), tx.inputs[inscription_input_index].block_height);
|
||||
}
|
||||
None => return Err(format!("txid not in block #{ordinal_block_number}")),
|
||||
}
|
||||
@@ -70,23 +60,6 @@ pub fn compute_satoshi_number(
|
||||
},
|
||||
};
|
||||
|
||||
for (i, (min, max)) in sats_ranges.into_iter().enumerate() {
|
||||
if inscription_offset_cross_outputs >= min && inscription_offset_cross_outputs < max {
|
||||
inscription_output_index = i;
|
||||
inscription_offset_intra_output = inscription_offset_cross_outputs - min;
|
||||
}
|
||||
}
|
||||
ctx.try_log(|logger| {
|
||||
debug!(
|
||||
logger,
|
||||
"Start ordinal number retrieval for Satpoint {}:{}:0 (block #{})",
|
||||
transaction_identifier.hash,
|
||||
inscription_input_index,
|
||||
block_identifier.index
|
||||
)
|
||||
});
|
||||
|
||||
let mut tx_cursor: ([u8; 8], usize) = (txid, inscription_input_index);
|
||||
let mut hops: u32 = 0;
|
||||
|
||||
loop {
|
||||
@@ -143,13 +116,8 @@ pub fn compute_satoshi_number(
|
||||
transfers: 0,
|
||||
inscription_input_index,
|
||||
transaction_identifier_inscription: transaction_identifier.clone(),
|
||||
transfer_data: TransferData {
|
||||
inscription_offset_intra_output,
|
||||
transaction_identifier_location: transaction_identifier.clone(),
|
||||
output_index: inscription_output_index,
|
||||
tx_index: 0,
|
||||
},
|
||||
},
|
||||
inscription_pointer,
|
||||
back_track,
|
||||
));
|
||||
}
|
||||
@@ -231,7 +199,7 @@ pub fn compute_satoshi_number(
|
||||
}
|
||||
} else {
|
||||
// isolate the target transaction
|
||||
let lazy_tx = match block_cursor.find_and_serialize_transaction_with_txid(&txid) {
|
||||
let tx_bytes_cursor = match block_cursor.find_and_serialize_transaction_with_txid(&txid) {
|
||||
Some(entry) => entry,
|
||||
None => {
|
||||
ctx.try_log(|logger| {
|
||||
@@ -247,7 +215,7 @@ pub fn compute_satoshi_number(
|
||||
};
|
||||
|
||||
let mut sats_out = 0;
|
||||
for (index, output_value) in lazy_tx.outputs.iter().enumerate() {
|
||||
for (index, output_value) in tx_bytes_cursor.outputs.iter().enumerate() {
|
||||
if index == tx_cursor.1 {
|
||||
break;
|
||||
}
|
||||
@@ -256,12 +224,12 @@ pub fn compute_satoshi_number(
|
||||
sats_out += ordinal_offset;
|
||||
|
||||
let mut sats_in = 0;
|
||||
for input in lazy_tx.inputs.iter() {
|
||||
for input in tx_bytes_cursor.inputs.iter() {
|
||||
sats_in += input.txin_value;
|
||||
|
||||
if sats_out < sats_in {
|
||||
back_track.push((ordinal_block_number, tx_cursor.0.clone()));
|
||||
traversals_cache.insert((ordinal_block_number, tx_cursor.0), lazy_tx.clone());
|
||||
back_track.push((ordinal_block_number, tx_cursor.0.clone(), tx_cursor.1));
|
||||
traversals_cache.insert((ordinal_block_number, tx_cursor.0), tx_bytes_cursor.clone());
|
||||
ordinal_offset = sats_out - (sats_in - input.txin_value);
|
||||
ordinal_block_number = input.block_height;
|
||||
tx_cursor = (input.txin.clone(), input.vout as usize);
|
||||
@@ -284,13 +252,8 @@ pub fn compute_satoshi_number(
|
||||
transfers: 0,
|
||||
inscription_input_index,
|
||||
transaction_identifier_inscription: transaction_identifier.clone(),
|
||||
transfer_data: TransferData {
|
||||
inscription_offset_intra_output,
|
||||
transaction_identifier_location: transaction_identifier.clone(),
|
||||
output_index: inscription_output_index,
|
||||
tx_index: 0,
|
||||
},
|
||||
},
|
||||
inscription_pointer,
|
||||
back_track,
|
||||
));
|
||||
}
|
||||
@@ -298,7 +261,7 @@ pub fn compute_satoshi_number(
|
||||
}
|
||||
|
||||
let height = Height(ordinal_block_number.into());
|
||||
let ordinal_number = height.starting_sat().0 + ordinal_offset + inscription_offset_intra_output;
|
||||
let ordinal_number = height.starting_sat().0 + ordinal_offset;
|
||||
|
||||
Ok((
|
||||
TraversalResult {
|
||||
@@ -307,13 +270,8 @@ pub fn compute_satoshi_number(
|
||||
transfers: hops,
|
||||
inscription_input_index,
|
||||
transaction_identifier_inscription: transaction_identifier.clone(),
|
||||
transfer_data: TransferData {
|
||||
inscription_offset_intra_output,
|
||||
transaction_identifier_location: transaction_identifier.clone(),
|
||||
output_index: inscription_output_index,
|
||||
tx_index: 0,
|
||||
},
|
||||
},
|
||||
inscription_pointer,
|
||||
back_track,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -1091,11 +1091,6 @@ pub fn find_inscription_with_id(
|
||||
));
|
||||
};
|
||||
|
||||
let Some(transfer_data) =
|
||||
find_initial_inscription_transfer_data(&ordinal_number, db_conn, ctx)?
|
||||
else {
|
||||
return Err(format!("unable to retrieve location for {inscription_id}"));
|
||||
};
|
||||
Ok(Some((
|
||||
TraversalResult {
|
||||
inscription_number,
|
||||
@@ -1103,7 +1098,6 @@ pub fn find_inscription_with_id(
|
||||
inscription_input_index,
|
||||
transaction_identifier_inscription,
|
||||
transfers: 0,
|
||||
transfer_data,
|
||||
},
|
||||
block_height,
|
||||
)))
|
||||
@@ -1114,8 +1108,6 @@ pub fn find_all_inscriptions_in_block(
|
||||
inscriptions_db_tx: &Connection,
|
||||
ctx: &Context,
|
||||
) -> BTreeMap<String, TraversalResult> {
|
||||
let transfers_data = find_all_transfers_in_block(block_height, inscriptions_db_tx, ctx);
|
||||
|
||||
let args: &[&dyn ToSql] = &[&block_height.to_sql().unwrap()];
|
||||
|
||||
let mut stmt = loop {
|
||||
@@ -1155,26 +1147,12 @@ pub fn find_all_inscriptions_in_block(
|
||||
let inscription_input_index: usize = row.get(4).unwrap();
|
||||
let (transaction_identifier_inscription, _) =
|
||||
{ parse_inscription_id(&inscription_id) };
|
||||
let Some(transfer_data) = transfers_data
|
||||
.get(&ordinal_number)
|
||||
.and_then(|entries| entries.first())
|
||||
else {
|
||||
ctx.try_log(|logger| {
|
||||
error!(
|
||||
logger,
|
||||
"unable to retrieve inscription genesis transfer data: {}",
|
||||
inscription_id,
|
||||
)
|
||||
});
|
||||
continue;
|
||||
};
|
||||
let traversal = TraversalResult {
|
||||
inscription_number,
|
||||
ordinal_number,
|
||||
inscription_input_index,
|
||||
transfers: 0,
|
||||
transaction_identifier_inscription: transaction_identifier_inscription.clone(),
|
||||
transfer_data: transfer_data.clone(),
|
||||
};
|
||||
results.insert(inscription_id, traversal);
|
||||
}
|
||||
@@ -1333,7 +1311,6 @@ pub struct TraversalResult {
|
||||
pub transaction_identifier_inscription: TransactionIdentifier,
|
||||
pub ordinal_number: u64,
|
||||
pub transfers: u32,
|
||||
pub transfer_data: TransferData,
|
||||
}
|
||||
|
||||
impl TraversalResult {
|
||||
|
||||
@@ -35,7 +35,13 @@ pub fn update_observer_progress(
|
||||
"UPDATE observers SET last_block_height_update = ? WHERE uuid = ?",
|
||||
rusqlite::params![last_block_height_update, uuid],
|
||||
) {
|
||||
ctx.try_log(|logger| warn!(logger, "unable to query observers.sqlite: {}", e.to_string()));
|
||||
ctx.try_log(|logger| {
|
||||
warn!(
|
||||
logger,
|
||||
"unable to query observers.sqlite: {}",
|
||||
e.to_string()
|
||||
)
|
||||
});
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
}
|
||||
}
|
||||
@@ -50,7 +56,13 @@ pub fn update_observer_streaming_enabled(
|
||||
"UPDATE observers SET streaming_enabled = ? WHERE uuid = ?",
|
||||
rusqlite::params![streaming_enabled, uuid],
|
||||
) {
|
||||
ctx.try_log(|logger| warn!(logger, "unable to query observers.sqlite: {}", e.to_string()));
|
||||
ctx.try_log(|logger| {
|
||||
warn!(
|
||||
logger,
|
||||
"unable to query observers.sqlite: {}",
|
||||
e.to_string()
|
||||
)
|
||||
});
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
}
|
||||
}
|
||||
@@ -177,7 +189,13 @@ pub fn remove_entry_from_observers(uuid: &str, db_conn: &Connection, ctx: &Conte
|
||||
"DELETE FROM observers WHERE uuid = ?1",
|
||||
rusqlite::params![&uuid],
|
||||
) {
|
||||
ctx.try_log(|logger| warn!(logger, "unable to query observers.sqlite: {}", e.to_string()));
|
||||
ctx.try_log(|logger| {
|
||||
warn!(
|
||||
logger,
|
||||
"unable to query observers.sqlite: {}",
|
||||
e.to_string()
|
||||
)
|
||||
});
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user