global: snapshot

This commit is contained in:
nym21
2025-10-24 12:04:10 +02:00
parent 4f1653b086
commit 1e4acfe124
30 changed files with 200 additions and 139 deletions

View File

@@ -20,14 +20,17 @@ full = [
"fetcher",
"grouper",
"indexer",
"interface",
"iterator",
"logger",
"mcp",
"parser",
"monitor",
"query",
"reader",
"rpc",
"server",
"store",
"types",
"traversable",
"types",
]
binder = ["brk_binder"]
bundler = ["brk_bundler"]
@@ -37,14 +40,17 @@ error = ["brk_error"]
fetcher = ["brk_fetcher"]
grouper = ["brk_grouper"]
indexer = ["brk_indexer"]
interface = ["brk_query"]
iterator = ["brk_iterator"]
logger = ["brk_logger"]
mcp = ["brk_mcp"]
parser = ["brk_reader"]
monitor = ["brk_monitor"]
query = ["brk_query"]
reader = ["brk_reader"]
rpc = ["brk_rpc"]
server = ["brk_server"]
store = ["brk_store"]
types = ["brk_types"]
traversable = ["brk_traversable"]
types = ["brk_types"]
[dependencies]
brk_binder = { workspace = true, optional = true }
@@ -55,14 +61,17 @@ brk_error = { workspace = true, optional = true }
brk_fetcher = { workspace = true, optional = true }
brk_grouper = { workspace = true, optional = true }
brk_indexer = { workspace = true, optional = true }
brk_query = { workspace = true, optional = true }
brk_iterator = { workspace = true, optional = true }
brk_logger = { workspace = true, optional = true }
brk_mcp = { workspace = true, optional = true }
brk_monitor = { workspace = true, optional = true }
brk_query = { workspace = true, optional = true }
brk_reader = { workspace = true, optional = true }
brk_rpc = { workspace = true, optional = true }
brk_server = { workspace = true, optional = true }
brk_store = { workspace = true, optional = true }
brk_types = { workspace = true, optional = true }
brk_traversable = { workspace = true, optional = true }
brk_types = { workspace = true, optional = true }
[package.metadata.docs.rs]
all-features = true

View File

@@ -32,9 +32,9 @@ pub use brk_grouper as grouper;
#[doc(inline)]
pub use brk_indexer as indexer;
#[cfg(feature = "interface")]
#[cfg(feature = "iterator")]
#[doc(inline)]
pub use brk_query as interface;
pub use brk_query as iterator;
#[cfg(feature = "logger")]
#[doc(inline)]
@@ -44,9 +44,21 @@ pub use brk_logger as logger;
#[doc(inline)]
pub use brk_mcp as mcp;
#[cfg(feature = "parser")]
#[cfg(feature = "monitor")]
#[doc(inline)]
pub use brk_reader as parser;
pub use brk_monitor as monitor;
#[cfg(feature = "query")]
#[doc(inline)]
pub use brk_query as query;
#[cfg(feature = "reader")]
#[doc(inline)]
pub use brk_reader as reader;
#[cfg(feature = "rpc")]
#[doc(inline)]
pub use brk_rpc as reader;
#[cfg(feature = "server")]
#[doc(inline)]
@@ -56,10 +68,10 @@ pub use brk_server as server;
#[doc(inline)]
pub use brk_store as store;
#[cfg(feature = "types")]
#[doc(inline)]
pub use brk_types as types;
#[cfg(feature = "traversable")]
#[doc(inline)]
pub use brk_traversable as traversable;
#[cfg(feature = "types")]
#[doc(inline)]
pub use brk_types as types;

View File

@@ -134,13 +134,13 @@ pub fn run() -> color_eyre::Result<()> {
info!("{} blocks found.", block_count + 1);
let starting_indexes = indexer
.index(&reader, rpc, &exit, config.check_collisions())
.unwrap();
let starting_indexes = if config.check_collisions() {
indexer.checked_index(&reader, rpc, &exit)?;
} else {
indexer.index(&reader, rpc, &exit)?;
};
computer
.compute(&indexer, starting_indexes, &reader, &exit)
.unwrap();
computer.compute(&indexer, starting_indexes, &reader, &exit)?;
info!("Waiting for new blocks...");

View File

@@ -16,11 +16,13 @@ brk_error = { workspace = true }
brk_fetcher = { workspace = true }
brk_grouper = { workspace = true }
brk_indexer = { workspace = true }
brk_iterator = { workspace = true }
brk_logger = { workspace = true }
brk_reader = { workspace = true }
brk_rpc = { workspace = true }
brk_store = { workspace = true }
brk_types = { workspace = true }
brk_traversable = { workspace = true }
brk_types = { workspace = true }
derive_deref = { workspace = true }
log = { workspace = true }
pco = "0.4.7"

View File

@@ -8,7 +8,9 @@ use brk_computer::Computer;
use brk_error::Result;
use brk_fetcher::Fetcher;
use brk_indexer::Indexer;
use brk_iterator::Blocks;
use brk_reader::Reader;
use brk_rpc::{Auth, Client};
use vecdb::Exit;
pub fn main() -> Result<()> {
@@ -20,10 +22,22 @@ pub fn main() -> Result<()> {
.join("Bitcoin");
// let bitcoin_dir = Path::new("/Volumes/WD_BLACK/bitcoin");
let rpc = Box::leak(Box::new(bitcoincore_rpc::Client::new(
let client = Client::new(
"http://localhost:8332",
bitcoincore_rpc::Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?));
Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?;
let reader = Reader::new(bitcoin_dir.join("blocks"), &client);
let blocks = Blocks::new(&client, &reader);
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
// let outputs_dir = Path::new("../../_outputs");
let mut indexer = Indexer::forced_import(&outputs_dir)?;
let fetcher = Fetcher::import(true, None)?;
let exit = Exit::new();
exit.set_ctrlc_handler();
@@ -31,20 +45,11 @@ pub fn main() -> Result<()> {
thread::Builder::new()
.stack_size(256 * 1024 * 1024)
.spawn(move || -> Result<()> {
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
// let outputs_dir = Path::new("../../_outputs");
let reader = Reader::new(bitcoin_dir.join("blocks"), rpc);
let mut indexer = Indexer::forced_import(&outputs_dir)?;
let fetcher = Fetcher::import(true, None)?;
let mut computer = Computer::forced_import(&outputs_dir, &indexer, Some(fetcher))?;
loop {
let i = Instant::now();
let starting_indexes = indexer.index(&reader, rpc, &exit, true)?;
let starting_indexes = indexer.checked_index(&blocks, &client, &exit)?;
computer.compute(&indexer, starting_indexes, &reader, &exit)?;
dbg!(i.elapsed());
sleep(Duration::from_secs(10));

View File

@@ -161,7 +161,7 @@ impl Vecs {
let txinindex_to_value = LazyVecFrom2::init(
"value",
version + Version::ZERO,
indexer.vecs.txinindex_to_txoutindex.boxed_clone(),
indexes.txinindex_to_txoutindex.boxed_clone(),
indexer.vecs.txoutindex_to_value.boxed_clone(),
|index: TxInIndex, txinindex_to_txoutindex_iter, txoutindex_to_value_iter| {
txinindex_to_txoutindex_iter.next_at(index.to_usize()).map(
@@ -224,7 +224,7 @@ impl Vecs {
let txindex_to_is_coinbase = LazyVecFrom2::init(
"is_coinbase",
version + Version::ZERO,
indexes.txindex_to_height.boxed_clone(),
indexer.vecs.txindex_to_height.boxed_clone(),
indexer.vecs.height_to_first_txindex.boxed_clone(),
|index: TxIndex, txindex_to_height_iter, height_to_first_txindex_iter| {
txindex_to_height_iter

View File

@@ -233,10 +233,6 @@ impl Computer {
Ok(())
}
pub fn static_clone(&self) -> &'static Self {
Box::leak(Box::new(self.clone()))
}
}
// pub fn generate_allocation_files(monitored: &pools::Vecs) -> Result<()> {

View File

@@ -542,7 +542,8 @@ impl Vecs {
let height_to_first_p2wshaddressindex = &indexer.vecs.height_to_first_p2wshaddressindex;
let height_to_output_count = chain.indexes_to_output_count.height.unwrap_sum();
let height_to_input_count = chain.indexes_to_input_count.height.unwrap_sum();
let txinindex_to_txoutindex = &indexer.vecs.txinindex_to_txoutindex;
let txinindex_to_outpoint = &indexer.vecs.txinindex_to_outpoint;
let txindex_to_first_txoutindex = &indexer.vecs.txindex_to_first_txoutindex;
let txoutindex_to_value = &indexer.vecs.txoutindex_to_value;
let txindex_to_height = &indexer.vecs.txindex_to_height;
let height_to_timestamp_fixed = &indexes.height_to_timestamp_fixed;
@@ -582,9 +583,10 @@ impl Vecs {
+ height_to_timestamp_fixed.version()
+ height_to_output_count.version()
+ height_to_input_count.version()
+ txinindex_to_txoutindex.version()
+ txinindex_to_outpoint.version()
+ txoutindex_to_value.version()
+ txindex_to_height.version()
+ txindex_to_first_txoutindex.version()
+ txoutindex_to_txindex.version()
+ txoutindex_to_outputtype.version()
+ txoutindex_to_typeindex.version()
@@ -790,7 +792,8 @@ impl Vecs {
starting_indexes.update_from_height(starting_height, indexes);
let txinindex_to_txoutindex_reader = txinindex_to_txoutindex.create_reader();
let txinindex_to_outpoint_reader = txinindex_to_outpoint.create_reader();
let txindex_to_first_txoutindex_reader = txindex_to_first_txoutindex.create_reader();
let txoutindex_to_value_reader = txoutindex_to_value.create_reader();
let txoutindex_to_outputtype_reader = txoutindex_to_outputtype.create_reader();
let txoutindex_to_typeindex_reader = txoutindex_to_typeindex.create_reader();
@@ -1029,8 +1032,9 @@ impl Vecs {
.into_par_iter()
.map(TxInIndex::from)
.map(|txinindex| {
let txoutindex =
txinindex_to_txoutindex.unwrap_read(txinindex, &txinindex_to_txoutindex_reader);
let outpoint = txinindex_to_outpoint.unwrap_read(txinindex, &txinindex_to_outpoint_reader);
let txoutindex = txindex_to_first_txoutindex.unwrap_read(outpoint.txindex(), &txindex_to_first_txoutindex_reader) + outpoint.vout();
let value = txoutindex_to_value
.unwrap_read(txoutindex, &txoutindex_to_value_reader);
@@ -2005,7 +2009,7 @@ impl HeightToAddressTypeToVec<(TypeIndex, Sats)> {
let amount = prev_amount.checked_sub(value).unwrap();
let will_be_empty = addressdata.utxo_count - 1 == 0;
let will_be_empty = addressdata.has_1_utxos();
if will_be_empty
|| vecs.amount_range.get_mut(amount).0.clone()

View File

@@ -44,14 +44,14 @@ impl AddressCohortState {
let prev_realized_price = compute_price.then(|| addressdata.realized_price());
let prev_supply_state = SupplyState {
utxo_count: addressdata.utxo_count as u64,
utxo_count: addressdata.utxo_count() as u64,
value: addressdata.balance(),
};
addressdata.send(value, prev_price)?;
let supply_state = SupplyState {
utxo_count: addressdata.utxo_count as u64,
utxo_count: addressdata.utxo_count() as u64,
value: addressdata.balance(),
};
@@ -82,14 +82,14 @@ impl AddressCohortState {
let prev_realized_price = compute_price.then(|| address_data.realized_price());
let prev_supply_state = SupplyState {
utxo_count: address_data.utxo_count as u64,
utxo_count: address_data.utxo_count() as u64,
value: address_data.balance(),
};
address_data.receive(value, price);
let supply_state = SupplyState {
utxo_count: address_data.utxo_count as u64,
utxo_count: address_data.utxo_count() as u64,
value: address_data.balance(),
};

View File

@@ -43,7 +43,7 @@ impl SubAssign<&SupplyState> for SupplyState {
impl From<&LoadedAddressData> for SupplyState {
fn from(value: &LoadedAddressData) -> Self {
Self {
utxo_count: value.utxo_count as u64,
utxo_count: value.utxo_count() as u64,
value: value.balance(),
}
}

View File

@@ -30,20 +30,14 @@ fn main() -> Result<()> {
Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?;
let reader = Reader::new(bitcoin_dir.join("blocks"), client.clone());
let reader = Reader::new(bitcoin_dir.join("blocks"), &client);
let blocks = Blocks::new(client.clone(), reader);
let blocks = Blocks::new(&client, &reader);
fs::create_dir_all(&outputs_dir)?;
let mut indexer = Indexer::forced_import(&outputs_dir)?;
// 44
// let vecs = indexer.vecs.iter_any_collectable().collect::<Vec<_>>();
// dbg!(indexer.vecs.to_tree_node());
// dbg!(vecs.len());
// std::process::exit(0);
let exit = Exit::new();
exit.set_ctrlc_handler();

View File

@@ -812,10 +812,6 @@ impl Indexer {
Ok(starting_indexes)
}
pub fn static_clone(&self) -> &'static Self {
Box::leak(Box::new(self.clone()))
}
}
#[derive(Debug)]

View File

@@ -17,9 +17,9 @@ fn main() -> Result<()> {
Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?;
let reader = Reader::new(bitcoin_dir.join("blocks"), client.clone());
let reader = Reader::new(bitcoin_dir.join("blocks"), &client);
let blocks = Blocks::new(client, reader);
let blocks = Blocks::new(&client, &reader);
let i = Instant::now();
blocks

View File

@@ -28,18 +28,25 @@ pub struct Blocks(Arc<Source>);
impl Blocks {
/// Create with smart mode (auto-select source based on range size)
pub fn new(client: Client, reader: Reader) -> Self {
Self::new_inner(Source::Smart { client, reader })
pub fn new(client: &Client, reader: &Reader) -> Self {
Self::new_inner(Source::Smart {
client: client.clone(),
reader: reader.clone(),
})
}
/// Create with RPC-only mode
pub fn new_rpc(client: Client) -> Self {
Self::new_inner(Source::Rpc { client })
pub fn new_rpc(client: &Client) -> Self {
Self::new_inner(Source::Rpc {
client: client.clone(),
})
}
/// Create with Reader-only mode
pub fn new_reader(reader: Reader) -> Self {
Self::new_inner(Source::Reader { reader })
pub fn new_reader(reader: &Reader) -> Self {
Self::new_inner(Source::Reader {
reader: reader.clone(),
})
}
fn new_inner(source: Source) -> Self {

View File

@@ -16,7 +16,7 @@ pub mod route;
#[derive(Clone)]
pub struct MCP {
query: &'static Query<'static>,
query: Query,
tool_router: ToolRouter<MCP>,
}
@@ -24,9 +24,9 @@ const VERSION: &str = env!("CARGO_PKG_VERSION");
#[tool_router]
impl MCP {
pub fn new(query: &'static Query<'static>) -> Self {
pub fn new(query: &Query) -> Self {
Self {
query,
query: query.clone(),
tool_router: Self::tool_router(),
}
}

View File

@@ -10,20 +10,21 @@ use log::info;
use crate::MCP;
pub trait MCPRoutes {
fn add_mcp_routes(self, query: &'static Query<'static>, mcp: bool) -> Self;
fn add_mcp_routes(self, query: &Query, mcp: bool) -> Self;
}
impl<T> MCPRoutes for ApiRouter<T>
where
T: Clone + Send + Sync + 'static,
{
fn add_mcp_routes(self, query: &'static Query<'static>, mcp: bool) -> Self {
fn add_mcp_routes(self, query: &Query, mcp: bool) -> Self {
if !mcp {
return self;
}
let query = query.clone();
let service = StreamableHttpService::new(
move || Ok(MCP::new(query)),
move || Ok(MCP::new(&query)),
LocalSessionManager::default().into(),
StreamableHttpServerConfig {
stateful_mode: false,

View File

@@ -15,8 +15,9 @@ brk_computer = { workspace = true }
brk_error = { workspace = true }
brk_indexer = { workspace = true }
brk_reader = { workspace = true }
brk_types = { workspace = true }
brk_rpc = { workspace = true }
brk_traversable = { workspace = true }
brk_types = { workspace = true }
derive_deref = { workspace = true }
# quickmatch = { path = "../../../quickmatch" }
quickmatch = "0.1.8"

View File

@@ -5,6 +5,7 @@ use brk_error::Result;
use brk_indexer::Indexer;
use brk_query::{Params, ParamsOpt, Query};
use brk_reader::Reader;
use brk_rpc::{Auth, Client};
use brk_types::Index;
use vecdb::Exit;
@@ -21,15 +22,18 @@ pub fn main() -> Result<()> {
fs::create_dir_all(&outputs_dir)?;
// let outputs_dir = Path::new("/Volumes/WD_BLACK1/brk");
let rpc = Box::leak(Box::new(bitcoincore_rpc::Client::new(
let client = Client::new(
"http://localhost:8332",
bitcoincore_rpc::Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?));
Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?;
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
// let outputs_dir = Path::new("../../_outputs");
let exit = Exit::new();
exit.set_ctrlc_handler();
let reader = Reader::new(blocks_dir, rpc);
let reader = Reader::new(blocks_dir, &client);
let indexer = Indexer::forced_import(&outputs_dir)?;

View File

@@ -4,7 +4,7 @@ use bitcoin::{Network, PublicKey, ScriptBuf};
use brk_error::{Error, Result};
use brk_types::{
Address, AddressBytes, AddressBytesHash, AddressChainStats, AddressMempoolStats, AddressStats,
AnyAddressDataIndexEnum, Bitcoin, OutputType,
AnyAddressDataIndexEnum, OutputType,
};
use vecdb::{AnyIterableVec, VecIterator};
@@ -31,7 +31,7 @@ pub fn get_address(Address { address }: Address, query: &Query) -> Result<Addres
let Ok(bytes) = AddressBytes::try_from((&script, type_)) else {
return Err(Error::Str("Failed to convert the address to bytes"));
};
let hash = AddressBytesHash::from((&bytes, type_));
let hash = AddressBytesHash::from(&bytes);
let Ok(Some(type_index)) = stores
.addressbyteshash_to_typeindex

View File

@@ -31,7 +31,7 @@ pub fn get_transaction_info(TxidPath { txid }: TxidPath, query: &Query) -> Resul
let txid = indexer.vecs.txindex_to_txid.iter().unwrap_get_inner(index);
let reader = query.parser();
let reader = query.reader();
let computer = query.computer();
let position = computer

View File

@@ -1,6 +1,6 @@
#![doc = include_str!("../README.md")]
use std::collections::BTreeMap;
use std::{collections::BTreeMap, sync::Arc};
use brk_computer::Computer;
use brk_error::Result;
@@ -30,31 +30,32 @@ use crate::{
vecs::{IndexToVec, MetricToVec},
};
#[allow(dead_code)]
pub struct Query<'a> {
vecs: Vecs<'a>,
parser: &'a Reader,
#[derive(Clone)]
pub struct Query(Arc<QueryInner<'static>>);
struct QueryInner<'a> {
vecs: &'a Vecs<'a>,
reader: Reader,
indexer: &'a Indexer,
computer: &'a Computer,
}
impl<'a> Query<'a> {
pub fn build(parser: &Reader, indexer: &Indexer, computer: &Computer) -> Self {
let reader = parser.static_clone();
let indexer = indexer.static_clone();
let computer = computer.static_clone();
let vecs = Vecs::build(indexer, computer);
impl Query {
pub fn build(reader: &Reader, indexer: &Indexer, computer: &Computer) -> Self {
let reader = reader.clone();
let indexer = Box::leak(Box::new(indexer.clone()));
let computer = Box::leak(Box::new(computer.clone()));
let vecs = Box::leak(Box::new(Vecs::build(indexer, computer)));
Self {
Self(Arc::new(QueryInner {
vecs,
parser: reader,
reader,
indexer,
computer,
}
}))
}
pub fn get_height(&self) -> Height {
Height::from(self.indexer.vecs.height_to_blockhash.stamp())
Height::from(self.indexer().vecs.height_to_blockhash.stamp())
}
pub fn get_address(&self, address: Address) -> Result<AddressStats> {
@@ -66,7 +67,7 @@ impl<'a> Query<'a> {
}
pub fn match_metric(&self, metric: &Metric, limit: Limit) -> Vec<&str> {
self.vecs.matches(metric, limit)
self.vecs().matches(metric, limit)
}
pub fn search_metric_with_index(
@@ -212,11 +213,11 @@ impl<'a> Query<'a> {
}
pub fn metric_to_index_to_vec(&self) -> &BTreeMap<&str, IndexToVec<'_>> {
&self.vecs.metric_to_index_to_vec
&self.vecs().metric_to_index_to_vec
}
pub fn index_to_metric_to_vec(&self) -> &BTreeMap<Index, MetricToVec<'_>> {
&self.vecs.index_to_metric_to_vec
&self.vecs().index_to_metric_to_vec
}
pub fn metric_count(&self) -> MetricCount {
@@ -227,42 +228,50 @@ impl<'a> Query<'a> {
}
pub fn distinct_metric_count(&self) -> usize {
self.vecs.distinct_metric_count
self.vecs().distinct_metric_count
}
pub fn total_metric_count(&self) -> usize {
self.vecs.total_metric_count
self.vecs().total_metric_count
}
pub fn get_indexes(&self) -> &[IndexInfo] {
&self.vecs.indexes
&self.vecs().indexes
}
pub fn get_metrics(&'static self, pagination: PaginationParam) -> PaginatedMetrics {
self.vecs.metrics(pagination)
pub fn get_metrics(&self, pagination: PaginationParam) -> PaginatedMetrics {
self.vecs().metrics(pagination)
}
pub fn get_metrics_catalog(&self) -> &TreeNode {
self.vecs.catalog()
self.vecs().catalog()
}
pub fn get_index_to_vecids(&self, paginated_index: PaginatedIndexParam) -> Vec<&str> {
self.vecs.index_to_ids(paginated_index)
self.vecs().index_to_ids(paginated_index)
}
pub fn metric_to_indexes(&self, metric: String) -> Option<&Vec<Index>> {
self.vecs.metric_to_indexes(metric)
self.vecs().metric_to_indexes(metric)
}
pub fn parser(&self) -> &Reader {
self.parser
#[inline]
pub fn reader(&self) -> &Reader {
&self.0.reader
}
#[inline]
pub fn indexer(&self) -> &Indexer {
self.indexer
self.0.indexer
}
#[inline]
pub fn computer(&self) -> &Computer {
self.computer
self.0.computer
}
#[inline]
pub fn vecs(&self) -> &'static Vecs<'static> {
self.0.vecs
}
}

View File

@@ -20,7 +20,7 @@ fn main() -> Result<()> {
let blocks_dir = bitcoin_dir.join("blocks");
let reader = Reader::new(blocks_dir, client);
let reader = Reader::new(blocks_dir, &client);
let start = None;
// let start = Some(916037_u32.into());

View File

@@ -46,8 +46,8 @@ const BOUND_CAP: usize = 50;
pub struct Reader(Arc<ReaderInner>);
impl Reader {
pub fn new(blocks_dir: PathBuf, client: Client) -> Self {
Self(Arc::new(ReaderInner::new(blocks_dir, client)))
pub fn new(blocks_dir: PathBuf, client: &Client) -> Self {
Self(Arc::new(ReaderInner::new(blocks_dir, client.clone())))
}
}

View File

@@ -47,6 +47,11 @@ impl Client {
self.call(|c| c.get_block(hash.into())).map_err(Into::into)
}
/// Returns the numbers of block in the longest chain.
pub fn get_block_count(&self) -> Result<u64> {
self.call(|c| c.get_block_count()).map_err(Into::into)
}
/// Returns the numbers of block in the longest chain.
pub fn get_last_height(&self) -> Result<Height> {
self.call(|c| c.get_block_count())

View File

@@ -17,10 +17,12 @@ brk_computer = { workspace = true }
brk_error = { workspace = true }
brk_fetcher = { workspace = true }
brk_indexer = { workspace = true }
brk_query = { workspace = true }
brk_iterator = { workspace = true }
brk_logger = { workspace = true }
brk_mcp = { workspace = true }
brk_query = { workspace = true }
brk_reader = { workspace = true }
brk_rpc = { workspace = true }
brk_types = { workspace = true }
brk_traversable = { workspace = true }
vecdb = { workspace = true }

View File

@@ -1,13 +1,14 @@
use std::{path::Path, thread::sleep, time::Duration};
use bitcoincore_rpc::RpcApi;
use brk_computer::Computer;
use brk_error::Result;
use brk_fetcher::Fetcher;
use brk_indexer::Indexer;
use brk_iterator::Blocks;
use brk_query::Query;
use brk_reader::Reader;
use brk_rpc::{Auth, Client};
use brk_server::Server;
use vecdb::Exit;
@@ -18,14 +19,14 @@ pub fn main() -> Result<()> {
let bitcoin_dir = Path::new("");
let rpc = Box::leak(Box::new(bitcoincore_rpc::Client::new(
let client = Client::new(
"http://localhost:8332",
bitcoincore_rpc::Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?));
let exit = Exit::new();
exit.set_ctrlc_handler();
Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?;
let reader = Reader::new(bitcoin_dir.join("blocks"), rpc);
let reader = Reader::new(bitcoin_dir.join("blocks"), &client);
let blocks = Blocks::new(&client, &reader);
let outputs_dir = Path::new("../../_outputs");
@@ -35,13 +36,16 @@ pub fn main() -> Result<()> {
let mut computer = Computer::forced_import(outputs_dir, &indexer, fetcher)?;
let exit = Exit::new();
exit.set_ctrlc_handler();
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()?
.block_on(async {
let query = Query::build(&reader, &indexer, &computer);
let server = Server::new(query, None);
let server = Server::new(&query, None);
let server = tokio::spawn(async move {
server.serve(true).await.unwrap();
@@ -49,13 +53,13 @@ pub fn main() -> Result<()> {
if process {
loop {
let block_count = rpc.get_block_count()?;
let last_height = client.get_last_height()?;
let starting_indexes = indexer.checked_index(&reader, rpc, &exit)?;
let starting_indexes = indexer.checked_index(&blocks, &client, &exit)?;
computer.compute(&indexer, starting_indexes, &reader, &exit)?;
while block_count == rpc.get_block_count()? {
while last_height == client.get_last_height()? {
sleep(Duration::from_secs(1))
}
}

View File

@@ -37,13 +37,13 @@ use crate::api::create_openapi;
#[derive(Clone)]
pub struct AppState {
query: &'static Query<'static>,
query: Query,
path: Option<PathBuf>,
cache: Arc<Cache<String, Bytes>>,
}
impl Deref for AppState {
type Target = &'static Query<'static>;
type Target = Query;
fn deref(&self) -> &Self::Target {
&self.query
}
@@ -54,9 +54,9 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub struct Server(AppState);
impl Server {
pub fn new(query: Query<'static>, files_path: Option<PathBuf>) -> Self {
pub fn new(query: &Query, files_path: Option<PathBuf>) -> Self {
Self(AppState {
query: Box::leak(Box::new(query)),
query: query.clone(),
path: files_path,
cache: Arc::new(Cache::new(5_000)),
})
@@ -106,7 +106,7 @@ impl Server {
let router = ApiRouter::new()
.add_api_routes()
.add_mcp_routes(state.query, mcp)
.add_mcp_routes(&state.query, mcp)
.add_files_routes(state.path.as_ref())
.route(
"/discord",

View File

@@ -15,4 +15,4 @@ proc-macro = true
[dependencies]
syn = "2.0"
quote = "1.0"
proc-macro2 = "1.0.102"
proc-macro2 = "1.0.103"

View File

@@ -49,6 +49,16 @@ impl LoadedAddressData {
self.balance() == Sats::ZERO
}
#[inline]
pub fn utxo_count(&self) -> u32 {
self.funded_txo_count - self.spent_txo_count
}
#[inline]
pub fn has_1_utxos(&self) -> bool {
self.utxo_count() == 1
}
#[inline]
pub fn has_0_utxos(&self) -> bool {
self.funded_txo_count == self.spent_txo_count

View File

@@ -23,7 +23,7 @@ use crate::{TxIndex, Vout};
JsonSchema,
Hash,
)]
pub struct OutPoint(pub u64);
pub struct OutPoint(u64);
impl OutPoint {
pub const COINBASE: Self = Self(u64::MAX);