1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
//!
//! implementation of methods that retrieve block info with outpoints connected
//!
use crate::api::{
BitcoinDB, TxConnectable, ConnectedBlockIterator, FConnectedBlock, FConnectedTransaction, FTxOut,
SConnectedBlock, SConnectedTransaction, STxOut, Txid,
};
use crate::parser::errors::{OpError, OpResult};
use crate::parser::proto::connected_proto::BlockConnectable;
// Define iterator types
pub type ConnectedBlockIteratorFull =
ConnectedBlockIterator<FConnectedBlock, FConnectedTransaction, FTxOut>;
pub type ConnectedBlockIteratorSimple =
ConnectedBlockIterator<SConnectedBlock, SConnectedTransaction, STxOut>;
impl BitcoinDB {
///
/// Get a full block with inputs replaced by connected outputs.
///
/// This function requires `txindex` to be set to `true`,
/// and `txindex=1` when running Bitcoin Core.
///
/// # Caveat!!
///
/// This is a *very slow* function!!
/// For massive processing of `connected` blocks, use `iter`.
///
pub fn get_block_connected<T: BlockConnectable>(&self, height: i32) -> OpResult<T> {
if !self.tx_db.is_open() {
return Err(OpError::from("TxDB not open"));
}
let tx = self.get_block(height)?;
Ok(T::connect(tx, &self.tx_db, &self.blk_file))
}
///
/// Get `full version` transaction with outpoints replaced by outputs.
///
/// # Caveats
///
/// Slow! Not suitable for massive computation. Use `iter`.
///
pub fn get_transaction_connected<T: TxConnectable>(&self, txid: &Txid) -> OpResult<T> {
let tx = self.get_transaction(txid)?;
let tx_parsed = T::connect(tx, &self.tx_db, &self.blk_file);
Ok(tx_parsed)
}
///
/// Iterate through all blocks for a given heights (excluded).
///
/// Format: `full block (with outpoints connected)`.
///
/// This iterator use `unspent output` to track down the connected
/// outputs of each outpoints.
///
/// ## Note
/// This does NOT require `txindex=true`.
///
/// # Performance
///
/// Iterating through height from 0 to 700000 takes 5 hours.
/// The performance bottleneck is most likely diskIO.
///
/// This iterator is implemented to read the blocks in concurrency,
/// but each block connects its outpoints to outputs only after
/// all previous blocks have finished inserting their outputs in
/// `unspent cache`.
/// The result is still produced in the sequential order.
///
/// Because this iterator tracks unspent outputs,
/// it can use up to 20GB to 30GB memory.
///
/// This iterator can only start from genesis block, because it has to
/// track unspent transactions.
///
/// TODO: might use txindex to allow for iterating starting from larger heights.
///
/// # Example
///
/// ```rust
/// use bitcoin_explorer::api::BitcoinDB;
/// use std::path::Path;
///
/// let path = Path::new("/Users/me/bitcoin").unwrap();
///
/// // launch without reading txindex
/// let db = BitcoinDB::new(path, false).unwrap();
///
/// // iterate over block from 0 to 700000
/// for block in db.iter_block_full_connected(700000) {
/// for tx in block.txdata {
/// println!("do something for this transaction");
/// }
/// }
/// ```
///
pub fn iter_block_full_connected(&self, end: u32) -> ConnectedBlockIteratorFull {
ConnectedBlockIterator::new(self, end)
}
///
/// Iterate through all blocks for a given heights (excluded).
///
/// Format: `simple block (with outpoints connected)`.
///
/// This iterator use `unspent output` to track down the connected
/// outputs of each outpoints.
///
/// ## Note
/// This does NOT require `txindex=true`.
///
/// # Performance
///
/// Iterating through height from 0 to 700000 takes 5 hours.
/// The performance bottleneck is most likely diskIO.
///
/// This iterator is implemented to read the blocks in concurrency,
/// but each block connects its outpoints to outputs only after
/// all previous blocks have finished inserting their outputs in
/// `unspent cache`.
/// The result is still produced in the sequential order.
///
/// Because this iterator tracks unspent outputs,
/// it can use up to 20GB to 30GB memory.
///
/// This iterator can only start from genesis block, because it has to
/// track unspent transactions.
///
/// TODO: might use txindex to allow for iterating starting from larger heights.
///
/// # Example
///
/// ```rust
/// use bitcoin_explorer::api::BitcoinDB;
/// use std::path::Path;
///
/// let path = Path::new("/Users/me/bitcoin").unwrap();
///
/// // launch without reading txindex
/// let db = BitcoinDB::new(path, false).unwrap();
///
/// // iterate over block from 0 to 700000
/// for block in db.iter_block_simple_connected(700000) {
/// for tx in block.txdata {
/// println!("do something for this transaction");
/// }
/// }
/// ```
///
pub fn iter_block_simple_connected(&self, end: u32) -> ConnectedBlockIteratorSimple {
ConnectedBlockIterator::new(self, end)
}
}