mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 22:59:58 -07:00
global: MASSIVE snapshot
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use brk_error::{Error, Result};
|
||||
use brk_types::{BlockHash, BlockHashPrefix, BlockInfo, Height, TxIndex};
|
||||
use vecdb::{AnyVec, GenericStoredVec, VecIndex};
|
||||
use vecdb::{AnyVec, ReadableVec, VecIndex};
|
||||
|
||||
use crate::Query;
|
||||
|
||||
@@ -21,10 +21,10 @@ impl Query {
|
||||
}
|
||||
|
||||
let blockhash = indexer.vecs.blocks.blockhash.read_once(height)?;
|
||||
let difficulty = indexer.vecs.blocks.difficulty.read_once(height)?;
|
||||
let timestamp = indexer.vecs.blocks.timestamp.read_once(height)?;
|
||||
let size = indexer.vecs.blocks.total_size.read_once(height)?;
|
||||
let weight = indexer.vecs.blocks.weight.read_once(height)?;
|
||||
let difficulty = indexer.vecs.blocks.difficulty.collect_one(height).unwrap();
|
||||
let timestamp = indexer.vecs.blocks.timestamp.collect_one(height).unwrap();
|
||||
let size = indexer.vecs.blocks.total_size.collect_one(height).unwrap();
|
||||
let weight = indexer.vecs.blocks.weight.collect_one(height).unwrap();
|
||||
let tx_count = self.tx_count_at_height(height, max_height)?;
|
||||
|
||||
Ok(BlockInfo {
|
||||
@@ -45,12 +45,58 @@ impl Query {
|
||||
let start = start.min(max_height);
|
||||
|
||||
let start_u32: u32 = start.into();
|
||||
let count = DEFAULT_BLOCK_COUNT.min(start_u32 + 1);
|
||||
let count = DEFAULT_BLOCK_COUNT.min(start_u32 + 1) as usize;
|
||||
|
||||
let mut blocks = Vec::with_capacity(count as usize);
|
||||
for i in 0..count {
|
||||
let height = Height::from(start_u32 - i);
|
||||
blocks.push(self.block_by_height(height)?);
|
||||
if count == 0 {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
let indexer = self.indexer();
|
||||
let computer = self.computer();
|
||||
|
||||
// Batch-read all PcoVec data for the contiguous range (avoids
|
||||
// per-block page decompression — 4 reads instead of 4*count).
|
||||
let end = start_u32 as usize + 1;
|
||||
let begin = end - count;
|
||||
|
||||
let difficulties = indexer.vecs.blocks.difficulty.collect_range_at(begin, end);
|
||||
let timestamps = indexer.vecs.blocks.timestamp.collect_range_at(begin, end);
|
||||
let sizes = indexer.vecs.blocks.total_size.collect_range_at(begin, end);
|
||||
let weights = indexer.vecs.blocks.weight.collect_range_at(begin, end);
|
||||
|
||||
// Batch-read first_txindex for tx_count computation (need one extra for next boundary)
|
||||
let txindex_end = if end <= max_height.to_usize() {
|
||||
end + 1
|
||||
} else {
|
||||
end
|
||||
};
|
||||
let first_txindexes: Vec<TxIndex> = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.first_txindex
|
||||
.collect_range_at(begin, txindex_end);
|
||||
let total_txs = computer.indexes.txindex.identity.len();
|
||||
|
||||
let mut blocks = Vec::with_capacity(count);
|
||||
for i in (0..count).rev() {
|
||||
let height = Height::from(begin + i);
|
||||
let blockhash = indexer.vecs.blocks.blockhash.read_once(height)?;
|
||||
|
||||
let tx_count = if i + 1 < first_txindexes.len() {
|
||||
first_txindexes[i + 1].to_usize() - first_txindexes[i].to_usize()
|
||||
} else {
|
||||
total_txs - first_txindexes[i].to_usize()
|
||||
};
|
||||
|
||||
blocks.push(BlockInfo {
|
||||
id: blockhash,
|
||||
height,
|
||||
tx_count: tx_count as u32,
|
||||
size: *sizes[i],
|
||||
weight: weights[i],
|
||||
timestamp: timestamps[i],
|
||||
difficulty: *difficulties[i],
|
||||
});
|
||||
}
|
||||
|
||||
Ok(blocks)
|
||||
@@ -72,27 +118,26 @@ impl Query {
|
||||
}
|
||||
|
||||
fn max_height(&self) -> Height {
|
||||
Height::from(
|
||||
self.indexer()
|
||||
.vecs
|
||||
.blocks
|
||||
.blockhash
|
||||
.len()
|
||||
.saturating_sub(1),
|
||||
)
|
||||
Height::from(self.indexer().vecs.blocks.blockhash.len().saturating_sub(1))
|
||||
}
|
||||
|
||||
fn tx_count_at_height(&self, height: Height, max_height: Height) -> Result<u32> {
|
||||
let indexer = self.indexer();
|
||||
let computer = self.computer();
|
||||
|
||||
let first_txindex = indexer.vecs.transactions.first_txindex.read_once(height)?;
|
||||
let first_txindex = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.first_txindex
|
||||
.collect_one(height)
|
||||
.unwrap();
|
||||
let next_first_txindex = if height < max_height {
|
||||
indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.first_txindex
|
||||
.read_once(height.incremented())?
|
||||
.collect_one(height.incremented())
|
||||
.unwrap()
|
||||
} else {
|
||||
TxIndex::from(computer.indexes.txindex.identity.len())
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use brk_error::{Error, Result};
|
||||
use brk_types::{BlockHash, Height};
|
||||
use vecdb::{AnyVec, GenericStoredVec};
|
||||
use vecdb::{AnyVec, ReadableVec};
|
||||
|
||||
use crate::Query;
|
||||
|
||||
@@ -20,8 +20,8 @@ impl Query {
|
||||
return Err(Error::OutOfRange("Block height out of range".into()));
|
||||
}
|
||||
|
||||
let position = computer.positions.block_position.read_once(height)?;
|
||||
let size = indexer.vecs.blocks.total_size.read_once(height)?;
|
||||
let position = computer.positions.block_position.collect_one(height).unwrap();
|
||||
let size = indexer.vecs.blocks.total_size.collect_one(height).unwrap();
|
||||
|
||||
reader.read_raw_bytes(position, *size as usize)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use brk_error::Result;
|
||||
use brk_types::{BlockHash, BlockStatus, Height};
|
||||
use vecdb::{AnyVec, GenericStoredVec};
|
||||
use vecdb::AnyVec;
|
||||
|
||||
use crate::Query;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use brk_error::{Error, Result};
|
||||
use brk_types::{BlockTimestamp, Date, DateIndex, Height, Timestamp};
|
||||
use brk_types::{BlockTimestamp, Date, Day1, Height, Timestamp};
|
||||
use jiff::Timestamp as JiffTimestamp;
|
||||
use vecdb::{GenericStoredVec, TypedVecIterator};
|
||||
use vecdb::ReadableVec;
|
||||
|
||||
use crate::Query;
|
||||
|
||||
@@ -19,28 +19,26 @@ impl Query {
|
||||
|
||||
let target = timestamp;
|
||||
let date = Date::from(target);
|
||||
let dateindex = DateIndex::try_from(date).unwrap_or_default();
|
||||
let day1 = Day1::try_from(date).unwrap_or_default();
|
||||
|
||||
// Get first height of the target date
|
||||
let first_height_of_day = computer
|
||||
.indexes
|
||||
.dateindex
|
||||
.day1
|
||||
.first_height
|
||||
.read_once(dateindex)
|
||||
.collect_one(day1)
|
||||
.unwrap_or(Height::from(0usize));
|
||||
|
||||
let start: usize = usize::from(first_height_of_day).min(max_height_usize);
|
||||
|
||||
// Use iterator for efficient sequential access
|
||||
let mut timestamp_iter = indexer.vecs.blocks.timestamp.iter()?;
|
||||
let timestamps = &indexer.vecs.blocks.timestamp;
|
||||
|
||||
// Search forward from start to find the last block <= target timestamp
|
||||
let mut best_height = start;
|
||||
let mut best_ts = timestamp_iter.get_unwrap(Height::from(start));
|
||||
let mut best_ts = timestamps.collect_one_at(start).unwrap();
|
||||
|
||||
for h in (start + 1)..=max_height_usize {
|
||||
let height = Height::from(h);
|
||||
let block_ts = timestamp_iter.get_unwrap(height);
|
||||
let block_ts = timestamps.collect_one_at(h).unwrap();
|
||||
if block_ts <= target {
|
||||
best_height = h;
|
||||
best_ts = block_ts;
|
||||
@@ -51,8 +49,7 @@ impl Query {
|
||||
|
||||
// Check one block before start in case we need to go backward
|
||||
if start > 0 && best_ts > target {
|
||||
let prev_height = Height::from(start - 1);
|
||||
let prev_ts = timestamp_iter.get_unwrap(prev_height);
|
||||
let prev_ts = timestamps.collect_one_at(start - 1).unwrap();
|
||||
if prev_ts <= target {
|
||||
best_height = start - 1;
|
||||
best_ts = prev_ts;
|
||||
@@ -60,12 +57,7 @@ impl Query {
|
||||
}
|
||||
|
||||
let height = Height::from(best_height);
|
||||
let blockhash = indexer
|
||||
.vecs
|
||||
.blocks
|
||||
.blockhash
|
||||
.iter()?
|
||||
.get_unwrap(height);
|
||||
let blockhash = indexer.vecs.blocks.blockhash.reader().get(usize::from(height));
|
||||
|
||||
// Convert timestamp to ISO 8601 format
|
||||
let ts_secs: i64 = (*best_ts).into();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use brk_error::{Error, Result};
|
||||
use brk_types::{BlockHash, Height, Transaction, TxIndex, Txid};
|
||||
use vecdb::{AnyVec, GenericStoredVec, TypedVecIterator};
|
||||
use vecdb::{AnyVec, ReadableVec};
|
||||
|
||||
use super::BLOCK_TXS_PAGE_SIZE;
|
||||
use crate::Query;
|
||||
@@ -31,26 +31,22 @@ impl Query {
|
||||
return Err(Error::OutOfRange("Block height out of range".into()));
|
||||
}
|
||||
|
||||
let first_txindex = indexer.vecs.transactions.first_txindex.read_once(height)?;
|
||||
let first_txindex = indexer.vecs.transactions.first_txindex.collect_one(height).unwrap();
|
||||
let next_first_txindex = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.first_txindex
|
||||
.read_once(height.incremented())
|
||||
.unwrap_or_else(|_| TxIndex::from(indexer.vecs.transactions.txid.len()));
|
||||
.collect_one(height.incremented())
|
||||
.unwrap_or_else(|| TxIndex::from(indexer.vecs.transactions.txid.len()));
|
||||
|
||||
let first: usize = first_txindex.into();
|
||||
let next: usize = next_first_txindex.into();
|
||||
let count = next - first;
|
||||
|
||||
let txids: Vec<Txid> = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.txid
|
||||
.iter()?
|
||||
.skip(first)
|
||||
.take(count)
|
||||
.collect();
|
||||
.collect_range_at(first, next);
|
||||
|
||||
Ok(txids)
|
||||
}
|
||||
@@ -67,13 +63,13 @@ impl Query {
|
||||
return Err(Error::OutOfRange("Block height out of range".into()));
|
||||
}
|
||||
|
||||
let first_txindex = indexer.vecs.transactions.first_txindex.read_once(height)?;
|
||||
let first_txindex = indexer.vecs.transactions.first_txindex.collect_one(height).unwrap();
|
||||
let next_first_txindex = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.first_txindex
|
||||
.read_once(height.incremented())
|
||||
.unwrap_or_else(|_| TxIndex::from(indexer.vecs.transactions.txid.len()));
|
||||
.collect_one(height.incremented())
|
||||
.unwrap_or_else(|| TxIndex::from(indexer.vecs.transactions.txid.len()));
|
||||
|
||||
let first: usize = first_txindex.into();
|
||||
let next: usize = next_first_txindex.into();
|
||||
@@ -104,13 +100,13 @@ impl Query {
|
||||
return Err(Error::OutOfRange("Block height out of range".into()));
|
||||
}
|
||||
|
||||
let first_txindex = indexer.vecs.transactions.first_txindex.read_once(height)?;
|
||||
let first_txindex = indexer.vecs.transactions.first_txindex.collect_one(height).unwrap();
|
||||
let next_first_txindex = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.first_txindex
|
||||
.read_once(height.incremented())
|
||||
.unwrap_or_else(|_| TxIndex::from(indexer.vecs.transactions.txid.len()));
|
||||
.collect_one(height.incremented())
|
||||
.unwrap_or_else(|| TxIndex::from(indexer.vecs.transactions.txid.len()));
|
||||
|
||||
let first: usize = first_txindex.into();
|
||||
let next: usize = next_first_txindex.into();
|
||||
@@ -120,8 +116,8 @@ impl Query {
|
||||
return Err(Error::OutOfRange("Transaction index out of range".into()));
|
||||
}
|
||||
|
||||
let txindex = TxIndex::from(first + index);
|
||||
let txid = indexer.vecs.transactions.txid.iter()?.get_unwrap(txindex);
|
||||
let txindex = first + index;
|
||||
let txid = indexer.vecs.transactions.txid.reader().get(txindex);
|
||||
|
||||
Ok(txid)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user