mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
fmt: global
This commit is contained in:
@@ -167,11 +167,9 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
|
||||
|
||||
if endpoint.query_params.is_empty() {
|
||||
if endpoint.path_params.is_empty() {
|
||||
writeln!(output, " return self.{}('{}')", fetch_method, path)
|
||||
.unwrap();
|
||||
writeln!(output, " return self.{}('{}')", fetch_method, path).unwrap();
|
||||
} else {
|
||||
writeln!(output, " return self.{}(f'{}')", fetch_method, path)
|
||||
.unwrap();
|
||||
writeln!(output, " return self.{}(f'{}')", fetch_method, path).unwrap();
|
||||
}
|
||||
} else {
|
||||
writeln!(output, " params = []").unwrap();
|
||||
|
||||
@@ -197,8 +197,7 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
|
||||
.unwrap();
|
||||
writeln!(output, " }}").unwrap();
|
||||
} else {
|
||||
writeln!(output, " self.base.{}(&path)", fetch_method)
|
||||
.unwrap();
|
||||
writeln!(output, " self.base.{}(&path)", fetch_method).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,8 +12,8 @@ use brk_error::Result;
|
||||
use brk_reader::{Reader, XORBytes};
|
||||
use brk_rpc::Client;
|
||||
use brk_types::{BlockHash, Height};
|
||||
use parking_lot::RwLock;
|
||||
use fjall::PersistMode;
|
||||
use parking_lot::RwLock;
|
||||
use tracing::{debug, info};
|
||||
use vecdb::{
|
||||
Exit, RawDBError, ReadOnlyClone, ReadableVec, Ro, Rw, StorageMode, WritableVec, unlikely,
|
||||
@@ -87,11 +87,7 @@ impl Indexer {
|
||||
let stores = Stores::forced_import(&indexed_path, VERSION)?;
|
||||
info!("Imported stores in {:?}", i.elapsed());
|
||||
|
||||
let tip_blockhash = vecs
|
||||
.blocks
|
||||
.blockhash
|
||||
.collect_last()
|
||||
.unwrap_or_default();
|
||||
let tip_blockhash = vecs.blocks.blockhash.collect_last().unwrap_or_default();
|
||||
|
||||
Ok(Self {
|
||||
path: indexed_path.clone(),
|
||||
|
||||
@@ -48,16 +48,36 @@ impl Query {
|
||||
|
||||
// 7 range reads instead of count * 7 point reads
|
||||
let txids: Vec<Txid> = indexer.vecs.transactions.txid.collect_range_at(start, end);
|
||||
let heights: Vec<Height> = indexer.vecs.transactions.height.collect_range_at(start, end);
|
||||
let versions = indexer.vecs.transactions.tx_version.collect_range_at(start, end);
|
||||
let lock_times = indexer.vecs.transactions.raw_locktime.collect_range_at(start, end);
|
||||
let total_sizes = indexer.vecs.transactions.total_size.collect_range_at(start, end);
|
||||
let heights: Vec<Height> = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.height
|
||||
.collect_range_at(start, end);
|
||||
let versions = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.tx_version
|
||||
.collect_range_at(start, end);
|
||||
let lock_times = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.raw_locktime
|
||||
.collect_range_at(start, end);
|
||||
let total_sizes = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.total_size
|
||||
.collect_range_at(start, end);
|
||||
let first_txin_indices = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.first_txin_index
|
||||
.collect_range_at(start, end);
|
||||
let positions = indexer.vecs.transactions.position.collect_range_at(start, end);
|
||||
let positions = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.position
|
||||
.collect_range_at(start, end);
|
||||
|
||||
// Readers for prevout lookups (created once)
|
||||
let txid_reader = indexer.vecs.transactions.txid.reader();
|
||||
@@ -76,15 +96,16 @@ impl Query {
|
||||
let height = heights[i];
|
||||
|
||||
// Reuse block info if same height as previous tx
|
||||
let (block_hash, block_time) =
|
||||
if let Some((h, ref bh, bt)) = cached_block && h == height {
|
||||
(bh.clone(), bt)
|
||||
} else {
|
||||
let bh = indexer.vecs.blocks.blockhash.read_once(height)?;
|
||||
let bt = indexer.vecs.blocks.timestamp.collect_one(height).unwrap();
|
||||
cached_block = Some((height, bh.clone(), bt));
|
||||
(bh, bt)
|
||||
};
|
||||
let (block_hash, block_time) = if let Some((h, ref bh, bt)) = cached_block
|
||||
&& h == height
|
||||
{
|
||||
(bh.clone(), bt)
|
||||
} else {
|
||||
let bh = indexer.vecs.blocks.blockhash.read_once(height)?;
|
||||
let bt = indexer.vecs.blocks.timestamp.collect_one(height).unwrap();
|
||||
cached_block = Some((height, bh.clone(), bt));
|
||||
(bh, bt)
|
||||
};
|
||||
|
||||
// Decode raw transaction from blk file
|
||||
let buffer = reader.read_raw_bytes(positions[i], *total_sizes[i] as usize)?;
|
||||
@@ -117,8 +138,7 @@ impl Query {
|
||||
let prev_value = value_reader.get(usize::from(prev_txout_index));
|
||||
let prev_output_type: OutputType =
|
||||
output_type_reader.get(usize::from(prev_txout_index));
|
||||
let prev_type_index =
|
||||
type_index_reader.get(usize::from(prev_txout_index));
|
||||
let prev_type_index = type_index_reader.get(usize::from(prev_txout_index));
|
||||
let script_pubkey =
|
||||
addr_readers.script_pubkey(prev_output_type, prev_type_index);
|
||||
(
|
||||
|
||||
@@ -7,7 +7,14 @@ use crate::Query;
|
||||
impl Query {
|
||||
pub fn block_rewards(&self, time_period: TimePeriod) -> Result<Vec<BlockRewardsEntry>> {
|
||||
let bw = BlockWindow::new(self, time_period);
|
||||
let cumulative = &self.computer().mining.rewards.coinbase.cumulative.sats.height;
|
||||
let cumulative = &self
|
||||
.computer()
|
||||
.mining
|
||||
.rewards
|
||||
.coinbase
|
||||
.cumulative
|
||||
.sats
|
||||
.height;
|
||||
Ok(bw
|
||||
.cumulative_averages(self, cumulative)
|
||||
.into_iter()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use brk_types::{Cents, Dollars, Height, Sats, Timestamp, TimePeriod};
|
||||
use brk_types::{Cents, Dollars, Height, Sats, TimePeriod, Timestamp};
|
||||
use vecdb::{ReadableVec, VecIndex};
|
||||
|
||||
use crate::Query;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use brk_error::{Error, Result};
|
||||
use brk_types::{
|
||||
BlockInfoV1, Day1, Height, Pool, PoolBlockCounts, PoolBlockShares, PoolDetail,
|
||||
PoolDetailInfo, PoolHashrateEntry, PoolInfo, PoolSlug, PoolStats, PoolsSummary, StoredF64,
|
||||
StoredU64, TimePeriod, pools,
|
||||
BlockInfoV1, Day1, Height, Pool, PoolBlockCounts, PoolBlockShares, PoolDetail, PoolDetailInfo,
|
||||
PoolHashrateEntry, PoolInfo, PoolSlug, PoolStats, PoolsSummary, StoredF64, StoredU64,
|
||||
TimePeriod, pools,
|
||||
};
|
||||
use vecdb::{AnyVec, ReadableVec, VecIndex};
|
||||
|
||||
@@ -40,13 +40,29 @@ impl Query {
|
||||
// Use timestamp-based lookback for accurate time boundaries
|
||||
let lookback = &computer.blocks.lookback;
|
||||
let start = match time_period {
|
||||
TimePeriod::Day => lookback.cached_window_starts.0._24h.collect_one(current_height),
|
||||
TimePeriod::Day => lookback
|
||||
.cached_window_starts
|
||||
.0
|
||||
._24h
|
||||
.collect_one(current_height),
|
||||
TimePeriod::ThreeDays => lookback._3d.collect_one(current_height),
|
||||
TimePeriod::Week => lookback.cached_window_starts.0._1w.collect_one(current_height),
|
||||
TimePeriod::Month => lookback.cached_window_starts.0._1m.collect_one(current_height),
|
||||
TimePeriod::Week => lookback
|
||||
.cached_window_starts
|
||||
.0
|
||||
._1w
|
||||
.collect_one(current_height),
|
||||
TimePeriod::Month => lookback
|
||||
.cached_window_starts
|
||||
.0
|
||||
._1m
|
||||
.collect_one(current_height),
|
||||
TimePeriod::ThreeMonths => lookback._3m.collect_one(current_height),
|
||||
TimePeriod::SixMonths => lookback._6m.collect_one(current_height),
|
||||
TimePeriod::Year => lookback.cached_window_starts.0._1y.collect_one(current_height),
|
||||
TimePeriod::Year => lookback
|
||||
.cached_window_starts
|
||||
.0
|
||||
._1y
|
||||
.collect_one(current_height),
|
||||
TimePeriod::TwoYears => lookback._2y.collect_one(current_height),
|
||||
TimePeriod::ThreeYears => lookback._3y.collect_one(current_height),
|
||||
}
|
||||
@@ -107,7 +123,12 @@ impl Query {
|
||||
.collect();
|
||||
|
||||
let hashrate_at = |height: Height| -> u128 {
|
||||
let day = computer.indexes.height.day1.collect_one(height).unwrap_or_default();
|
||||
let day = computer
|
||||
.indexes
|
||||
.height
|
||||
.day1
|
||||
.collect_one(height)
|
||||
.unwrap_or_default();
|
||||
computer
|
||||
.mining
|
||||
.hashrate
|
||||
@@ -276,7 +297,10 @@ impl Query {
|
||||
let shared = self.hashrate_shared_data(0)?;
|
||||
let pool_cum = self.pool_daily_cumulative(slug, shared.start_day, shared.end_day)?;
|
||||
Ok(Self::compute_hashrate_entries(
|
||||
&shared, &pool_cum, &pool_name, SAMPLE_WEEKLY,
|
||||
&shared,
|
||||
&pool_cum,
|
||||
&pool_name,
|
||||
SAMPLE_WEEKLY,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -289,13 +313,29 @@ impl Query {
|
||||
let lookback = &self.computer().blocks.lookback;
|
||||
let current_height = self.height();
|
||||
match tp {
|
||||
TimePeriod::Day => lookback.cached_window_starts.0._24h.collect_one(current_height),
|
||||
TimePeriod::Day => lookback
|
||||
.cached_window_starts
|
||||
.0
|
||||
._24h
|
||||
.collect_one(current_height),
|
||||
TimePeriod::ThreeDays => lookback._3d.collect_one(current_height),
|
||||
TimePeriod::Week => lookback.cached_window_starts.0._1w.collect_one(current_height),
|
||||
TimePeriod::Month => lookback.cached_window_starts.0._1m.collect_one(current_height),
|
||||
TimePeriod::Week => lookback
|
||||
.cached_window_starts
|
||||
.0
|
||||
._1w
|
||||
.collect_one(current_height),
|
||||
TimePeriod::Month => lookback
|
||||
.cached_window_starts
|
||||
.0
|
||||
._1m
|
||||
.collect_one(current_height),
|
||||
TimePeriod::ThreeMonths => lookback._3m.collect_one(current_height),
|
||||
TimePeriod::SixMonths => lookback._6m.collect_one(current_height),
|
||||
TimePeriod::Year => lookback.cached_window_starts.0._1y.collect_one(current_height),
|
||||
TimePeriod::Year => lookback
|
||||
.cached_window_starts
|
||||
.0
|
||||
._1y
|
||||
.collect_one(current_height),
|
||||
TimePeriod::TwoYears => lookback._2y.collect_one(current_height),
|
||||
TimePeriod::ThreeYears => lookback._3y.collect_one(current_height),
|
||||
}
|
||||
@@ -378,13 +418,20 @@ impl Query {
|
||||
.pools
|
||||
.major
|
||||
.get(&slug)
|
||||
.map(|v| v.base.blocks_mined.cumulative.day1.collect_range_at(start_day, end_day))
|
||||
.map(|v| {
|
||||
v.base
|
||||
.blocks_mined
|
||||
.cumulative
|
||||
.day1
|
||||
.collect_range_at(start_day, end_day)
|
||||
})
|
||||
.or_else(|| {
|
||||
computer
|
||||
.pools
|
||||
.minor
|
||||
.get(&slug)
|
||||
.map(|v| v.blocks_mined.cumulative.day1.collect_range_at(start_day, end_day))
|
||||
computer.pools.minor.get(&slug).map(|v| {
|
||||
v.blocks_mined
|
||||
.cumulative
|
||||
.day1
|
||||
.collect_range_at(start_day, end_day)
|
||||
})
|
||||
})
|
||||
.ok_or_else(|| Error::NotFound("Pool not found".into()))
|
||||
}
|
||||
@@ -405,9 +452,7 @@ impl Query {
|
||||
let mut entries = Vec::new();
|
||||
let mut i = LOOKBACK_DAYS;
|
||||
while i < total {
|
||||
if let (Some(cum_now), Some(cum_prev)) =
|
||||
(pool_cum[i], pool_cum[i - LOOKBACK_DAYS])
|
||||
{
|
||||
if let (Some(cum_now), Some(cum_prev)) = (pool_cum[i], pool_cum[i - LOOKBACK_DAYS]) {
|
||||
let pool_blocks = (*cum_now).saturating_sub(*cum_prev);
|
||||
if pool_blocks > 0 {
|
||||
let h_now = shared.first_heights[i].to_usize();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use bitcoin::hex::DisplayHex;
|
||||
use brk_error::{Error, Result};
|
||||
use brk_types::{
|
||||
BlockHash, Height, MerkleProof, Timestamp, TxInIndex, TxIndex, TxOutspend, TxStatus,
|
||||
Transaction, Txid, TxidPrefix, Vin, Vout,
|
||||
BlockHash, Height, MerkleProof, Timestamp, Transaction, TxInIndex, TxIndex, TxOutspend,
|
||||
TxStatus, Txid, TxidPrefix, Vin, Vout,
|
||||
};
|
||||
use vecdb::{ReadableVec, VecIndex};
|
||||
|
||||
@@ -175,20 +175,20 @@ impl Query {
|
||||
let spending_tx_index = input_tx_cursor.get(usize::from(txin_index)).unwrap();
|
||||
let spending_first_txin_index =
|
||||
first_txin_cursor.get(spending_tx_index.to_usize()).unwrap();
|
||||
let vin =
|
||||
Vin::from(usize::from(txin_index) - usize::from(spending_first_txin_index));
|
||||
let vin = Vin::from(usize::from(txin_index) - usize::from(spending_first_txin_index));
|
||||
let spending_txid = txid_reader.get(spending_tx_index.to_usize());
|
||||
let spending_height = height_cursor.get(spending_tx_index.to_usize()).unwrap();
|
||||
|
||||
let (block_hash, block_time) =
|
||||
if let Some((h, ref bh, bt)) = cached_block && h == spending_height {
|
||||
(bh.clone(), bt)
|
||||
} else {
|
||||
let bh = indexer.vecs.blocks.blockhash.read_once(spending_height)?;
|
||||
let bt = block_ts_cursor.get(spending_height.to_usize()).unwrap();
|
||||
cached_block = Some((spending_height, bh.clone(), bt));
|
||||
(bh, bt)
|
||||
};
|
||||
let (block_hash, block_time) = if let Some((h, ref bh, bt)) = cached_block
|
||||
&& h == spending_height
|
||||
{
|
||||
(bh.clone(), bt)
|
||||
} else {
|
||||
let bh = indexer.vecs.blocks.blockhash.read_once(spending_height)?;
|
||||
let bt = block_ts_cursor.get(spending_height.to_usize()).unwrap();
|
||||
cached_block = Some((spending_height, bh.clone(), bt));
|
||||
(bh, bt)
|
||||
};
|
||||
|
||||
outspends.push(TxOutspend {
|
||||
spent: true,
|
||||
@@ -217,13 +217,25 @@ impl Query {
|
||||
|
||||
fn transaction_raw_by_index(&self, tx_index: TxIndex) -> Result<Vec<u8>> {
|
||||
let indexer = self.indexer();
|
||||
let total_size = indexer.vecs.transactions.total_size.collect_one(tx_index).unwrap();
|
||||
let position = indexer.vecs.transactions.position.collect_one(tx_index).unwrap();
|
||||
let total_size = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.total_size
|
||||
.collect_one(tx_index)
|
||||
.unwrap();
|
||||
let position = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.position
|
||||
.collect_one(tx_index)
|
||||
.unwrap();
|
||||
self.reader().read_raw_bytes(position, *total_size as usize)
|
||||
}
|
||||
|
||||
fn transaction_hex_by_index(&self, tx_index: TxIndex) -> Result<String> {
|
||||
Ok(self.transaction_raw_by_index(tx_index)?.to_lower_hex_string())
|
||||
Ok(self
|
||||
.transaction_raw_by_index(tx_index)?
|
||||
.to_lower_hex_string())
|
||||
}
|
||||
|
||||
pub fn resolve_tx(&self, txid: &Txid) -> Result<(TxIndex, Height)> {
|
||||
|
||||
@@ -4,7 +4,9 @@ use axum::{
|
||||
http::{HeaderMap, Uri},
|
||||
};
|
||||
use brk_query::BLOCK_TXS_PAGE_SIZE;
|
||||
use brk_types::{BlockInfo, BlockInfoV1, BlockStatus, BlockTimestamp, Transaction, TxIndex, Txid, Version};
|
||||
use brk_types::{
|
||||
BlockInfo, BlockInfoV1, BlockStatus, BlockTimestamp, Transaction, TxIndex, Txid, Version,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
AppState, CacheStrategy,
|
||||
|
||||
@@ -6,9 +6,7 @@ use axum::{
|
||||
use brk_types::{DifficultyAdjustment, HistoricalPrice, Prices, Timestamp};
|
||||
|
||||
use crate::{
|
||||
AppState, CacheStrategy,
|
||||
extended::TransformResponseExtended,
|
||||
params::OptionalTimestampParam,
|
||||
AppState, CacheStrategy, extended::TransformResponseExtended, params::OptionalTimestampParam,
|
||||
};
|
||||
|
||||
pub trait GeneralRoutes {
|
||||
|
||||
@@ -6,9 +6,8 @@ use axum::{
|
||||
routing::get,
|
||||
};
|
||||
use brk_types::{
|
||||
BlockFeesEntry, BlockInfoV1, BlockRewardsEntry, BlockSizesWeights,
|
||||
DifficultyAdjustmentEntry, HashrateSummary, PoolDetail, PoolHashrateEntry, PoolInfo,
|
||||
PoolsSummary, RewardStats,
|
||||
BlockFeesEntry, BlockInfoV1, BlockRewardsEntry, BlockSizesWeights, DifficultyAdjustmentEntry,
|
||||
HashrateSummary, PoolDetail, PoolHashrateEntry, PoolInfo, PoolsSummary, RewardStats,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
||||
@@ -216,6 +216,9 @@ mod tests {
|
||||
assert_eq!(raw[4], 0x00, "segwit marker");
|
||||
|
||||
let raw_txid = Block::hash_raw_tx(&raw, base_size);
|
||||
assert_eq!(raw_txid, expected_txid, "hash_raw_tx must match compute_txid");
|
||||
assert_eq!(
|
||||
raw_txid, expected_txid,
|
||||
"hash_raw_tx must match compute_txid"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,10 +44,10 @@ mod cents_signed;
|
||||
mod cents_squared_sats;
|
||||
mod cohort;
|
||||
mod coinbase_tag;
|
||||
mod cpfp;
|
||||
mod cost_basis_bucket;
|
||||
mod cost_basis_distribution;
|
||||
mod cost_basis_value;
|
||||
mod cpfp;
|
||||
mod data_range;
|
||||
mod data_range_format;
|
||||
mod date;
|
||||
@@ -76,8 +76,8 @@ mod hashrate_entry;
|
||||
mod hashrate_summary;
|
||||
mod health;
|
||||
mod height;
|
||||
mod historical_price;
|
||||
mod hex;
|
||||
mod historical_price;
|
||||
mod hour1;
|
||||
mod hour12;
|
||||
mod hour4;
|
||||
@@ -124,8 +124,8 @@ mod pagination_index;
|
||||
mod percentile;
|
||||
mod pool;
|
||||
mod pool_detail;
|
||||
mod pool_info;
|
||||
mod pool_hashrate_entry;
|
||||
mod pool_info;
|
||||
mod pool_slug;
|
||||
mod pool_stats;
|
||||
mod pools;
|
||||
@@ -234,10 +234,10 @@ pub use cents_signed::*;
|
||||
pub use cents_squared_sats::*;
|
||||
pub use cohort::*;
|
||||
pub use coinbase_tag::*;
|
||||
pub use cpfp::*;
|
||||
pub use cost_basis_bucket::*;
|
||||
pub use cost_basis_distribution::*;
|
||||
pub use cost_basis_value::*;
|
||||
pub use cpfp::*;
|
||||
pub use data_range::*;
|
||||
pub use data_range_format::*;
|
||||
pub use date::*;
|
||||
@@ -266,8 +266,8 @@ pub use hashrate_entry::*;
|
||||
pub use hashrate_summary::*;
|
||||
pub use health::*;
|
||||
pub use height::*;
|
||||
pub use historical_price::*;
|
||||
pub use hex::*;
|
||||
pub use historical_price::*;
|
||||
pub use hour1::*;
|
||||
pub use hour4::*;
|
||||
pub use hour12::*;
|
||||
@@ -314,8 +314,8 @@ pub use pagination_index::*;
|
||||
pub use percentile::*;
|
||||
pub use pool::*;
|
||||
pub use pool_detail::*;
|
||||
pub use pool_info::*;
|
||||
pub use pool_hashrate_entry::*;
|
||||
pub use pool_info::*;
|
||||
pub use pool_slug::*;
|
||||
pub use pool_stats::*;
|
||||
pub use pools::*;
|
||||
|
||||
@@ -67,8 +67,7 @@ impl Serialize for TxIn {
|
||||
// P2WSH: witness has >2 items, last is the witnessScript
|
||||
let inner_witness = if has_witness && !has_scriptsig && self.witness.len() > 2 {
|
||||
if let Some(last) = self.witness.last() {
|
||||
let bytes: Vec<u8> =
|
||||
bitcoin::hex::FromHex::from_hex(last).unwrap_or_default();
|
||||
let bytes: Vec<u8> = bitcoin::hex::FromHex::from_hex(last).unwrap_or_default();
|
||||
ScriptBuf::from(bytes).to_asm_string()
|
||||
} else {
|
||||
String::new()
|
||||
|
||||
Reference in New Issue
Block a user