brk_query/impl/block/
txs.rs1use brk_error::{Error, Result};
2use brk_types::{BlockHash, Height, Transaction, TxIndex, Txid};
3use vecdb::{AnyVec, GenericStoredVec, TypedVecIterator};
4
5use super::BLOCK_TXS_PAGE_SIZE;
6use crate::Query;
7
8impl Query {
9 pub fn block_txids(&self, hash: &BlockHash) -> Result<Vec<Txid>> {
10 let height = self.height_by_hash(hash)?;
11 self.block_txids_by_height(height)
12 }
13
14 pub fn block_txs(&self, hash: &BlockHash, start_index: TxIndex) -> Result<Vec<Transaction>> {
15 let height = self.height_by_hash(hash)?;
16 self.block_txs_by_height(height, start_index.into())
17 }
18
19 pub fn block_txid_at_index(&self, hash: &BlockHash, index: TxIndex) -> Result<Txid> {
20 let height = self.height_by_hash(hash)?;
21 self.block_txid_at_index_by_height(height, index.into())
22 }
23
24 fn block_txids_by_height(&self, height: Height) -> Result<Vec<Txid>> {
27 let indexer = self.indexer();
28
29 let max_height = self.height();
30 if height > max_height {
31 return Err(Error::OutOfRange("Block height out of range".into()));
32 }
33
34 let first_txindex = indexer.vecs.transactions.first_txindex.read_once(height)?;
35 let next_first_txindex = indexer
36 .vecs
37 .transactions
38 .first_txindex
39 .read_once(height.incremented())
40 .unwrap_or_else(|_| TxIndex::from(indexer.vecs.transactions.txid.len()));
41
42 let first: usize = first_txindex.into();
43 let next: usize = next_first_txindex.into();
44 let count = next - first;
45
46 let txids: Vec<Txid> = indexer
47 .vecs
48 .transactions
49 .txid
50 .iter()?
51 .skip(first)
52 .take(count)
53 .collect();
54
55 Ok(txids)
56 }
57
58 fn block_txs_by_height(
59 &self,
60 height: Height,
61 start_index: usize,
62 ) -> Result<Vec<Transaction>> {
63 let indexer = self.indexer();
64
65 let max_height = self.height();
66 if height > max_height {
67 return Err(Error::OutOfRange("Block height out of range".into()));
68 }
69
70 let first_txindex = indexer.vecs.transactions.first_txindex.read_once(height)?;
71 let next_first_txindex = indexer
72 .vecs
73 .transactions
74 .first_txindex
75 .read_once(height.incremented())
76 .unwrap_or_else(|_| TxIndex::from(indexer.vecs.transactions.txid.len()));
77
78 let first: usize = first_txindex.into();
79 let next: usize = next_first_txindex.into();
80 let tx_count = next - first;
81
82 if start_index >= tx_count {
83 return Ok(Vec::new());
84 }
85
86 let end_index = (start_index + BLOCK_TXS_PAGE_SIZE).min(tx_count);
87 let count = end_index - start_index;
88
89 let mut txs = Vec::with_capacity(count);
90 for i in start_index..end_index {
91 let txindex = TxIndex::from(first + i);
92 let tx = self.transaction_by_index(txindex)?;
93 txs.push(tx);
94 }
95
96 Ok(txs)
97 }
98
99 fn block_txid_at_index_by_height(&self, height: Height, index: usize) -> Result<Txid> {
100 let indexer = self.indexer();
101
102 let max_height = self.height();
103 if height > max_height {
104 return Err(Error::OutOfRange("Block height out of range".into()));
105 }
106
107 let first_txindex = indexer.vecs.transactions.first_txindex.read_once(height)?;
108 let next_first_txindex = indexer
109 .vecs
110 .transactions
111 .first_txindex
112 .read_once(height.incremented())
113 .unwrap_or_else(|_| TxIndex::from(indexer.vecs.transactions.txid.len()));
114
115 let first: usize = first_txindex.into();
116 let next: usize = next_first_txindex.into();
117 let tx_count = next - first;
118
119 if index >= tx_count {
120 return Err(Error::OutOfRange("Transaction index out of range".into()));
121 }
122
123 let txindex = TxIndex::from(first + index);
124 let txid = indexer.vecs.transactions.txid.iter()?.get_unwrap(txindex);
125
126 Ok(txid)
127 }
128}