global: snapshot

This commit is contained in:
nym21
2025-12-12 16:55:55 +01:00
parent e755f2856a
commit 3526a177fc
66 changed files with 1964 additions and 9175 deletions

View File

@@ -9,7 +9,6 @@ use brk_types::{
Address, AddressStats, Height, Index, IndexInfo, Limit, Metric, MetricCount, Transaction,
TreeNode, TxidPath,
};
#[cfg(feature = "tokio")]
use tokio::task::spawn_blocking;
use crate::{
@@ -18,7 +17,6 @@ use crate::{
};
#[derive(Clone)]
#[cfg(feature = "tokio")]
pub struct AsyncQuery(Query);
impl AsyncQuery {

View File

@@ -7,8 +7,10 @@ use std::{
use bitcoin::consensus::Decodable;
use brk_error::{Error, Result};
use brk_reader::XORIndex;
use brk_types::{Transaction, Txid, TxidPath, TxidPrefix};
use vecdb::TypedVecIterator;
use brk_types::{
Sats, Transaction, TxIn, TxIndex, TxOut, TxStatus, Txid, TxidPath, TxidPrefix, Vout, Weight,
};
use vecdb::{GenericStoredVec, TypedVecIterator};
use crate::Query;
@@ -20,7 +22,7 @@ pub fn get_transaction(TxidPath { txid }: TxidPath, query: &Query) -> Result<Tra
let txid = Txid::from(txid);
let prefix = TxidPrefix::from(&txid);
let indexer = query.indexer();
let Ok(Some(index)) = indexer
let Ok(Some(txindex)) = indexer
.stores
.txidprefix_to_txindex
.get(&prefix)
@@ -29,16 +31,29 @@ pub fn get_transaction(TxidPath { txid }: TxidPath, query: &Query) -> Result<Tra
return Err(Error::UnknownTxid);
};
let txid = indexer.vecs.txindex_to_txid.iter()?.get_unwrap(index);
get_transaction_by_index(txindex, query)
}
pub fn get_transaction_by_index(txindex: TxIndex, query: &Query) -> Result<Transaction> {
let indexer = query.indexer();
let reader = query.reader();
let computer = query.computer();
let position = computer.blks.txindex_to_position.iter()?.get_unwrap(index);
let len = indexer.vecs.txindex_to_total_size.iter()?.get_unwrap(index);
// Get tx metadata using read_once for single lookups
let txid = indexer.vecs.tx.txindex_to_txid.read_once(txindex)?;
let height = indexer.vecs.tx.txindex_to_height.read_once(txindex)?;
let version = indexer.vecs.tx.txindex_to_txversion.read_once(txindex)?;
let lock_time = indexer.vecs.tx.txindex_to_rawlocktime.read_once(txindex)?;
let total_size = indexer.vecs.tx.txindex_to_total_size.read_once(txindex)?;
let first_txinindex = indexer.vecs.tx.txindex_to_first_txinindex.read_once(txindex)?;
let position = computer.blks.txindex_to_position.read_once(txindex)?;
// Get block info for status
let block_hash = indexer.vecs.block.height_to_blockhash.read_once(height)?;
let block_time = indexer.vecs.block.height_to_timestamp.read_once(height)?;
// Read and decode the raw transaction from blk file
let blk_index_to_blk_path = reader.blk_index_to_blk_path();
let Some(blk_path) = blk_index_to_blk_path.get(&position.blk_index()) else {
return Err(Error::Str("Failed to get the correct blk file"));
};
@@ -57,22 +72,105 @@ pub fn get_transaction(TxidPath { txid }: TxidPath, query: &Query) -> Result<Tra
return Err(Error::Str("Failed to seek position in file"));
}
let mut buffer = vec![0u8; *len as usize];
let mut buffer = vec![0u8; *total_size as usize];
if file.read_exact(&mut buffer).is_err() {
return Err(Error::Str("Failed to read the transaction (read exact)"));
}
xori.bytes(&mut buffer, reader.xor_bytes());
let mut reader = Cursor::new(buffer);
let Ok(tx) = bitcoin::Transaction::consensus_decode(&mut reader) else {
let mut cursor = Cursor::new(buffer);
let Ok(tx) = bitcoin::Transaction::consensus_decode(&mut cursor) else {
return Err(Error::Str("Failed decode the transaction"));
};
todo!();
// For iterating through inputs, we need iterators (multiple lookups)
let mut txindex_to_txid_iter = indexer.vecs.tx.txindex_to_txid.iter()?;
let mut txindex_to_first_txoutindex_iter = indexer.vecs.tx.txindex_to_first_txoutindex.iter()?;
let mut txinindex_to_outpoint_iter = indexer.vecs.txin.txinindex_to_outpoint.iter()?;
let mut txoutindex_to_value_iter = indexer.vecs.txout.txoutindex_to_value.iter()?;
// Ok(TxInfo {
// txid,
// index,
// // tx
// })
// Build inputs with prevout information
let input: Vec<TxIn> = tx
.input
.iter()
.enumerate()
.map(|(i, txin)| {
let txinindex = first_txinindex + i;
let outpoint = txinindex_to_outpoint_iter.get_unwrap(txinindex);
let is_coinbase = outpoint.is_coinbase();
// Get prevout info if not coinbase
let (prev_txid, prev_vout, prevout) = if is_coinbase {
(Txid::COINBASE, Vout::MAX, None)
} else {
let prev_txindex = outpoint.txindex();
let prev_vout = outpoint.vout();
let prev_txid = txindex_to_txid_iter.get_unwrap(prev_txindex);
// Calculate the txoutindex for the prevout
let prev_first_txoutindex =
txindex_to_first_txoutindex_iter.get_unwrap(prev_txindex);
let prev_txoutindex = prev_first_txoutindex + prev_vout;
// Get the value of the prevout
let prev_value = txoutindex_to_value_iter.get_unwrap(prev_txoutindex);
// We don't have the script_pubkey stored directly, so we need to reconstruct
// For now, we'll get it from the decoded transaction's witness/scriptsig
// which can reveal the prevout script type, but the actual script needs
// to be fetched from the spending tx or reconstructed from address bytes
let prevout = Some(TxOut::from((
bitcoin::ScriptBuf::new(), // Placeholder - would need to reconstruct
prev_value,
)));
(prev_txid, prev_vout, prevout)
};
TxIn {
txid: prev_txid,
vout: prev_vout,
prevout,
script_sig: txin.script_sig.clone(),
script_sig_asm: (),
is_coinbase,
sequence: txin.sequence.0,
inner_redeem_script_asm: (),
}
})
.collect();
// Calculate weight before consuming tx.output
let weight = Weight::from(tx.weight());
// Build outputs
let output: Vec<TxOut> = tx.output.into_iter().map(TxOut::from).collect();
// Build status
let status = TxStatus {
confirmed: true,
block_height: Some(height),
block_hash: Some(block_hash),
block_time: Some(block_time),
};
let mut transaction = Transaction {
index: Some(txindex),
txid,
version,
lock_time,
total_size: *total_size as usize,
weight,
total_sigop_cost: 0, // Would need to calculate from scripts
fee: Sats::ZERO, // Will be computed below
input,
output,
status,
};
// Compute fee from inputs - outputs
transaction.compute_fee();
Ok(transaction)
}

View File

@@ -14,6 +14,7 @@ use brk_types::{
};
use vecdb::{AnyExportableVec, AnyStoredVec};
#[cfg(feature = "tokio")]
mod r#async;
mod chain;
mod deser;
@@ -22,6 +23,7 @@ mod pagination;
mod params;
mod vecs;
#[cfg(feature = "tokio")]
pub use r#async::*;
pub use output::{Output, Value};
pub use pagination::{PaginatedIndexParam, PaginatedMetrics, PaginationParam};
@@ -65,7 +67,7 @@ impl Query {
}
pub fn get_height(&self) -> Height {
Height::from(self.indexer().vecs.height_to_blockhash.stamp())
Height::from(self.indexer().vecs.block.height_to_blockhash.stamp())
}
pub fn get_address(&self, address: Address) -> Result<AddressStats> {