From 000027fab8155406bff286108cbb55427cf10d2f Mon Sep 17 00:00:00 2001 From: nym21 Date: Mon, 23 Mar 2026 18:30:32 +0100 Subject: [PATCH] changelog: updated --- docs/CHANGELOG.md | 262 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 120aeedd3..1ada2c6f5 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,268 @@ All notable changes to the Bitcoin Research Kit (BRK) project will be documented > *This changelog was generated by Claude Code* +## [v0.2.1](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.2.1) - 2026-03-23 + +### Breaking Changes + +#### `brk_rpc` +- Made `corepc` the default feature — `brk_rpc` now uses the `brk-corepc-client` RPC backend by default instead of requiring explicit feature opt-in; users relying on `bitcoincore-rpc` must now explicitly enable it ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.1/crates/brk_rpc/Cargo.toml)) + +[View changes](https://github.com/bitcoinresearchkit/brk/compare/v0.2.0...v0.2.1) + +## [v0.2.0](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.2.0) - 2026-03-23 + +This is a major architectural release. The most significant changes are: + +1. **Self-contained, oracle-only pricing**: The computation pipeline no longer uses exchange APIs for price data. All prices are now derived on-chain via the `brk_oracle` crate from block 550,000 onward, with pre-computed historical prices embedded for earlier blocks. `brk_fetcher` remains as a crate but is no longer used by `brk_computer` or `brk_cli`. Bitcoin Core is now the only runtime dependency — the toolkit runs fully offline and produces deterministic, reproducible results. + +2. **Height-only storage**: All series now store only the per-block (height-indexed) vec on disk. Previously each series stored both a height vec and a date-indexed vec. All non-height resolutions (minute10 through year10, halving, epoch — 15 total, up from 8) are now computed lazily on demand from the height data using `LazyAggVec` with flat height-to-period mappings. This roughly halves on-disk vec count while nearly doubling the number of available resolutions. + +3. **Flat index architecture**: The old cascading index hierarchy (height → date → week → month → quarter → year → decade) is replaced by a flat system where every period type maps directly to Height. This eliminates intermediate stored mappings and enables sub-day resolutions (10min, 30min, 1h, 4h, 12h) that were previously impossible. + +4. **Profitability cohorts**: New UTXO bucketing by unrealized profit/loss percentage — 25 ranges from ">1000% in profit" to "90-100% in loss", plus 14 aggregate profit thresholds and 9 loss thresholds, powered by a 190K-bucket Fenwick tree for O(log N) per-block computation. + +As a consequence of height-only storage, temporal aggregation shifted from date-based (daily sum, daily last, daily cumulative) to **rolling windows** (24h, 1w, 1m, 1y) computed from height data using precomputed lookback start positions (`CachedWindowStarts`). Most series now expose a `block` value, `cumulative` sum, and `RollingComplete` (rolling sums + rolling averages + rolling distribution with min/max/median/percentiles per window) — all derived from the single height vec. + +Resolution data is served through a popularity-based caching layer: up to 256 height-source vecs are cached in memory with LRU eviction based on access frequency, while period-to-height index mappings are always cached since they're small and shared across all series. + +### Breaking Changes + +#### `brk_types` +- Renamed all `Address`/`Addresses` types to `Addr`/`Addrs` across the entire public API: `Address` → `Addr`, `AddressBytes` → `AddrBytes`, `AddressHash` → `AddrHash`, `AddressStats` → `AddrStats`, `AddressChainStats` → `AddrChainStats`, `AddressMempoolStats` → `AddrMempoolStats`, `AddressParam` → `AddrParam`, `AddressValidation` → `AddrValidation`, `AnyAddressIndex` → `AnyAddrIndex`, `FundedAddressData` → `FundedAddrData`, `EmptyAddressData` → `EmptyAddrData`, etc. ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/addr.rs)) +- Renamed all `Metric`/`Metrics` types to `Series`: `MetricParam` → `SeriesParam`, `MetricData` → `SeriesData`, `MetricOutput` → `SeriesOutput`, `MetricCount` → `SeriesCount`, `MetricSelection` → `SeriesSelection`, `MetricsPaginated` → `SeriesPaginated`, `MetricWithIndex` → `SeriesNameWithIndex` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/series_data.rs)) +- Renamed `DateIndex` to `Day1` and removed `DecadeIndex`, `WeekIndex`, `MonthIndex`, `QuarterIndex`, `SemesterIndex`, `YearIndex` — replaced with a comprehensive resolution system: `Minute10`, `Minute30`, `Hour1`, `Hour4`, `Hour12`, `Day1`, `Day3`, `Week1`, `Month1`, `Month3`, `Month6`, `Year1`, `Year10` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/day1.rs)) +- Renamed `DifficultyEpoch` to `Epoch` and `HalvingEpoch` to `Halving` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/epoch.rs)) +- Renamed `CentsUnsigned` to `Cents` and `CentsUnsignedCompact` to `CentsCompact` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/cents.rs)) +- Adopted snake_case for all module file names (e.g. `blockinfo` → `block_info`, `blocktimestamp` → `block_timestamp`, `feeratepercentiles` → `feerate_percentiles`, `txstatus` → `tx_status`, `poolslug` → `pool_slug`, etc.) + +#### `brk_computer` +- **All series now store height-indexed data only on disk** — previously each metric stored both a `height: EagerVec` and a `dateindex: EagerVec` (and sometimes cumulative/sum variants at each level). Now `PerBlock` has `height: EagerVec` + `resolutions: Box>` where all 15 resolutions are `LazyAggVec` instances computed on demand. This roughly halves the on-disk vec count per series ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/internal/per_block/computed/base.rs)) +- **Replaced cascading index hierarchy with flat height-to-period mappings** — old system chained height→dateindex→weekindex→monthindex→yearindex→decadeindex; new system maps every period type directly to Height via `EagerIndexes`, enabling all resolutions to derive from height data without intermediate stored vecs ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/indexes/mod.rs)) +- Restructured `internal/` SDK from `single`/`multi` hierarchy to concept-oriented modules: `per_block/`, `per_tx/`, `algo/`, `transform/`, `containers/`, `indexes/` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/internal/mod.rs)) +- Moved `blocks/mining/` and `blocks/rewards/` into a dedicated top-level `mining/` module with `rewards/` and `hashrate/` sub-modules ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/mining/mod.rs)) +- Moved `market/indicators/` to a top-level `indicators/` module with expanded scope ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/indicators/mod.rs)) +- Renamed `price` module to `prices` with restructured sub-modules: `by_unit.rs` (multi-currency structs), `ohlcs.rs` (OHLC aggregation), `compute.rs` (oracle-based price computation) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/prices/mod.rs)) +- Renamed `cointime/pricing` to `cointime/prices` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/cointime/prices/mod.rs)) +- Renamed `distribution/address` to `distribution/addr` and `distribution/cohorts/address` to `distribution/cohorts/addr` +- Replaced all `Clone`-derived `Vecs` structs with generic `StorageMode` parameter (`Vecs`) across every computation module (blocks, transactions, market, distribution, supply, etc.) for type-safe read-only sharing +- Removed `brk_fetcher` dependency — price computation is now fully on-chain via the oracle, eliminating exchange API calls (Binance, Kraken) and the 12-hour retry/HAR-import fallback logic +- Removed `traits/` module (pricing traits) and `utils.rs` +- `Computer::forced_import` no longer accepts a `Fetcher` parameter — signature simplified from `(path, indexer, fetcher)` to `(path, indexer)` +- Restructured all market sub-modules with new type-safe containers replacing ad-hoc naming: `price_1w_sma` → `sma._1w`, `price_ath` → `high`, `price_drawdown` → `drawdown`, `price_returns` → `periods`, `price_ago` → `price_past`, etc. +- Restructured ATH vecs: `price_ath` → `high.cents`, `price_drawdown` → `drawdown`, `days_since_price_ath` → `days_since`, `max_days_between_price_aths` → `max_days_between` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/market/ath/vecs.rs)) +- Restructured DCA vecs: split into `PeriodVecs` (stack, cost_basis, return, cagr, lump_sum) and `ClassVecs` (stack, cost_basis, return), removing explicit days-in-profit/loss and min/max return fields ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/market/dca/vecs.rs)) +- Restructured volatility vecs: replaced individual `price_Xw_volatility`, `sharpe_Xw`, `sortino_Xw` fields with `Windows>` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/market/volatility/vecs.rs)) +- Restructured returns vecs: replaced individual period fields with `ByLookbackPeriod`, added `sd_24h: Windows` replacing explicit 1w/1m/1y standard deviation and downside fields ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/market/returns/vecs.rs)) +- Restructured range vecs: replaced 8 individual min/max price fields with `PriceMinMaxVecs` containing `min`/`max` groups, and added choppiness index as `PercentPerBlock` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/market/range/vecs.rs)) +- Restructured moving average vecs: split into `SmaVecs` and `EmaVecs` using `PriceWithRatioPerBlock` for each period, added Mayer Multiple bands (`_200d_x2_4`, `_200d_x0_8`) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/market/moving_average/vecs.rs)) +- Restructured burned supply: merged `opreturn` and `unspendable` into single `total: AmountPerBlockCumulative` with inline computation ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/supply/burned/vecs.rs)) +- Restructured transaction volume: replaced `sent_sum`/`received_sum`/`annualized_volume` with single `transfer_volume: AmountPerBlockCumulativeRolling`, wrapped throughput metrics in `Windows` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/transactions/volume/vecs.rs)) +- Removed `distribution/compute/aggregates.rs` — aggregate computation moved into metric tiers +- Removed `distribution/range_map.rs` — range mapping moved to `brk_types::RangeMap` + +#### `brk_query` +- Renamed `address()`/`address_txids()`/`address_utxos()` methods to `addr()`/`addr_txids()`/`addr_utxos()` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_query/src/impl/addr.rs)) +- Renamed `metrics` query module to `series` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_query/src/impl/series.rs)) +- Removed `resolved.rs` — resolution handling moved inline + +#### `brk_server` +- Renamed `/api/address/*` routes and `AddressRoutes` trait to `AddrRoutes` (redirects preserved from old paths) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_server/src/api/addrs/mod.rs)) +- Renamed `/api/series/*` routes (previously `/api/metrics/*`) — legacy `/api/metrics/*` routes preserved as redirects ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_server/src/api/series/mod.rs)) +- Removed `brk_fetcher` dependency +- Removed `Client` from `AppState` — server no longer holds a direct RPC client reference + +#### `brk_client` +- Switched HTTP backend from `minreq` to `ureq` +- Removed `fetch_prices.rs` example + +#### `brk_fetcher` +- Switched HTTP backend from `minreq` to `ureq` + +#### `brk_rpc` +- Added `corepc` feature integrating `brk-corepc-client` and `brk-corepc-jsonrpc` as alternative RPC backends ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_rpc/Cargo.toml)) + +#### `brk_cohort` +- Renamed `AddressGroups` to `AddrGroups` with renamed fields: `ge_amount` → `over_amount`, `lt_amount` → `under_amount`, `ByGreatEqualAmount` → `OverAmount`, `ByLowerThanAmount` → `UnderAmount`, `ByAmountRange` → `AmountRange` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_cohort/src/addr.rs)) +- Renamed `ByAgeRange` to `AgeRange` with renamed fields: `up_to_1h` → `under_1h`, `from_15y` → `over_15y` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_cohort/src/age_range.rs)) +- Renamed file names from concatenated (`by_age_range.rs`, `by_amount_range.rs`) to snake_case (`age_range.rs`, `amount_range.rs`) + +### New Features + +#### `brk_computer` +- Added `indicators/` module computing on-chain indicators: Puell Multiple, RHODL Ratio, NVT Ratio, Thermocap Multiple, Supply-Adjusted CDD, Supply-Adjusted CYD, Supply-Adjusted Dormancy, Dormancy Flow, Stock-to-Flow, Seller Exhaustion Constant, and Gini coefficient ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/indicators/compute.rs)) +- Added `mining/` module with dedicated hashrate computations: hash rate with 1w/1m/2m/1y SMAs, hash rate ATH and drawdown, hash price and hash value per TH/s and PH/s, hash price/value minimums and rebound metrics ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/mining/hashrate/compute.rs)) +- Added `mining/rewards/` with coinbase rewards, subsidy, fee dominance, unclaimed rewards — each with block/cumulative/rolling views and sats/btc/usd units ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/mining/rewards/compute.rs)) +- Added `market/technical/` module implementing RSI with Stochastic RSI (RSI, StochRSI, K-line, D-line with configurable RMA/SMA periods) and MACD (fast/slow EMA, signal line, histogram) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/market/technical/rsi.rs)) +- Added Fenwick tree (Binary Indexed Tree) data structure supporting O(log N) point-update, prefix-sum, and multi-target kth walk-down queries ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/internal/algo/fenwick.rs)) +- Added `ExpandingPercentiles` tracker using Fenwick tree for O(log N) percentile queries with 0.1% resolution, supporting bulk-load initialization ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/internal/algo/expanding_percentiles.rs)) +- Added `CostBasisFenwick` — 4-field Fenwick tree (all_sats, sth_sats, all_usd, sth_usd) for per-block accurate cost basis percentiles, supply density queries (±5% of spot price), and profitability range computation across 25 ranges with all/STH splits ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/distribution/cohorts/utxo/fenwick.rs)) +- Added sliding distribution, sliding median, sliding window, and drawdown algorithms in `internal/algo/` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/internal/algo/mod.rs)) +- Added `Resolutions` — a `PerResolution` of 15 `LazyAggVec` instances that lazily derive all supported resolutions from a single height-indexed source vec, using flat height-to-period mappings and a "last value in period" aggregation strategy ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/internal/per_block/computed/resolutions.rs)) +- Added `DerivedResolutions` — doubly-lazy resolution system for `LazyPerBlock` that chains `UnaryTransform` on top of source resolutions, enabling zero-storage derived series at all 15 resolutions ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/internal/per_block/lazy/derived_resolutions.rs)) +- Added popularity-based resolution caching: `CachedVec` wrapping with a global budget of 256 slots, minimum 2 accesses before caching, and LRU eviction that replaces the least-accessed cached vec when a more popular one requests caching ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/internal/cache_budget.rs)) +- Added `prices/` module with `SplitByUnit` (open/high/low/close in USD/cents/sats), `OhlcByUnit`, and `PriceByUnit` structured types for multi-currency price access ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/prices/by_unit.rs)) +- Added `ProfitabilityMetrics` computing per-block supply, realized cap, unrealized PnL, and NUPL across 25 profitability ranges plus 14 profit thresholds and 9 loss thresholds, each with all/STH splits ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/distribution/metrics/profitability.rs)) +- Restructured distribution metrics into trait-based tiered system with `ActivityLike`, `RealizedLike`, `UnrealizedLike` trait hierarchies — each metric type has core/basic/minimal/full variants enabling flexible per-cohort metric composition ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/distribution/metrics/cohort/mod.rs)) +- Added `distribution/metrics/relative/` sub-module with 6 variants: `RelativeToAll`, `RelativeForAll`, `RelativeWithExtended`, `RelativeFull`, `RelativeExtendedOwnMarketCap`, `RelativeExtendedOwnPnl` for cohort-to-total ratio metrics ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/distribution/metrics/relative/mod.rs)) +- Added `distribution/addr/activity.rs` tracking per-block address activity counts (receiving, sending, reactivated, both) globally and per address type, with rolling averages ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/distribution/addr/activity.rs)) +- Added `distribution/addr/delta.rs` computing rolling address count deltas with change magnitude and basis-point rates ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/distribution/addr/delta.rs)) +- Added `distribution/state/pending.rs` with `PendingDelta`, `PendingCapDelta`, `PendingInvestorCapDelta` for batched cost basis state updates +- Added maturation tracking to age cohorts: `tick_tock_next_block` now returns `AgeRange` tracking how many sats mature from each age range into the next older one per block, stored as `matured: AgeRange` on `UTXOCohorts` with cumulative and rolling window views for all 21 age ranges ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/distribution/cohorts/utxo/tick_tock.rs)) +- Added `pools/major.rs` and `pools/minor.rs` separating major pools (with cumulative rolling rewards and dominance rolling windows) from minor pools (blocks mined with cumulative rolling and dominance ratio) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_computer/src/pools/major.rs)) +- Added `blocks/lookback.rs` for precomputed rolling window lookback start vectors used across all windowed computations +- Added `cache_budget.rs` system for managing memory cache allocation across vecs +- Added `tree.rs` example for inspecting the full series tree structure + +#### `brk_types` +- Added 11 new resolution index types expanding from 8 resolutions (day, week, month, quarter, semester, year, decade, difficulty epoch) to 15: `Minute10`, `Minute30`, `Hour1`, `Hour4`, `Hour12` (sub-day — entirely new), `Day3`, `Month3`, `Month6` (new intermediate periods), `Year10` (replaces decade), plus renamed `Day1` (was DateIndex), `Week1` (was WeekIndex), `Month1` (was MonthIndex), `Year1` (was YearIndex), `Halving` (was HalvingEpoch), `Epoch` (was DifficultyEpoch) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/hour1.rs)) +- Added `FromCoarser` trait enabling automatic derivation of finer-grained resolution data from coarser sources ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/from_coarser.rs)) +- Added basis points types: `BasisPoints16`, `BasisPoints32`, `BasisPointsSigned16`, `BasisPointsSigned32` for precision ratio/percentage storage without floating point ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/basis_points_32.rs)) +- Added `StoredI64` type for signed 64-bit stored values ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/stored_i64.rs)) +- Added `RangeIndex` and `RangeMap` types for range-based lookups ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/range_index.rs)) +- Added `SearchQuery` type for series full-text search ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/search_query.rs)) +- Added `SeriesInfo` type carrying metadata about each data series ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/series_info.rs)) +- Added `DataRange` as a dedicated type (previously inline) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_types/src/data_range.rs)) +- Added `pools-v2.json` with expanded mining pool identification data +- Added `SeriesList` and `SeriesName` types for typed series enumeration + +#### `brk_server` +- Added structured JSON error responses with RFC 9457-inspired format: `type` (error category), `code` (machine-readable), `message` (human-readable), `doc_url` (link to API docs) — covers all BRK error variants with proper HTTP status mapping ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_server/src/error.rs)) +- Added `X-Response-Time` header (in microseconds) on all responses for latency observability +- Added Vary header consolidation middleware merging duplicate Vary headers into a single comma-separated value +- Added custom panic handler extracting panic messages into structured JSON error responses instead of empty 500s +- Added `ContentEncoding` module with server-side content encoding negotiation (zstd > br > gzip > identity) and transparent pre-compression of cached responses via brotli, flate2, and zstd ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_server/src/extended/encoding.rs)) +- Added pre-compressed Brotli encoding for the Scalar API documentation viewer (`scalar.js.br`) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_server/src/api/scalar.js.br)) +- Extracted `finish_openapi()` and `generate_bindings()` as public functions for external use ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_server/src/lib.rs)) +- Made `ApiRoutes` trait public for external router composition + +#### `brk_query` +- Added `list.rs` example for enumerating all available series names ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_query/examples/list.rs)) + +#### `brk_cohort` +- Added `ProfitabilityRange` with 25 buckets from ">1000% in profit" to "90-100% in loss", with boundary prices computed dynamically from spot price via `compute_profitability_boundaries()` ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_cohort/src/profitability_range.rs)) +- Added `Profit` with 14 aggregate "at least X% profit" thresholds (prefix sums over ranges) and `Loss` with 9 aggregate "at least X% loss" thresholds (suffix sums over ranges) ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_cohort/src/profit.rs)) +- Added `AgeRange::from_array()` constructor for building age range structs from fixed-size arrays ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_cohort/src/age_range.rs)) +- Derived `Traversable` on `AddrGroups` via proc macro (previously manual `Traversable` impl on `AddressGroups`) + +#### `brk_traversable` +- Added `iter_any_visible()` method to the `Traversable` trait — allows structs to expose all vecs for disk operations while hiding some from the public series tree ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_traversable/src/lib.rs)) +- Added `Traversable` impls for `LazyAggVec`, `LazyDeltaVec`, `ReadOnlyCompressedVec`, `ReadOnlyRawVec` — enabling lazy and read-only vecs to appear in the series tree + +#### `brk_traversable_derive` +- Added `#[traversable(hidden)]` attribute at struct and field level — hidden structs return empty tree nodes and empty `iter_any_visible()` while still participating in `iter_any_exportable()` for disk I/O ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_traversable_derive/src/lib.rs)) +- Added automatic `ReadOnlyClone` derive generation — the proc macro now generates `impl ReadOnlyClone` alongside `impl Traversable`, mapping `Rw` to `Ro` storage mode for all fields with `StorageMode` parameters +- Added multi-level `wrap` paths (`#[traversable(wrap = "a/b")]`) for creating nested tree structure +- Preserved struct field declaration order in tree key ordering (previously normal and flattened fields were separated) + +#### `brk_oracle` +- Lowered `START_HEIGHT` from 575,000 to 550,000 — oracle begins computing 25,000 blocks earlier ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_oracle/src/lib.rs)) + +#### `brk_reader` +- Added timestamp-based pre-filtering in block decoding — blocks are skipped by header timestamp before computing block hash, avoiding expensive RPC calls for out-of-range blocks ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_reader/src/lib.rs)) +- Added `find_magic()` function with XOR-decoded sliding window for blk file scanning, replacing byte-by-byte loop +- Replaced batch-based block decoding pipeline (accumulated blocks, sleep-based backpressure) with direct `par_bridge()` streaming — simpler, no sleep delays + +#### `brk_bindgen` +- Added template-based pattern system with discriminator support — `try_detect_template()` handles suffix discriminators (e.g. `ratio_sd` vs `ratio_sd_4y`) and embedded discriminators (e.g. `ratio_pct99_bps` vs `ratio_pct1_bps`) for smarter client code generation ([source](https://github.com/bitcoinresearchkit/brk/blob/v0.2.0/crates/brk_bindgen/src/analysis/positions.rs)) +- Added two-pass field part analysis: first pass collects instance analyses bottom-up, second pass fills mixed-empty field parts using shortest leaf names +- Added `owned_expr()`, `disc_arg_expr()`, `template_expr()` to `LanguageSyntax` trait for language-specific discriminator formatting +- Fixed pattern normalization to only erase leaf types when all leaves share the same type (prevents incorrect genericization of mixed-type signatures) + +#### `brk_client` (Rust) +- Switched HTTP backend from `minreq` to `ureq` +- Removed `fetch_prices.rs` example + +#### `brk_client` (JavaScript) +- Added `tests/consistency.js` — verifies all series sharing the same index have the same length (catches stale state after reorg rollback) +- Upgraded `quickmatch` 0.3.1 → 0.4.0: expanded default separators (`_- :/`), added prefix indexing and compound word indexing (e.g. "hashrate" now matches "hash_rate"), added `minScore` threshold to reduce false positives, replaced per-match object allocation with pre-allocated `Uint32Array` scoring + +#### `brk_client` (Python) +- Added `DateSeriesData` subclass with date-aware methods (`.dates()`, `.date_items()`, `.to_date_dict()`) — date-based indexes return `DateSeriesData`, non-date indexes return `SeriesData` +- Added new API methods: `get_series_data()`, `get_series_latest()`, `get_series_len()`, `get_series_version()`, `date_to_index()` +- Added `DetailedSeriesCount` with `distinct_series`, `total_endpoints`, `lazy_endpoints`, `stored_endpoints` fields +- Added `ErrorDetail`/`ErrorBody` types matching the server's structured error responses +- Range parameters now accept `date` and `datetime` objects in addition to integers + +### Internal Changes + +#### `brk_computer` +- Rewrote the `internal/` SDK: replaced the `single`/`multi` hierarchy (160+ files with per-combination types like `lazy_binary_computed_full`, `value_lazy_sum_cum`, `ComputedFromHeightAndDateLast`, `ComputedFromHeightSumCum`) with a composable system organized by concept (`per_block/`, `per_tx/`, `algo/`, `transform/`, `containers/`, `indexes/`). Concrete example: block count went from ~15 on-disk vecs (`ComputedFromHeightSumCum` + 4 rolling start vecs + 4 `ComputedFromHeightLast`) down to ~2 on-disk vecs (`PerBlockCumulativeRolling`) with all resolutions lazy +- Added `UnaryTransform` trait system in `internal/transform/` replacing ad-hoc closures: `arithmetic.rs`, `bps.rs`, `currency.rs`, `derived.rs`, `ratio.rs`, `specialized.rs` +- Added container types in `internal/containers/`: `per_resolution`, `windows`, `windows_from_1w`, `windows_to_1m`, `window_24h`, `distribution_stats`, `constant`, `percent` +- Added per-block type variants: `PerBlock`, `PerBlockFull`, `PerBlockCumulative`, `PerBlockCumulativeWithSums`, `PerBlockRolling`, `PerBlockAggregated`, `LazyPerBlock`, `LazyPerBlockRolling`, plus `AmountPerBlock`, `AmountPerBlockCumulative`, `AmountPerBlockCumulativeRolling`, `AmountPerBlockWithDeltas`, `FiatPerBlock`, `PercentPerBlock`, `RatioPerBlock`, `PerBlockRollingAverage`, `PercentRollingWindows`, `PriceWithRatioPerBlock`, `StdDevPerBlock` +- Added rolling types: `RollingComplete`, `LazyRollingComplete`, `RollingDistribution`, `LazyRollingSums`, `LazyRollingDeltasFromHeight` +- Added per-tx types: `PerTxDerived`, `PerTxDistribution`, `LazyPerTxDerived`, `LazyPerTxDistribution`, `LazyPerTxDistributionTransformed` +- Added eager/lazy index helpers in `internal/indexes/` +- Introduced `CachedWindowStarts` for shared precomputed lookback window start positions across all modules +- Split distribution UTXO cohort vecs into `core.rs`, `minimal.rs`, `type.rs` sub-modules for tiered storage +- Added `sum_others` macro in distribution metrics for computing aggregate cohort fields by summing constituent cohorts +- Removed `brk_fetcher` dependency — oracle prices are computed directly in the `prices/` module +- Removed `distribution/compute/aggregates.rs` — aggregate computation replaced by `compute_from_stateful` / `compute_sum_of_others` within each metric tier + +#### `brk_indexer` +- Bumped reindex version 24 → 25 (forces full reindex on upgrade) +- Added `StorageMode` generic parameter on `Indexer` and `Vecs` with `ReadOnlyClone` impl producing `Indexer` for type-safe read-only sharing +- Parallelized block processing pipeline: inputs and outputs now processed in parallel via `rayon::join`, finalization of outputs+inputs runs in parallel with tx metadata storage +- Added `BlockBuffers` struct with reusable `FxHashMap`/`FxHashSet` allocations cleared per block, eliminating per-block allocation overhead +- Added `AddrTypeVecs` and `ScriptTypeVecs` generic sub-structs for uniform per-type vec organization, replacing individually named fields +- Added `TxMetadataVecs` sub-struct with `split_for_finalize()` for separating tx metadata vecs from index vecs during parallel finalization +- Added `AddrReaders` with `script_pubkey(&self, output_type, type_index) -> ScriptBuf` for typed address-to-script lookup +- Block size and weight now computed from pre-computed `ComputedTx.base_size`/`total_size` fields instead of re-serializing transactions +- Removed 512MB thread stack size workaround — main function runs directly +- Added `schemars` and `serde` dependencies for OpenAPI-compatible schema generation + +#### `brk_server` +- Applied `NormalizePathLayer` as an outer wrapping layer (via `ServiceExt`) instead of an inner router layer, fixing route matching for trailing slashes +- Reduced in-memory response cache from 5,000 to 1,000 entries +- Moved `CatchPanicLayer` after compression in the middleware stack with a custom handler +- Restructured response caching to include content encoding in cache keys, pre-compressing responses per-encoding for cache-friendly serving +- Added `brotli`, `flate2`, and `zstd` dependencies for server-side compression +- Added `color-eyre` for panic reporting + +#### `brk_query` +- Removed thread stack-size workaround in the query example — main function now runs directly +- Added `parking_lot` and `serde_json` dependencies + +#### `brk_rpc` +- Added `serde` and `serde_json` dependencies for `corepc` feature + +#### `brk_store` +- Removed `insert_if_needed()` and `remove_if_needed()` — callers now use plain `insert()`/`remove()` +- Changed `clear_caches()` to drop allocations entirely (`FxHashMap::default()`) instead of clearing in place + +#### `brk_reader` +- Removed batch-based block decoding pipeline — simplified to streaming `par_bridge()` +- Removed `AnyBlock` enum, replaced with `decode_block()` standalone function +- Added `find_magic()` with XOR-decoded sliding window for efficient blk file scanning + +#### `brk_logger` +- Replaced `EnvFilter` with `Targets` for simpler log filter configuration +- Separated `LOG` (default level) from `RUST_LOG` (full directive control) environment variables +- Added `corepc=off` to default filter list + +#### `brk_error` +- Added `brk-corepc-client` and `ureq` error conversions, removed `minreq` error conversions + +#### `brk_cli` +- Removed `--fetch` CLI flag and `brk_fetcher` dependency — price fetching handled by the oracle +- Removed 512MB thread stack size workaround + +#### `docker` +- Switched base image from `rustlang/rust:nightly` to `rust:1.93-bookworm` (stable, pinned) +- Replaced `pgrep + nc` healthcheck with `curl -sf http://localhost:3110/health` +- Removed `docker-build.sh` helper script and docker-specific `.dockerignore` +- Removed all `environment:` variables from `docker-compose.yml` — configuration now via `command:` args only + +#### `scripts` +- Added `pool_major_threshold.py` — utility to determine major vs minor pool classification based on rolling dominance thresholds across multiple time windows + +#### `workspace` +- Upgraded Rust toolchain to edition 2024 +- Updated `.dockerignore` to exclude `docker/` directory + +[View changes](https://github.com/bitcoinresearchkit/brk/compare/v0.1.9...v0.2.0) + ## [v0.1.9](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.1.9) - 2026-02-13 ### New Features