Changeset View
Changeset View
Standalone View
Standalone View
chronik/chronik-indexer/src/query/txs.rs
// Copyright (c) 2023 The Bitcoin developers | // Copyright (c) 2023 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
//! Module for [`QueryTxs`], to query txs from mempool/db. | //! Module for [`QueryTxs`], to query txs from mempool/db. | ||||
use abc_rust_error::{Result, WrapErr}; | use abc_rust_error::{Result, WrapErr}; | ||||
use bitcoinsuite_core::{ | use bitcoinsuite_core::{ | ||||
ser::BitcoinSer, | ser::BitcoinSer, | ||||
tx::{Tx, TxId}, | tx::{Tx, TxId}, | ||||
}; | }; | ||||
use chronik_bridge::ffi; | |||||
use chronik_db::{ | use chronik_db::{ | ||||
db::Db, | db::Db, | ||||
io::{BlockReader, SpentByReader, TxReader}, | io::{BlockReader, SpentByReader, TxReader}, | ||||
mem::Mempool, | mem::Mempool, | ||||
}; | }; | ||||
use chronik_proto::proto; | use chronik_proto::proto; | ||||
use thiserror::Error; | use thiserror::Error; | ||||
use crate::{ | use crate::{ | ||||
avalanche::Avalanche, | avalanche::Avalanche, | ||||
indexer::Node, | |||||
query::{ | query::{ | ||||
make_genesis_info_proto, make_token_type_proto, make_tx_proto, | make_genesis_info_proto, make_token_type_proto, make_tx_proto, | ||||
read_token_info, OutputsSpent, QueryTxError::*, TxTokenData, | read_token_info, OutputsSpent, QueryTxError::*, TxTokenData, | ||||
}, | }, | ||||
}; | }; | ||||
/// Struct for querying txs from the db/mempool. | /// Struct for querying txs from the db/mempool. | ||||
#[derive(Debug)] | #[derive(Debug)] | ||||
pub struct QueryTxs<'a> { | pub struct QueryTxs<'a> { | ||||
/// Database | /// Database | ||||
pub db: &'a Db, | pub db: &'a Db, | ||||
/// Avalanche | /// Avalanche | ||||
pub avalanche: &'a Avalanche, | pub avalanche: &'a Avalanche, | ||||
/// Mempool | /// Mempool | ||||
pub mempool: &'a Mempool, | pub mempool: &'a Mempool, | ||||
/// Access to bitcoind to read txs | |||||
pub node: &'a Node, | |||||
/// Whether the SLP/ALP token index is enabled | /// Whether the SLP/ALP token index is enabled | ||||
pub is_token_index_enabled: bool, | pub is_token_index_enabled: bool, | ||||
} | } | ||||
/// Errors indicating something went wrong with reading txs. | /// Errors indicating something went wrong with reading txs. | ||||
#[derive(Debug, Error, PartialEq)] | #[derive(Debug, Error, PartialEq)] | ||||
pub enum QueryTxError { | pub enum QueryTxError { | ||||
/// Transaction not in mempool nor DB. | /// Transaction not in mempool nor DB. | ||||
Show All 36 Lines | pub fn tx_by_id(&self, txid: TxId) -> Result<proto::Tx> { | ||||
.ok_or(TxNotFound(txid))?; | .ok_or(TxNotFound(txid))?; | ||||
let tx_entry = block_tx.entry; | let tx_entry = block_tx.entry; | ||||
let block_reader = BlockReader::new(self.db)?; | let block_reader = BlockReader::new(self.db)?; | ||||
let spent_by_reader = SpentByReader::new(self.db)?; | let spent_by_reader = SpentByReader::new(self.db)?; | ||||
let block = block_reader | let block = block_reader | ||||
.by_height(block_tx.block_height)? | .by_height(block_tx.block_height)? | ||||
.ok_or(DbTxHasNoBlock(txid))?; | .ok_or(DbTxHasNoBlock(txid))?; | ||||
let tx = Tx::from( | let tx = Tx::from( | ||||
ffi::load_tx( | self.node | ||||
.bridge | |||||
.load_tx( | |||||
block.file_num, | block.file_num, | ||||
tx_entry.data_pos, | tx_entry.data_pos, | ||||
tx_entry.undo_pos, | tx_entry.undo_pos, | ||||
) | ) | ||||
.wrap_err(ReadFailure(txid))?, | .wrap_err(ReadFailure(txid))?, | ||||
); | ); | ||||
let outputs_spent = OutputsSpent::query( | let outputs_spent = OutputsSpent::query( | ||||
&spent_by_reader, | &spent_by_reader, | ||||
&tx_reader, | &tx_reader, | ||||
self.mempool.spent_by().outputs_spent(&txid), | self.mempool.spent_by().outputs_spent(&txid), | ||||
tx_num, | tx_num, | ||||
)?; | )?; | ||||
let token = TxTokenData::from_db( | let token = TxTokenData::from_db( | ||||
Show All 25 Lines | pub fn raw_tx_by_id(&self, txid: &TxId) -> Result<proto::RawTx> { | ||||
None => { | None => { | ||||
let tx_reader = TxReader::new(self.db)?; | let tx_reader = TxReader::new(self.db)?; | ||||
let block_reader = BlockReader::new(self.db)?; | let block_reader = BlockReader::new(self.db)?; | ||||
let block_tx = | let block_tx = | ||||
tx_reader.tx_by_txid(txid)?.ok_or(TxNotFound(*txid))?; | tx_reader.tx_by_txid(txid)?.ok_or(TxNotFound(*txid))?; | ||||
let block = block_reader | let block = block_reader | ||||
.by_height(block_tx.block_height)? | .by_height(block_tx.block_height)? | ||||
.ok_or(DbTxHasNoBlock(*txid))?; | .ok_or(DbTxHasNoBlock(*txid))?; | ||||
ffi::load_raw_tx(block.file_num, block_tx.entry.data_pos) | self.node | ||||
.bridge | |||||
.load_raw_tx(block.file_num, block_tx.entry.data_pos) | |||||
.wrap_err(ReadFailure(*txid))? | .wrap_err(ReadFailure(*txid))? | ||||
} | } | ||||
}; | }; | ||||
Ok(proto::RawTx { raw_tx }) | Ok(proto::RawTx { raw_tx }) | ||||
} | } | ||||
/// Get token info of the token by token ID. | /// Get token info of the token by token ID. | ||||
pub fn token_info(&self, token_id_txid: &TxId) -> Result<proto::TokenInfo> { | pub fn token_info(&self, token_id_txid: &TxId) -> Result<proto::TokenInfo> { | ||||
Show All 19 Lines |