mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-29 21:52:09 -07:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 10b496e845 | |||
| bbe7bf390d | |||
| 4777b3400a | |||
| acaa70e944 | |||
| 4049d694f7 | |||
| e155a3dacf | |||
| a224e4c4d8 | |||
| edaeda5424 | |||
| 09d974913d | |||
| f82edb290a | |||
| 3d8b33ae94 | |||
| 565ecbd436 | |||
| 3359dfcc29 | |||
| 1c2afd14dd | |||
| fe5343c1d6 | |||
| 08cfefc02a | |||
| f6d9332c48 | |||
| cc6913c854 | |||
| 8c75fbd0a4 | |||
| 0de6d62409 | |||
| 5ba7ce5b7c | |||
| e106d30852 | |||
| 30affc884b | |||
| 745717ea49 | |||
| 4efd98b758 | |||
| 36640e3710 | |||
| 311c4fd29d | |||
| f50374f983 | |||
| 82ceb7f021 | |||
| 0aba3bc1d8 | |||
| f6c984ff3c | |||
| 4091ab6b6c | |||
| fb9fd5b51a | |||
| 9389700a01 | |||
| 016c1b2233 |
+2
-5
@@ -4,7 +4,8 @@
|
|||||||
# Builds
|
# Builds
|
||||||
target
|
target
|
||||||
websites/dist
|
websites/dist
|
||||||
vecid-to-indexes.js
|
bridge/
|
||||||
|
/ids.txt
|
||||||
|
|
||||||
# Copies
|
# Copies
|
||||||
*\ copy*
|
*\ copy*
|
||||||
@@ -12,10 +13,6 @@ vecid-to-indexes.js
|
|||||||
# Ignored
|
# Ignored
|
||||||
_*
|
_*
|
||||||
|
|
||||||
# Editors
|
|
||||||
.vscode
|
|
||||||
.zed
|
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
.log
|
.log
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"file_scan_exclusions": [
|
||||||
|
// default
|
||||||
|
"**/.git",
|
||||||
|
"**/.svn",
|
||||||
|
"**/.hg",
|
||||||
|
"**/.jj",
|
||||||
|
"**/CVS",
|
||||||
|
"**/.DS_Store",
|
||||||
|
"**/Thumbs.db",
|
||||||
|
"**/.classpath",
|
||||||
|
"**/.settings",
|
||||||
|
// custom
|
||||||
|
"**/lean-qr/*/index.mjs",
|
||||||
|
"uFuzzy.mjs",
|
||||||
|
"lightweight-charts.standalone.production.mjs",
|
||||||
|
"**/modern-screenshot/*/index.mjs",
|
||||||
|
"**/solidjs-signals/*/dist/prod.js"
|
||||||
|
]
|
||||||
|
}
|
||||||
+21
-32
@@ -4,46 +4,35 @@
|
|||||||
|
|
||||||
All notable changes to the Bitcoin Research Kit (BRK) project will be documented in this file.
|
All notable changes to the Bitcoin Research Kit (BRK) project will be documented in this file.
|
||||||
|
|
||||||
## Unreleased
|
## [v0.0.89](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.0.89) - 2025-08-24
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
- **Enhanced**: Comprehensive rewrite of all crate README files for improved clarity and developer experience
|
- **Enhanced**: Comprehensive rewrite of all crate README files for improved clarity and developer experience across all workspace crates: [brk](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/crates/brk/README.md), [brk_bundler](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/crates/brk_bundler/README.md), [brk_computer](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/crates/brk_computer/README.md), [brk_cli](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/crates/brk_cli/README.md), [brk_error](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/crates/brk_error/README.md)
|
||||||
- **Updated**: Main project README with better structure and documentation
|
- **Updated**: Main project [README](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/README.md) with better structure and comprehensive architecture documentation
|
||||||
- **Standardized**: README format across all workspace crates with consistent styling
|
- **Standardized**: README format across all workspace crates with consistent styling and improved developer experience
|
||||||
- **Improved**: Documentation structure and organization across the entire project
|
- **Added**: More detailed descriptions for each crate's purpose and functionality with examples
|
||||||
- **Added**: More detailed descriptions for each crate's purpose and functionality
|
|
||||||
|
|
||||||
### Computer Module
|
### Computer Module - Major Refactoring
|
||||||
- **Refactored**: Converted ComputedFrom pattern to LazyFrom pattern for improved performance
|
- **Refactored**: Converted ComputedFrom pattern to [LazyFrom pattern](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/crates/brk_computer/src/grouped/builder_lazy.rs) for improved performance and memory efficiency
|
||||||
- **Added**: New LazyVecBuilder implementation for on-demand computation
|
- **Added**: New [LazyVecBuilder implementation](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/crates/brk_computer/src/grouped/builder_lazy.rs) for on-demand computation with support for first, average, sum, max, min, last, and cumulative operations
|
||||||
- **Restructured**: Computer module stateful operations with improved organization
|
- **Restructured**: Computer module [stateful operations](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/crates/brk_computer/src/stateful/mod.rs) with improved organization and rollback functionality
|
||||||
- **Cleaned**: Removed hardcoded format specifications, now using defaults
|
- **Enhanced**: [Address type organization](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/crates/brk_computer/src/stateful/addresstype/) into dedicated module structure
|
||||||
- **Optimized**: Vector storage operations with lazy computation patterns
|
- **Improved**: Stateful rollback functionality for better error recovery and blockchain reorganization handling
|
||||||
- **Refactored**: Address type handling in stateful computations
|
|
||||||
- **Reorganized**: Stateful module structure for better maintainability
|
|
||||||
- **Enhanced**: Builder patterns for grouped vector operations
|
|
||||||
- **Improved**: Memory efficiency through lazy computation strategies
|
|
||||||
|
|
||||||
### Vector Storage
|
### Data Structures
|
||||||
- **Enhanced**: Vector storage engine development workflow
|
- **Added**: New [StoredI16](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/crates/brk_structs/src/structs/stored_i16.rs) data type for efficient 16-bit signed integer storage with compression support
|
||||||
- **Optimized**: Lazy vector computation patterns for better performance
|
- **Enhanced**: StoredF32 with additional [utility methods](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/crates/brk_structs/src/structs/stored_f32.rs) for mathematical operations
|
||||||
- **Improved**: Vector builder architecture with lazy evaluation
|
|
||||||
|
|
||||||
### Dependencies
|
### Website Frontend
|
||||||
- **Updated**: Rayon from 1.10.0 to 1.11.0 for improved parallel processing
|
- **Updated**: Upgraded solid-signals from v0.3.2 to [solidjs-signals v0.4.1](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/websites/default/packages/solidjs-signals/) for improved reactivity and performance
|
||||||
- **Migrated**: vecdb from external version 0.1.0 to local development path for better development workflow
|
- **Enhanced**: Frontend package management and dependency organization
|
||||||
- **Reorganized**: Workspace dependency structure for consistency
|
- **Improved**: Chart rendering performance with updated signal library
|
||||||
|
|
||||||
### Build System
|
### Build System
|
||||||
- **Added**: Rust toolchain version specification (1.89) to workspace configuration
|
- **Updated**: All crate versions from 0.0.88 to 0.0.89 across the workspace
|
||||||
- **Enhanced**: Development environment consistency with toolchain pinning
|
- **Enhanced**: [Cargo.toml](https://github.com/bitcoinresearchkit/brk/blob/v0.0.89/Cargo.toml) dependency management and version consistency
|
||||||
|
|
||||||
### Server Module
|
[View changes](https://github.com/bitcoinresearchkit/brk/compare/v0.0.88...v0.0.89)
|
||||||
- **Improved**: API interface implementations
|
|
||||||
- **Enhanced**: File serving functionality
|
|
||||||
|
|
||||||
### Indexer Module
|
|
||||||
- **Optimized**: Integration with updated computer module patterns
|
|
||||||
|
|
||||||
## [v0.0.88](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.0.88) - 2025-08-10
|
## [v0.0.88](https://github.com/bitcoinresearchkit/brk/releases/tag/v0.0.88) - 2025-08-10
|
||||||
|
|
||||||
|
|||||||
Generated
+388
-154
File diff suppressed because it is too large
Load Diff
+23
-19
@@ -4,7 +4,7 @@ members = ["crates/*"]
|
|||||||
package.description = "The Bitcoin Research Kit is a suite of tools designed to extract, compute and display data stored on a Bitcoin Core node"
|
package.description = "The Bitcoin Research Kit is a suite of tools designed to extract, compute and display data stored on a Bitcoin Core node"
|
||||||
package.license = "MIT"
|
package.license = "MIT"
|
||||||
package.edition = "2024"
|
package.edition = "2024"
|
||||||
package.version = "0.0.89"
|
package.version = "0.0.100"
|
||||||
package.homepage = "https://bitcoinresearchkit.org"
|
package.homepage = "https://bitcoinresearchkit.org"
|
||||||
package.repository = "https://github.com/bitcoinresearchkit/brk"
|
package.repository = "https://github.com/bitcoinresearchkit/brk"
|
||||||
package.readme = "README.md"
|
package.readme = "README.md"
|
||||||
@@ -23,29 +23,32 @@ debug = true
|
|||||||
inherits = "release"
|
inherits = "release"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
allocative = { version = "0.3.4", features = ["parking_lot"] }
|
||||||
|
allocative_derive = "0.3.3"
|
||||||
axum = "0.8.4"
|
axum = "0.8.4"
|
||||||
bitcoin = { version = "0.32.7", features = ["serde"] }
|
bitcoin = { version = "0.32.7", features = ["serde"] }
|
||||||
bitcoincore-rpc = "0.19.0"
|
bitcoincore-rpc = "0.19.0"
|
||||||
brk_bundler = { version = "0.0.89", path = "crates/brk_bundler" }
|
brk_bundler = { version = "0.0.100", path = "crates/brk_bundler" }
|
||||||
brk_cli = { version = "0.0.89", path = "crates/brk_cli" }
|
brk_cli = { version = "0.0.100", path = "crates/brk_cli" }
|
||||||
brk_computer = { version = "0.0.89", path = "crates/brk_computer" }
|
brk_computer = { version = "0.0.100", path = "crates/brk_computer" }
|
||||||
brk_error = { version = "0.0.89", path = "crates/brk_error" }
|
brk_error = { version = "0.0.100", path = "crates/brk_error" }
|
||||||
brk_fetcher = { version = "0.0.89", path = "crates/brk_fetcher" }
|
brk_fetcher = { version = "0.0.100", path = "crates/brk_fetcher" }
|
||||||
brk_indexer = { version = "0.0.89", path = "crates/brk_indexer" }
|
brk_indexer = { version = "0.0.100", path = "crates/brk_indexer" }
|
||||||
brk_interface = { version = "0.0.89", path = "crates/brk_interface" }
|
brk_interface = { version = "0.0.100", path = "crates/brk_interface" }
|
||||||
brk_logger = { version = "0.0.89", path = "crates/brk_logger" }
|
brk_logger = { version = "0.0.100", path = "crates/brk_logger" }
|
||||||
brk_mcp = { version = "0.0.89", path = "crates/brk_mcp" }
|
brk_mcp = { version = "0.0.100", path = "crates/brk_mcp" }
|
||||||
brk_parser = { version = "0.0.89", path = "crates/brk_parser" }
|
brk_parser = { version = "0.0.100", path = "crates/brk_parser" }
|
||||||
brk_server = { version = "0.0.89", path = "crates/brk_server" }
|
brk_server = { version = "0.0.100", path = "crates/brk_server" }
|
||||||
brk_store = { version = "0.0.89", path = "crates/brk_store" }
|
brk_store = { version = "0.0.100", path = "crates/brk_store" }
|
||||||
brk_structs = { version = "0.0.89", path = "crates/brk_structs" }
|
brk_structs = { version = "0.0.100", path = "crates/brk_structs" }
|
||||||
byteview = "=0.6.1"
|
byteview = "=0.6.1"
|
||||||
derive_deref = "1.1.1"
|
derive_deref = "1.1.1"
|
||||||
fjall = "2.11.2"
|
fjall = "2.11.2"
|
||||||
jiff = "0.2.15"
|
jiff = "0.2.15"
|
||||||
log = "0.4.27"
|
log = "0.4.28"
|
||||||
minreq = { version = "2.14.0", features = ["https", "serde_json"] }
|
minreq = { version = "2.14.1", features = ["https", "serde_json"] }
|
||||||
parking_lot = "0.12.4"
|
parking_lot = "0.12.4"
|
||||||
|
quick_cache = "0.6.16"
|
||||||
rayon = "1.11.0"
|
rayon = "1.11.0"
|
||||||
serde = "1.0.219"
|
serde = "1.0.219"
|
||||||
serde_bytes = "0.11.17"
|
serde_bytes = "0.11.17"
|
||||||
@@ -53,9 +56,9 @@ serde_derive = "1.0.219"
|
|||||||
serde_json = { version = "1.0.143", features = ["float_roundtrip"] }
|
serde_json = { version = "1.0.143", features = ["float_roundtrip"] }
|
||||||
tokio = { version = "1.47.1", features = ["rt-multi-thread"] }
|
tokio = { version = "1.47.1", features = ["rt-multi-thread"] }
|
||||||
# vecdb = { path = "../seqdb/crates/vecdb", features = ["derive"]}
|
# vecdb = { path = "../seqdb/crates/vecdb", features = ["derive"]}
|
||||||
vecdb = { version = "0.2.4", features = ["derive"]}
|
vecdb = { version = "0.2.11", features = ["derive"]}
|
||||||
zerocopy = "0.8.26"
|
zerocopy = "0.8.27"
|
||||||
zerocopy-derive = "0.8.26"
|
zerocopy-derive = "0.8.27"
|
||||||
|
|
||||||
[workspace.metadata.release]
|
[workspace.metadata.release]
|
||||||
shared-version = true
|
shared-version = true
|
||||||
@@ -66,6 +69,7 @@ tag-message = "release: v{{version}}"
|
|||||||
[workspace.metadata.dist]
|
[workspace.metadata.dist]
|
||||||
cargo-dist-version = "0.29.0"
|
cargo-dist-version = "0.29.0"
|
||||||
ci = "github"
|
ci = "github"
|
||||||
|
allow-dirty = ["ci"]
|
||||||
installers = []
|
installers = []
|
||||||
targets = ["aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"]
|
targets = ["aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"]
|
||||||
rust-toolchain-version = "1.89"
|
rust-toolchain-version = "1.89"
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<a href="https://deps.rs/crate/brk">
|
<a href="https://deps.rs/crate/brk">
|
||||||
<img src="https://deps.rs/crate/brk/latest/status.svg" alt="Dependency status">
|
<img src="https://deps.rs/crate/brk/latest/status.svg" alt="Dependency status">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://discord.gg/HaR3wpH3nr">
|
<a href="https://discord.gg/WACpShCB7M">
|
||||||
<img src="https://img.shields.io/discord/1350431684562124850?label=discord" alt="Discord" />
|
<img src="https://img.shields.io/discord/1350431684562124850?label=discord" alt="Discord" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://primal.net/p/nprofile1qqsfw5dacngjlahye34krvgz7u0yghhjgk7gxzl5ptm9v6n2y3sn03sqxu2e6">
|
<a href="https://primal.net/p/nprofile1qqsfw5dacngjlahye34krvgz7u0yghhjgk7gxzl5ptm9v6n2y3sn03sqxu2e6">
|
||||||
@@ -31,10 +31,9 @@ In other words it's an alternative to [Glassnode](https://glassnode.com), [mempo
|
|||||||
|
|
||||||
The toolkit can be used in various ways to accommodate as many needs as possible:
|
The toolkit can be used in various ways to accommodate as many needs as possible:
|
||||||
|
|
||||||
- **[Website](https://bitcoinresearchkit.org)** \
|
- **[Website](https://bitview.space)** \
|
||||||
Everyone is welcome to visit the official instance and showcase of the suite's capabilities. \
|
Everyone is welcome to visit the official instance and showcase of the suite's capabilities. \
|
||||||
It has a wide range of functionalities including charts, tables and simulations which you can visit for free and without the need for an account. \
|
It has a wide range of functionalities including charts, tables and simulations which you can visit for free and without the need for an account.
|
||||||
Also available at: [brekit.org](https://brekit.org) // [kibo.money](https://kibo.money) // [satonomics.xyz](https://satonomics.xyz)
|
|
||||||
- **[API](https://github.com/bitcoinresearchkit/brk/tree/main/crates/brk_server#brk-server)** \
|
- **[API](https://github.com/bitcoinresearchkit/brk/tree/main/crates/brk_server#brk-server)** \
|
||||||
Researchers and developers are free to use BRK's public API with  dataset variants at their disposal. \
|
Researchers and developers are free to use BRK's public API with  dataset variants at their disposal. \
|
||||||
Just like the website, it's entirely free, with no authentication or rate-limiting.
|
Just like the website, it's entirely free, with no authentication or rate-limiting.
|
||||||
@@ -62,7 +61,7 @@ If you'd like to have your own instance hosted for you please contact [hosting@b
|
|||||||
- Updates delivered at your convenience
|
- Updates delivered at your convenience
|
||||||
- Direct communication for feature requests and support
|
- Direct communication for feature requests and support
|
||||||
- Bitcoin Core or Knots with desired version
|
- Bitcoin Core or Knots with desired version
|
||||||
- Optional subdomains: `*.bitcoinresearchkit.org`, `*.brekit.org`, `*.kibo.money` and `*.satonomics.xyz`
|
- Optional subdomains
|
||||||
- Logo featured in the Readme if desired
|
- Logo featured in the Readme if desired
|
||||||
|
|
||||||
Pricing: `0.01 BTC / month` *or* `0.1 BTC / year`
|
Pricing: `0.01 BTC / month` *or* `0.1 BTC / year`
|
||||||
@@ -93,7 +92,3 @@ Heartfelt thanks go out to every donor on [Nostr](https://primal.net/p/npub1jagm
|
|||||||
## Donate
|
## Donate
|
||||||
|
|
||||||
[`bc1q09 8zsm89 m7kgyz e338vf ejhpdt 92ua9p 3peuve`](bitcoin:bc1q098zsm89m7kgyze338vfejhpdt92ua9p3peuve)
|
[`bc1q09 8zsm89 m7kgyz e338vf ejhpdt 92ua9p 3peuve`](bitcoin:bc1q098zsm89m7kgyze338vfejhpdt92ua9p3peuve)
|
||||||
|
|
||||||
[`lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkxmmww3jkuar8d35kgetj8yuq363hv4`](lightning:lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkxmmww3jkuar8d35kgetj8yuq363hv4)
|
|
||||||
|
|
||||||
[Geyser Fund](https://geyser.fund/project/brk)
|
|
||||||
|
|||||||
@@ -10,30 +10,19 @@
|
|||||||
- pull latest version and notify is out of date
|
- pull latest version and notify is out of date
|
||||||
- _computer_
|
- _computer_
|
||||||
- **add rollback of states (in stateful)**
|
- **add rollback of states (in stateful)**
|
||||||
- remove configurable format (raw/compressed) and chose sane ones instead
|
- add costs basis by percentile (percentile cost basis) back
|
||||||
- linear reads: compressed (height/date/... + txindex_to_height + txindex_to_version + ...)
|
|
||||||
- random reads: raw (outputindex_to_value + ...)
|
|
||||||
- add prices paid by percentile (percentile cost basis) back
|
|
||||||
- add support for per index computation
|
- add support for per index computation
|
||||||
- fix min feerate which is always ZERO due to coinbase transaction
|
- fix min fee_rate which is always ZERO due to coinbase transaction
|
||||||
- before computing multiple sources check their length, panic if not equal
|
- before computing multiple sources check their length, panic if not equal
|
||||||
- add oracle price dataset (https://utxo.live/oracle/UTXOracle.py)
|
- add oracle price dataset (https://utxo.live/oracle/UTXOracle.py)
|
||||||
- add address counts relative to all datasets
|
- add address counts relative to all datasets
|
||||||
- make decade, quarter, year datasets `computed` instead of `eager`
|
|
||||||
- add 6 months (semester) interval datasets to builder
|
|
||||||
- some datasets in `indexes` can probably be removed
|
|
||||||
- add revived/sent supply datasets
|
- add revived/sent supply datasets
|
||||||
- add `in-sats` version of all price datasets (average and co)
|
- add `in-sats` version of all price datasets (average and co)
|
||||||
- add `p2pk` group (sum of `p2pk33` and `p2pk65`)
|
- add `p2pk` group (sum of `p2pk33` and `p2pk65`)
|
||||||
- add chopiness datasets
|
- add chopiness datasets
|
||||||
- add utxo count, address count, supply data for by reused addresses in groups by address type
|
- add utxo count, address count, supply data for by reused addresses in groups by address type
|
||||||
- add more date ranges (3-6 months and more)
|
- add more date ranges (3-6 months and more)
|
||||||
- add puell multiple dataset
|
|
||||||
- add pi cycle dataset
|
- add pi cycle dataset
|
||||||
- add emas of price
|
|
||||||
- add 7d and 30d ema to sell side risk ratio and sopr
|
|
||||||
- don't compute everything for all cohorts as some datasets combinations are irrelevant
|
|
||||||
- addresses/utxos by amount don't need mvrvz for example
|
|
||||||
- add all possible charts from:
|
- add all possible charts from:
|
||||||
- https://mainnet.observer
|
- https://mainnet.observer
|
||||||
- https://glassnode.com
|
- https://glassnode.com
|
||||||
@@ -75,11 +64,9 @@
|
|||||||
- miners
|
- miners
|
||||||
- maybe xpubs
|
- maybe xpubs
|
||||||
- charts
|
- charts
|
||||||
- improve some names and colors
|
- improve names and colors
|
||||||
- remove `sum` series when it's a duplicate of the `base` (in subsidy for example)
|
|
||||||
- selected unit sometimes changes when going back end forth
|
- selected unit sometimes changes when going back end forth
|
||||||
- add support for custom charts
|
- add support for custom charts
|
||||||
- separate z-score charts from "realized price" (with their own prices), have 4y, 2y and 1y
|
|
||||||
- price scale format depends on unit, hide digits for sats for example (if/when possible)
|
- price scale format depends on unit, hide digits for sats for example (if/when possible)
|
||||||
- table
|
- table
|
||||||
- pagination
|
- pagination
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ brk = { version = "0.0.88", features = ["parser", "indexer", "computer"] }
|
|||||||
use brk::{parser, indexer, computer};
|
use brk::{parser, indexer, computer};
|
||||||
|
|
||||||
// Core data pipeline only
|
// Core data pipeline only
|
||||||
let parser = parser::Parser::new(blocks_dir, output_dir, rpc);
|
let parser = parser::Parser::new(blocks_dir, Some(output_dir), rpc);
|
||||||
let mut indexer = indexer::Indexer::forced_import(output_dir)?;
|
let mut indexer = indexer::Indexer::forced_import(output_dir)?;
|
||||||
let mut computer = computer::Computer::forced_import(output_dir, &indexer, None)?;
|
let mut computer = computer::Computer::forced_import(output_dir, &indexer, None)?;
|
||||||
```
|
```
|
||||||
@@ -81,7 +81,7 @@ use brk::{structs, parser};
|
|||||||
|
|
||||||
// Just parsing and types
|
// Just parsing and types
|
||||||
let height = structs::Height::new(800_000);
|
let height = structs::Height::new(800_000);
|
||||||
let parser = parser::Parser::new(blocks_dir, output_dir, rpc);
|
let parser = parser::Parser::new(blocks_dir, Some(output_dir), rpc);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Feature Flags
|
## Feature Flags
|
||||||
@@ -113,7 +113,7 @@ use brk::*;
|
|||||||
// Full data pipeline setup
|
// Full data pipeline setup
|
||||||
let config = cli::Config::load()?;
|
let config = cli::Config::load()?;
|
||||||
let rpc = /* Bitcoin Core RPC client */;
|
let rpc = /* Bitcoin Core RPC client */;
|
||||||
let parser = parser::Parser::new(config.blocks_dir, config.output_dir, rpc);
|
let parser = parser::Parser::new(config.blocks_dir, Some(config.output_dir), rpc);
|
||||||
let mut indexer = indexer::Indexer::forced_import(&config.output_dir)?;
|
let mut indexer = indexer::Indexer::forced_import(&config.output_dir)?;
|
||||||
let mut computer = computer::Computer::forced_import(&config.output_dir, &indexer, None)?;
|
let mut computer = computer::Computer::forced_import(&config.output_dir, &indexer, None)?;
|
||||||
let interface = interface::Interface::build(&indexer, &computer);
|
let interface = interface::Interface::build(&indexer, &computer);
|
||||||
@@ -152,15 +152,15 @@ use brk::{structs, parser, error};
|
|||||||
|
|
||||||
// Custom application with BRK components
|
// Custom application with BRK components
|
||||||
fn analyze_blocks() -> error::Result<()> {
|
fn analyze_blocks() -> error::Result<()> {
|
||||||
let parser = parser::Parser::new(blocks_dir, output_dir, rpc);
|
let parser = parser::Parser::new(blocks_dir, Some(output_dir), rpc);
|
||||||
|
|
||||||
parser.parse(None, None)
|
parser.parse(None, None)
|
||||||
.iter()
|
.iter()
|
||||||
.take(1000) // First 1000 blocks
|
.take(1000) // First 1000 blocks
|
||||||
.for_each(|(height, block, hash)| {
|
.for_each(|(height, block, hash)| {
|
||||||
println!("Block {}: {} transactions", height, block.txdata.len());
|
println!("Block {}: {} transactions", height, block.txdata.len());
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -194,4 +194,4 @@ For specific dependency information, see individual crate READMEs.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*This README was generated by Claude Code*
|
*This README was generated by Claude Code*
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ pub async fn bundle(websites_path: &Path, source_folder: &str, watch: bool) -> i
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
bundler.write().await.unwrap();
|
if let Err(error) = bundler.write().await {
|
||||||
|
error!("{error:?}");
|
||||||
|
}
|
||||||
|
|
||||||
let absolute_source_index_path = source_path.join("index.html").absolutize();
|
let absolute_source_index_path = source_path.join("index.html").absolutize();
|
||||||
let absolute_source_index_path_clone = absolute_source_index_path.clone();
|
let absolute_source_index_path_clone = absolute_source_index_path.clone();
|
||||||
|
|||||||
@@ -20,15 +20,15 @@ brk_logger = { workspace = true }
|
|||||||
brk_parser = { workspace = true }
|
brk_parser = { workspace = true }
|
||||||
brk_server = { workspace = true }
|
brk_server = { workspace = true }
|
||||||
vecdb = { workspace = true }
|
vecdb = { workspace = true }
|
||||||
clap = { version = "4.5.45", features = ["string"] }
|
clap = { version = "4.5.47", features = ["string"] }
|
||||||
clap_derive = "4.5.45"
|
clap_derive = "4.5.47"
|
||||||
color-eyre = "0.6.5"
|
color-eyre = "0.6.5"
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
minreq = { workspace = true }
|
minreq = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
toml = "0.9.5"
|
toml = "0.9.5"
|
||||||
zip = { version = "4.5.0", default-features = false, features = ["deflate"] }
|
zip = { version = "5.0.0", default-features = false, features = ["deflate"] }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "brk"
|
name = "brk"
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
use std::{fs, io, path::Path};
|
use std::{fs, io, path::Path};
|
||||||
|
|
||||||
|
use brk_computer::pools;
|
||||||
use brk_interface::{Index, Interface};
|
use brk_interface::{Index, Interface};
|
||||||
use brk_server::VERSION;
|
use brk_server::VERSION;
|
||||||
|
|
||||||
use crate::website::Website;
|
use crate::website::Website;
|
||||||
|
|
||||||
const SCRIPTS: &str = "scripts";
|
const BRIDGE_PATH: &str = "scripts/bridge";
|
||||||
|
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
pub trait Bridge {
|
pub trait Bridge {
|
||||||
fn generate_bridge_file(&self, website: Website, websites_path: &Path) -> io::Result<()>;
|
fn generate_bridge_files(&self, website: Website, websites_path: &Path) -> io::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bridge for Interface<'static> {
|
impl Bridge for Interface<'static> {
|
||||||
fn generate_bridge_file(&self, website: Website, websites_path: &Path) -> io::Result<()> {
|
fn generate_bridge_files(&self, website: Website, websites_path: &Path) -> io::Result<()> {
|
||||||
if website.is_none() {
|
if website.is_none() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -24,88 +25,130 @@ impl Bridge for Interface<'static> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = path.join(SCRIPTS);
|
let path = path.join(BRIDGE_PATH);
|
||||||
|
|
||||||
fs::create_dir_all(&path)?;
|
fs::create_dir_all(&path)?;
|
||||||
|
|
||||||
let path = path.join(Path::new("vecid-to-indexes.js"));
|
generate_vecs_file(self, &path)?;
|
||||||
|
generate_pools_file(&path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let indexes = Index::all();
|
fn generate_pools_file(parent: &Path) -> io::Result<()> {
|
||||||
|
let path = parent.join(Path::new("pools.js"));
|
||||||
|
|
||||||
let mut contents = format!(
|
let pools = pools();
|
||||||
"//
|
|
||||||
|
let mut contents = "//
|
||||||
|
// File auto-generated, any modifications will be overwritten
|
||||||
|
//
|
||||||
|
"
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
contents += "
|
||||||
|
/** @typedef {ReturnType<typeof createPools>} Pools */
|
||||||
|
/** @typedef {keyof Pools} Pool */
|
||||||
|
|
||||||
|
export function createPools() {
|
||||||
|
return /** @type {const} */ ({
|
||||||
|
";
|
||||||
|
|
||||||
|
let mut sorted_pools: Vec<_> = pools.iter().collect();
|
||||||
|
sorted_pools.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase()));
|
||||||
|
|
||||||
|
contents += &sorted_pools
|
||||||
|
.iter()
|
||||||
|
.map(|pool| {
|
||||||
|
let id = pool.serialized_id();
|
||||||
|
format!(" {id}: \"{}\",", pool.name)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
contents += "\n });\n}\n";
|
||||||
|
|
||||||
|
fs::write(path, contents)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_vecs_file(interface: &Interface<'static>, parent: &Path) -> io::Result<()> {
|
||||||
|
let path = parent.join(Path::new("vecs.js"));
|
||||||
|
|
||||||
|
let indexes = Index::all();
|
||||||
|
|
||||||
|
let mut contents = format!(
|
||||||
|
"//
|
||||||
// File auto-generated, any modifications will be overwritten
|
// File auto-generated, any modifications will be overwritten
|
||||||
//
|
//
|
||||||
|
|
||||||
export const VERSION = \"v{VERSION}\";
|
export const VERSION = \"v{VERSION}\";
|
||||||
|
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
contents += &indexes
|
contents += &indexes
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i_of_i, i)| {
|
||||||
|
// let lowered = i.to_string().to_lowercase();
|
||||||
|
format!("/** @typedef {{{i_of_i}}} {i} */",)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
contents += &format!(
|
||||||
|
"\n\n/** @typedef {{{}}} Index */\n",
|
||||||
|
indexes
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.map(|i| i.to_string())
|
||||||
.map(|(i_of_i, i)| {
|
|
||||||
// let lowered = i.to_string().to_lowercase();
|
|
||||||
format!("/** @typedef {{{i_of_i}}} {i} */",)
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n");
|
.join(" | ")
|
||||||
|
);
|
||||||
|
|
||||||
contents += &format!(
|
contents += "
|
||||||
"\n\n/** @typedef {{{}}} Index */\n",
|
|
||||||
indexes
|
|
||||||
.iter()
|
|
||||||
.map(|i| i.to_string())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(" | ")
|
|
||||||
);
|
|
||||||
|
|
||||||
contents += "
|
|
||||||
/** @typedef {ReturnType<typeof createIndexes>} Indexes */
|
/** @typedef {ReturnType<typeof createIndexes>} Indexes */
|
||||||
|
|
||||||
export function createIndexes() {
|
export function createIndexes() {
|
||||||
return {
|
return {
|
||||||
";
|
";
|
||||||
|
|
||||||
contents += &indexes
|
contents += &indexes
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i_of_i, i)| {
|
.map(|(i_of_i, i)| {
|
||||||
let lowered = i.to_string().to_lowercase();
|
let lowered = i.to_string().to_lowercase();
|
||||||
format!(" {lowered}: /** @satisfies {{{i}}} */ ({i_of_i}),",)
|
format!(" {lowered}: /** @satisfies {{{i}}} */ ({i_of_i}),",)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
|
|
||||||
contents += " };\n}\n";
|
contents += " };\n}\n";
|
||||||
|
|
||||||
contents += "
|
contents += "
|
||||||
/** @typedef {ReturnType<typeof createVecIdToIndexes>} VecIdToIndexes
|
/** @typedef {ReturnType<typeof createVecIdToIndexes>} VecIdToIndexes
|
||||||
/** @typedef {keyof VecIdToIndexes} VecId */
|
/** @typedef {keyof VecIdToIndexes} VecId */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {Record<any, number[]>}
|
* @returns {Record<any, number[]>}
|
||||||
*/
|
*/
|
||||||
export function createVecIdToIndexes() {
|
export function createVecIdToIndexes() {
|
||||||
return {
|
return {
|
||||||
";
|
";
|
||||||
|
|
||||||
self.id_to_index_to_vec()
|
interface
|
||||||
.iter()
|
.id_to_index_to_vec()
|
||||||
.for_each(|(id, index_to_vec)| {
|
.iter()
|
||||||
let indexes = index_to_vec
|
.for_each(|(id, index_to_vec)| {
|
||||||
.keys()
|
let indexes = index_to_vec
|
||||||
.map(|i| (*i as u8).to_string())
|
.keys()
|
||||||
// .map(|i| i.to_string())
|
.map(|i| (*i as u8).to_string())
|
||||||
.collect::<Vec<_>>()
|
// .map(|i| i.to_string())
|
||||||
.join(", ");
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
contents += &format!(" \"{id}\": [{indexes}],\n");
|
contents += &format!(" \"{id}\": [{indexes}],\n");
|
||||||
});
|
});
|
||||||
|
|
||||||
contents += " };\n}\n";
|
contents += " };\n}\n";
|
||||||
|
|
||||||
fs::write(path, contents)
|
fs::write(path, contents)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use std::{
|
|||||||
use bitcoincore_rpc::{self, Auth, Client};
|
use bitcoincore_rpc::{self, Auth, Client};
|
||||||
use brk_fetcher::Fetcher;
|
use brk_fetcher::Fetcher;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use clap_derive::Parser;
|
|
||||||
use color_eyre::eyre::eyre;
|
use color_eyre::eyre::eyre;
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
|
|
||||||
@@ -284,7 +283,7 @@ Finally, you can run the program with '-h' for help."
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn website(&self) -> Website {
|
pub fn website(&self) -> Website {
|
||||||
self.website.unwrap_or(Website::Default)
|
self.website.unwrap_or(Website::Bitview)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetch(&self) -> bool {
|
pub fn fetch(&self) -> bool {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use brk_bundler::bundle;
|
|||||||
use brk_computer::Computer;
|
use brk_computer::Computer;
|
||||||
use brk_indexer::Indexer;
|
use brk_indexer::Indexer;
|
||||||
use brk_interface::Interface;
|
use brk_interface::Interface;
|
||||||
|
use brk_parser::Parser;
|
||||||
use brk_server::{Server, VERSION};
|
use brk_server::{Server, VERSION};
|
||||||
use log::info;
|
use log::info;
|
||||||
use vecdb::Exit;
|
use vecdb::Exit;
|
||||||
@@ -46,7 +47,7 @@ pub fn run() -> color_eyre::Result<()> {
|
|||||||
let exit = Exit::new();
|
let exit = Exit::new();
|
||||||
exit.set_ctrlc_handler();
|
exit.set_ctrlc_handler();
|
||||||
|
|
||||||
let parser = brk_parser::Parser::new(config.blocksdir(), config.brkdir(), rpc);
|
let parser = Parser::new(config.blocksdir(), Some(config.brkdir()), rpc);
|
||||||
|
|
||||||
let mut indexer = Indexer::forced_import(&config.brkdir())?;
|
let mut indexer = Indexer::forced_import(&config.brkdir())?;
|
||||||
|
|
||||||
@@ -106,7 +107,7 @@ pub fn run() -> color_eyre::Result<()> {
|
|||||||
downloaded_websites_path
|
downloaded_websites_path
|
||||||
};
|
};
|
||||||
|
|
||||||
interface.generate_bridge_file(website, websites_path.as_path())?;
|
interface.generate_bridge_files(website, websites_path.as_path())?;
|
||||||
|
|
||||||
Some(bundle(&websites_path, website.to_folder_name(), true).await?)
|
Some(bundle(&websites_path, website.to_folder_name(), true).await?)
|
||||||
} else {
|
} else {
|
||||||
@@ -134,6 +135,8 @@ pub fn run() -> color_eyre::Result<()> {
|
|||||||
let starting_indexes =
|
let starting_indexes =
|
||||||
indexer.index(&parser, rpc, &exit, config.check_collisions()).unwrap();
|
indexer.index(&parser, rpc, &exit, config.check_collisions()).unwrap();
|
||||||
|
|
||||||
|
// dbg!(&starting_indexes);
|
||||||
|
|
||||||
computer.compute(&indexer, starting_indexes, &exit).unwrap();
|
computer.compute(&indexer, starting_indexes, &exit).unwrap();
|
||||||
|
|
||||||
info!("Waiting for new blocks...");
|
info!("Waiting for new blocks...");
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ use clap_derive::ValueEnum;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, ValueEnum)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, ValueEnum)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum Website {
|
pub enum Website {
|
||||||
None,
|
None,
|
||||||
Default,
|
Bitview,
|
||||||
Custom,
|
Custom,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ impl Website {
|
|||||||
pub fn to_folder_name(self) -> &'static str {
|
pub fn to_folder_name(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Self::Custom => "custom",
|
Self::Custom => "custom",
|
||||||
Self::Default => "default",
|
Self::Bitview => "bitview",
|
||||||
Self::None => unreachable!(),
|
Self::None => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ rust-version.workspace = true
|
|||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
allocative = { workspace = true }
|
||||||
|
allocative_derive = { workspace = true }
|
||||||
bitcoin = { workspace = true }
|
bitcoin = { workspace = true }
|
||||||
bitcoincore-rpc = { workspace = true }
|
bitcoincore-rpc = { workspace = true }
|
||||||
brk_structs = { workspace = true }
|
brk_structs = { workspace = true }
|
||||||
@@ -17,13 +19,18 @@ brk_error = { workspace = true }
|
|||||||
brk_fetcher = { workspace = true }
|
brk_fetcher = { workspace = true }
|
||||||
brk_indexer = { workspace = true }
|
brk_indexer = { workspace = true }
|
||||||
brk_logger = { workspace = true }
|
brk_logger = { workspace = true }
|
||||||
|
brk_store = { workspace = true }
|
||||||
brk_parser = { workspace = true }
|
brk_parser = { workspace = true }
|
||||||
vecdb = { workspace = true }
|
vecdb = { workspace = true }
|
||||||
derive_deref = { workspace = true }
|
derive_deref = { workspace = true }
|
||||||
|
inferno = "0.12.3"
|
||||||
|
jiff = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
|
num_enum = "0.7.4"
|
||||||
pco = "0.4.6"
|
pco = "0.4.6"
|
||||||
rayon = { workspace = true }
|
rayon = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
|
serde_json = { workspace = true }
|
||||||
zerocopy = { workspace = true }
|
zerocopy = { workspace = true }
|
||||||
zerocopy-derive = { workspace = true }
|
zerocopy-derive = { workspace = true }
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,11 @@ pub fn main() -> Result<()> {
|
|||||||
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
|
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
|
||||||
// let outputs_dir = Path::new("../../_outputs");
|
// let outputs_dir = Path::new("../../_outputs");
|
||||||
|
|
||||||
let parser = Parser::new(bitcoin_dir.join("blocks"), outputs_dir.to_path_buf(), rpc);
|
let parser = Parser::new(
|
||||||
|
bitcoin_dir.join("blocks"),
|
||||||
|
Some(outputs_dir.to_path_buf()),
|
||||||
|
rpc,
|
||||||
|
);
|
||||||
|
|
||||||
let mut indexer = Indexer::forced_import(&outputs_dir)?;
|
let mut indexer = Indexer::forced_import(&outputs_dir)?;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
use std::{collections::BTreeMap, path::Path, thread};
|
||||||
|
|
||||||
|
use brk_computer::{Computer, pools};
|
||||||
|
use brk_error::Result;
|
||||||
|
use brk_fetcher::Fetcher;
|
||||||
|
use brk_indexer::Indexer;
|
||||||
|
use brk_structs::{AddressBytes, OutputIndex, OutputType};
|
||||||
|
use vecdb::{AnyIterableVec, Exit, VecIterator};
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
brk_logger::init(Some(Path::new(".log")))?;
|
||||||
|
|
||||||
|
let exit = Exit::new();
|
||||||
|
exit.set_ctrlc_handler();
|
||||||
|
|
||||||
|
thread::Builder::new()
|
||||||
|
.stack_size(256 * 1024 * 1024)
|
||||||
|
.spawn(move || -> Result<()> {
|
||||||
|
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
|
||||||
|
|
||||||
|
let indexer = Indexer::forced_import(&outputs_dir)?;
|
||||||
|
|
||||||
|
let fetcher = Fetcher::import(true, None)?;
|
||||||
|
|
||||||
|
let computer = Computer::forced_import(&outputs_dir, &indexer, Some(fetcher))?;
|
||||||
|
|
||||||
|
let pools = pools();
|
||||||
|
|
||||||
|
let mut res: BTreeMap<&'static str, usize> = BTreeMap::default();
|
||||||
|
|
||||||
|
let vecs = indexer.vecs;
|
||||||
|
let stores = indexer.stores;
|
||||||
|
|
||||||
|
let mut height_to_first_txindex_iter = vecs.height_to_first_txindex.iter();
|
||||||
|
let mut txindex_to_first_outputindex_iter = vecs.txindex_to_first_outputindex.iter();
|
||||||
|
let mut txindex_to_output_count_iter = computer.indexes.txindex_to_output_count.iter();
|
||||||
|
let mut outputindex_to_outputtype_iter = vecs.outputindex_to_outputtype.iter();
|
||||||
|
let mut outputindex_to_typeindex_iter = vecs.outputindex_to_typeindex.iter();
|
||||||
|
let mut p2pk65addressindex_to_p2pk65bytes_iter =
|
||||||
|
vecs.p2pk65addressindex_to_p2pk65bytes.iter();
|
||||||
|
let mut p2pk33addressindex_to_p2pk33bytes_iter =
|
||||||
|
vecs.p2pk33addressindex_to_p2pk33bytes.iter();
|
||||||
|
let mut p2pkhaddressindex_to_p2pkhbytes_iter =
|
||||||
|
vecs.p2pkhaddressindex_to_p2pkhbytes.iter();
|
||||||
|
let mut p2shaddressindex_to_p2shbytes_iter = vecs.p2shaddressindex_to_p2shbytes.iter();
|
||||||
|
let mut p2wpkhaddressindex_to_p2wpkhbytes_iter =
|
||||||
|
vecs.p2wpkhaddressindex_to_p2wpkhbytes.iter();
|
||||||
|
let mut p2wshaddressindex_to_p2wshbytes_iter =
|
||||||
|
vecs.p2wshaddressindex_to_p2wshbytes.iter();
|
||||||
|
let mut p2traddressindex_to_p2trbytes_iter = vecs.p2traddressindex_to_p2trbytes.iter();
|
||||||
|
let mut p2aaddressindex_to_p2abytes_iter = vecs.p2aaddressindex_to_p2abytes.iter();
|
||||||
|
|
||||||
|
let unknown = pools.get_unknown();
|
||||||
|
|
||||||
|
stores
|
||||||
|
.height_to_coinbase_tag
|
||||||
|
.iter()
|
||||||
|
.for_each(|(height, coinbase_tag)| {
|
||||||
|
let txindex = height_to_first_txindex_iter.unwrap_get_inner(height);
|
||||||
|
let outputindex = txindex_to_first_outputindex_iter.unwrap_get_inner(txindex);
|
||||||
|
let outputcount = txindex_to_output_count_iter.unwrap_get_inner(txindex);
|
||||||
|
|
||||||
|
let pool = (*outputindex..(*outputindex + *outputcount))
|
||||||
|
.map(OutputIndex::from)
|
||||||
|
.find_map(|outputindex| {
|
||||||
|
let outputtype =
|
||||||
|
outputindex_to_outputtype_iter.unwrap_get_inner(outputindex);
|
||||||
|
let typeindex =
|
||||||
|
outputindex_to_typeindex_iter.unwrap_get_inner(outputindex);
|
||||||
|
|
||||||
|
let address = match outputtype {
|
||||||
|
OutputType::P2PK65 => Some(AddressBytes::from(
|
||||||
|
p2pk65addressindex_to_p2pk65bytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2PK33 => Some(AddressBytes::from(
|
||||||
|
p2pk33addressindex_to_p2pk33bytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2PKH => Some(AddressBytes::from(
|
||||||
|
p2pkhaddressindex_to_p2pkhbytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2SH => Some(AddressBytes::from(
|
||||||
|
p2shaddressindex_to_p2shbytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2WPKH => Some(AddressBytes::from(
|
||||||
|
p2wpkhaddressindex_to_p2wpkhbytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2WSH => Some(AddressBytes::from(
|
||||||
|
p2wshaddressindex_to_p2wshbytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2TR => Some(AddressBytes::from(
|
||||||
|
p2traddressindex_to_p2trbytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2A => Some(AddressBytes::from(
|
||||||
|
p2aaddressindex_to_p2abytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
address
|
||||||
|
.and_then(|address| pools.find_from_address(&address.to_string()))
|
||||||
|
})
|
||||||
|
.or_else(|| pools.find_from_coinbase_tag(&coinbase_tag))
|
||||||
|
.unwrap_or(unknown);
|
||||||
|
|
||||||
|
*res.entry(pool.name).or_default() += 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut v = res.into_iter().map(|(k, v)| (v, k)).collect::<Vec<_>>();
|
||||||
|
v.sort_unstable();
|
||||||
|
println!("{:#?}", v);
|
||||||
|
println!("{:#?}", v.len());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})?
|
||||||
|
.join()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
@@ -1,264 +0,0 @@
|
|||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use brk_error::Result;
|
|
||||||
use brk_indexer::Indexer;
|
|
||||||
use brk_structs::{
|
|
||||||
CheckedSub, DifficultyEpoch, HalvingEpoch, Height, StoredU32, StoredU64, Timestamp, Version,
|
|
||||||
Weight,
|
|
||||||
};
|
|
||||||
use vecdb::{AnyCollectableVec, Database, EagerVec, Exit, PAGE_SIZE, VecIterator};
|
|
||||||
|
|
||||||
use crate::grouped::Source;
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
Indexes,
|
|
||||||
grouped::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, VecBuilderOptions},
|
|
||||||
indexes,
|
|
||||||
};
|
|
||||||
|
|
||||||
const VERSION: Version = Version::ZERO;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Vecs {
|
|
||||||
db: Database,
|
|
||||||
|
|
||||||
pub height_to_interval: EagerVec<Height, Timestamp>,
|
|
||||||
pub height_to_vbytes: EagerVec<Height, StoredU64>,
|
|
||||||
pub difficultyepoch_to_timestamp: EagerVec<DifficultyEpoch, Timestamp>,
|
|
||||||
pub halvingepoch_to_timestamp: EagerVec<HalvingEpoch, Timestamp>,
|
|
||||||
pub timeindexes_to_timestamp: ComputedVecsFromDateIndex<Timestamp>,
|
|
||||||
pub indexes_to_block_count: ComputedVecsFromHeight<StoredU32>,
|
|
||||||
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
|
|
||||||
pub indexes_to_block_size: ComputedVecsFromHeight<StoredU64>,
|
|
||||||
pub indexes_to_block_vbytes: ComputedVecsFromHeight<StoredU64>,
|
|
||||||
pub indexes_to_block_weight: ComputedVecsFromHeight<Weight>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Vecs {
|
|
||||||
pub fn forced_import(parent: &Path, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
|
|
||||||
let db = Database::open(&parent.join("blocks"))?;
|
|
||||||
db.set_min_len(PAGE_SIZE * 1_000_000)?;
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
height_to_interval: EagerVec::forced_import_compressed(
|
|
||||||
&db,
|
|
||||||
"interval",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
timeindexes_to_timestamp: ComputedVecsFromDateIndex::forced_import(
|
|
||||||
&db,
|
|
||||||
"timestamp",
|
|
||||||
Source::Compute,
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
indexes,
|
|
||||||
VecBuilderOptions::default().add_first(),
|
|
||||||
)?,
|
|
||||||
indexes_to_block_interval: ComputedVecsFromHeight::forced_import(
|
|
||||||
&db,
|
|
||||||
"block_interval",
|
|
||||||
Source::None,
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
indexes,
|
|
||||||
VecBuilderOptions::default()
|
|
||||||
.add_percentiles()
|
|
||||||
.add_minmax()
|
|
||||||
.add_average(),
|
|
||||||
)?,
|
|
||||||
indexes_to_block_count: ComputedVecsFromHeight::forced_import(
|
|
||||||
&db,
|
|
||||||
"block_count",
|
|
||||||
Source::Compute,
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
indexes,
|
|
||||||
VecBuilderOptions::default().add_sum().add_cumulative(),
|
|
||||||
)?,
|
|
||||||
indexes_to_block_weight: ComputedVecsFromHeight::forced_import(
|
|
||||||
&db,
|
|
||||||
"block_weight",
|
|
||||||
Source::None,
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
indexes,
|
|
||||||
VecBuilderOptions::default().add_sum().add_cumulative(),
|
|
||||||
)?,
|
|
||||||
indexes_to_block_size: ComputedVecsFromHeight::forced_import(
|
|
||||||
&db,
|
|
||||||
"block_size",
|
|
||||||
Source::None,
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
indexes,
|
|
||||||
VecBuilderOptions::default().add_sum().add_cumulative(),
|
|
||||||
)?,
|
|
||||||
height_to_vbytes: EagerVec::forced_import_compressed(
|
|
||||||
&db,
|
|
||||||
"vbytes",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
indexes_to_block_vbytes: ComputedVecsFromHeight::forced_import(
|
|
||||||
&db,
|
|
||||||
"block_vbytes",
|
|
||||||
Source::None,
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
indexes,
|
|
||||||
VecBuilderOptions::default().add_sum().add_cumulative(),
|
|
||||||
)?,
|
|
||||||
difficultyepoch_to_timestamp: EagerVec::forced_import_compressed(
|
|
||||||
&db,
|
|
||||||
"timestamp",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
halvingepoch_to_timestamp: EagerVec::forced_import_compressed(
|
|
||||||
&db,
|
|
||||||
"timestamp",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
|
|
||||||
db,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compute(
|
|
||||||
&mut self,
|
|
||||||
indexer: &Indexer,
|
|
||||||
indexes: &indexes::Vecs,
|
|
||||||
starting_indexes: &Indexes,
|
|
||||||
exit: &Exit,
|
|
||||||
) -> Result<()> {
|
|
||||||
self.compute_(indexer, indexes, starting_indexes, exit)?;
|
|
||||||
self.db.flush_then_punch()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compute_(
|
|
||||||
&mut self,
|
|
||||||
indexer: &Indexer,
|
|
||||||
indexes: &indexes::Vecs,
|
|
||||||
starting_indexes: &Indexes,
|
|
||||||
exit: &Exit,
|
|
||||||
) -> Result<()> {
|
|
||||||
self.timeindexes_to_timestamp.compute_all(
|
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
|
||||||
vec.compute_transform(
|
|
||||||
starting_indexes.dateindex,
|
|
||||||
&indexes.dateindex_to_date,
|
|
||||||
|(di, d, ..)| (di, Timestamp::from(d)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.indexes_to_block_count.compute_all(
|
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
|v, indexer, _, starting_indexes, exit| {
|
|
||||||
v.compute_range(
|
|
||||||
starting_indexes.height,
|
|
||||||
&indexer.vecs.height_to_weight,
|
|
||||||
|h| (h, StoredU32::from(1_u32)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
|
|
||||||
self.height_to_interval.compute_transform(
|
|
||||||
starting_indexes.height,
|
|
||||||
&indexer.vecs.height_to_timestamp,
|
|
||||||
|(height, timestamp, ..)| {
|
|
||||||
let interval = height.decremented().map_or(Timestamp::ZERO, |prev_h| {
|
|
||||||
let prev_timestamp = height_to_timestamp_iter.unwrap_get_inner(prev_h);
|
|
||||||
timestamp
|
|
||||||
.checked_sub(prev_timestamp)
|
|
||||||
.unwrap_or(Timestamp::ZERO)
|
|
||||||
});
|
|
||||||
(height, interval)
|
|
||||||
},
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.indexes_to_block_interval.compute_rest(
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
Some(&self.height_to_interval),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.indexes_to_block_weight.compute_rest(
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
Some(&indexer.vecs.height_to_weight),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.indexes_to_block_size.compute_rest(
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
Some(&indexer.vecs.height_to_total_size),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.height_to_vbytes.compute_transform(
|
|
||||||
starting_indexes.height,
|
|
||||||
&indexer.vecs.height_to_weight,
|
|
||||||
|(h, w, ..)| {
|
|
||||||
(
|
|
||||||
h,
|
|
||||||
StoredU64::from(bitcoin::Weight::from(w).to_vbytes_floor()),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.indexes_to_block_vbytes.compute_rest(
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
Some(&self.height_to_vbytes),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
|
|
||||||
|
|
||||||
self.difficultyepoch_to_timestamp.compute_transform(
|
|
||||||
starting_indexes.difficultyepoch,
|
|
||||||
&indexes.difficultyepoch_to_first_height,
|
|
||||||
|(i, h, ..)| (i, height_to_timestamp_iter.unwrap_get_inner(h)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.halvingepoch_to_timestamp.compute_transform(
|
|
||||||
starting_indexes.halvingepoch,
|
|
||||||
&indexes.halvingepoch_to_first_height,
|
|
||||||
|(i, h, ..)| (i, height_to_timestamp_iter.unwrap_get_inner(h)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
|
||||||
[
|
|
||||||
vec![
|
|
||||||
&self.height_to_interval as &dyn AnyCollectableVec,
|
|
||||||
&self.height_to_vbytes,
|
|
||||||
&self.difficultyepoch_to_timestamp,
|
|
||||||
&self.halvingepoch_to_timestamp,
|
|
||||||
],
|
|
||||||
self.timeindexes_to_timestamp.vecs(),
|
|
||||||
self.indexes_to_block_count.vecs(),
|
|
||||||
self.indexes_to_block_interval.vecs(),
|
|
||||||
self.indexes_to_block_size.vecs(),
|
|
||||||
self.indexes_to_block_vbytes.vecs(),
|
|
||||||
self.indexes_to_block_weight.vecs(),
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.flatten()
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use allocative::Allocative;
|
||||||
use brk_error::Result;
|
use brk_error::Result;
|
||||||
use brk_indexer::Indexer;
|
use brk_indexer::Indexer;
|
||||||
use brk_structs::{
|
use brk_structs::{
|
||||||
CheckedSub, Feerate, HalvingEpoch, Height, InputIndex, OutputIndex, Sats, StoredBool,
|
CheckedSub, Date, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, FeeRate, HalvingEpoch,
|
||||||
StoredU32, StoredU64, TxIndex, TxVersion, Version, Weight,
|
Height, InputIndex, MonthIndex, OutputIndex, QuarterIndex, Sats, SemesterIndex, StoredBool,
|
||||||
|
StoredF32, StoredF64, StoredU32, StoredU64, Timestamp, TxIndex, TxVersion, Version, WeekIndex,
|
||||||
|
Weight, YearIndex,
|
||||||
};
|
};
|
||||||
use vecdb::{
|
use vecdb::{
|
||||||
AnyCloneableIterableVec, AnyCollectableVec, AnyIterableVec, Database, EagerVec, Exit,
|
AnyCloneableIterableVec, AnyCollectableVec, AnyIterableVec, Database, EagerVec, Exit,
|
||||||
@@ -12,25 +15,57 @@ use vecdb::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::grouped::{
|
use crate::grouped::{
|
||||||
ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromHeight,
|
ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromDateIndex,
|
||||||
ComputedVecsFromTxindex, Source, VecBuilderOptions,
|
ComputedVecsFromHeight, ComputedVecsFromTxindex, Source, VecBuilderOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Indexes, indexes, price};
|
use super::{Indexes, indexes, price};
|
||||||
|
|
||||||
const VERSION: Version = Version::ZERO;
|
const VERSION: Version = Version::ZERO;
|
||||||
|
const TARGET_BLOCKS_PER_DAY_F64: f64 = 144.0;
|
||||||
|
const TARGET_BLOCKS_PER_DAY: u64 = 144;
|
||||||
|
const TARGET_BLOCKS_PER_WEEK: u64 = 7 * TARGET_BLOCKS_PER_DAY;
|
||||||
|
const TARGET_BLOCKS_PER_MONTH: u64 = 30 * TARGET_BLOCKS_PER_DAY;
|
||||||
|
const TARGET_BLOCKS_PER_QUARTER: u64 = 3 * TARGET_BLOCKS_PER_MONTH;
|
||||||
|
const TARGET_BLOCKS_PER_SEMESTER: u64 = 2 * TARGET_BLOCKS_PER_QUARTER;
|
||||||
|
const TARGET_BLOCKS_PER_YEAR: u64 = 2 * TARGET_BLOCKS_PER_SEMESTER;
|
||||||
|
const TARGET_BLOCKS_PER_DECADE: u64 = 10 * TARGET_BLOCKS_PER_YEAR;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Allocative)]
|
||||||
pub struct Vecs {
|
pub struct Vecs {
|
||||||
db: Database,
|
db: Database,
|
||||||
|
|
||||||
// pub txindex_to_is_v1: LazyVec<Txindex, bool>,
|
pub dateindex_to_block_count_target: LazyVecFrom1<DateIndex, StoredU64, DateIndex, DateIndex>,
|
||||||
// pub txindex_to_is_v2: LazyVec<Txindex, bool>,
|
pub weekindex_to_block_count_target: LazyVecFrom1<WeekIndex, StoredU64, WeekIndex, WeekIndex>,
|
||||||
// pub txindex_to_is_v3: LazyVec<Txindex, bool>,
|
pub monthindex_to_block_count_target:
|
||||||
|
LazyVecFrom1<MonthIndex, StoredU64, MonthIndex, MonthIndex>,
|
||||||
|
pub quarterindex_to_block_count_target:
|
||||||
|
LazyVecFrom1<QuarterIndex, StoredU64, QuarterIndex, QuarterIndex>,
|
||||||
|
pub semesterindex_to_block_count_target:
|
||||||
|
LazyVecFrom1<SemesterIndex, StoredU64, SemesterIndex, SemesterIndex>,
|
||||||
|
pub yearindex_to_block_count_target: LazyVecFrom1<YearIndex, StoredU64, YearIndex, YearIndex>,
|
||||||
|
pub decadeindex_to_block_count_target:
|
||||||
|
LazyVecFrom1<DecadeIndex, StoredU64, DecadeIndex, DecadeIndex>,
|
||||||
|
pub height_to_interval: EagerVec<Height, Timestamp>,
|
||||||
|
pub height_to_vbytes: EagerVec<Height, StoredU64>,
|
||||||
|
pub difficultyepoch_to_timestamp: EagerVec<DifficultyEpoch, Timestamp>,
|
||||||
|
pub halvingepoch_to_timestamp: EagerVec<HalvingEpoch, Timestamp>,
|
||||||
|
pub timeindexes_to_timestamp: ComputedVecsFromDateIndex<Timestamp>,
|
||||||
|
pub indexes_to_block_count: ComputedVecsFromHeight<StoredU32>,
|
||||||
|
pub indexes_to_1w_block_count: ComputedVecsFromDateIndex<StoredU32>,
|
||||||
|
pub indexes_to_1m_block_count: ComputedVecsFromDateIndex<StoredU32>,
|
||||||
|
pub indexes_to_1y_block_count: ComputedVecsFromDateIndex<StoredU32>,
|
||||||
|
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
|
||||||
|
pub indexes_to_block_size: ComputedVecsFromHeight<StoredU64>,
|
||||||
|
pub indexes_to_block_vbytes: ComputedVecsFromHeight<StoredU64>,
|
||||||
|
pub indexes_to_block_weight: ComputedVecsFromHeight<Weight>,
|
||||||
|
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
|
||||||
|
pub indexes_to_difficultyepoch: ComputedVecsFromDateIndex<DifficultyEpoch>,
|
||||||
|
pub indexes_to_halvingepoch: ComputedVecsFromDateIndex<HalvingEpoch>,
|
||||||
pub indexes_to_coinbase: ComputedValueVecsFromHeight,
|
pub indexes_to_coinbase: ComputedValueVecsFromHeight,
|
||||||
pub indexes_to_emptyoutput_count: ComputedVecsFromHeight<StoredU64>,
|
pub indexes_to_emptyoutput_count: ComputedVecsFromHeight<StoredU64>,
|
||||||
pub indexes_to_fee: ComputedValueVecsFromTxindex,
|
pub indexes_to_fee: ComputedValueVecsFromTxindex,
|
||||||
pub indexes_to_feerate: ComputedVecsFromTxindex<Feerate>,
|
pub indexes_to_fee_rate: ComputedVecsFromTxindex<FeeRate>,
|
||||||
/// Value == 0 when Coinbase
|
/// Value == 0 when Coinbase
|
||||||
pub txindex_to_input_value:
|
pub txindex_to_input_value:
|
||||||
LazyVecFrom3<TxIndex, Sats, TxIndex, InputIndex, TxIndex, StoredU64, InputIndex, Sats>,
|
LazyVecFrom3<TxIndex, Sats, TxIndex, InputIndex, TxIndex, StoredU64, InputIndex, Sats>,
|
||||||
@@ -65,8 +100,18 @@ pub struct Vecs {
|
|||||||
pub txindex_to_vsize: LazyVecFrom1<TxIndex, StoredU64, TxIndex, Weight>,
|
pub txindex_to_vsize: LazyVecFrom1<TxIndex, StoredU64, TxIndex, Weight>,
|
||||||
pub txindex_to_weight: LazyVecFrom2<TxIndex, Weight, TxIndex, StoredU32, TxIndex, StoredU32>,
|
pub txindex_to_weight: LazyVecFrom2<TxIndex, Weight, TxIndex, StoredU32, TxIndex, StoredU32>,
|
||||||
pub txindex_to_fee: EagerVec<TxIndex, Sats>,
|
pub txindex_to_fee: EagerVec<TxIndex, Sats>,
|
||||||
pub txindex_to_feerate: EagerVec<TxIndex, Feerate>,
|
pub txindex_to_fee_rate: EagerVec<TxIndex, FeeRate>,
|
||||||
pub indexes_to_exact_utxo_count: ComputedVecsFromHeight<StoredU64>,
|
pub indexes_to_exact_utxo_count: ComputedVecsFromHeight<StoredU64>,
|
||||||
|
pub dateindex_to_fee_dominance: EagerVec<DateIndex, StoredF32>,
|
||||||
|
pub dateindex_to_subsidy_dominance: EagerVec<DateIndex, StoredF32>,
|
||||||
|
pub indexes_to_subsidy_usd_1y_sma: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||||
|
pub indexes_to_puell_multiple: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||||
|
pub indexes_to_hash_rate: ComputedVecsFromDateIndex<StoredF64>,
|
||||||
|
pub indexes_to_hash_rate_1w_sma: ComputedVecsFromDateIndex<StoredF64>,
|
||||||
|
pub indexes_to_hash_rate_1m_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
|
pub indexes_to_hash_rate_2m_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
|
pub indexes_to_hash_rate_1y_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
|
pub indexes_to_difficulty_as_hash: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vecs {
|
impl Vecs {
|
||||||
@@ -77,7 +122,7 @@ impl Vecs {
|
|||||||
indexes: &indexes::Vecs,
|
indexes: &indexes::Vecs,
|
||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let db = Database::open(&parent.join("transactions"))?;
|
let db = Database::open(&parent.join("chain"))?;
|
||||||
db.set_min_len(PAGE_SIZE * 10_000_000)?;
|
db.set_min_len(PAGE_SIZE * 10_000_000)?;
|
||||||
|
|
||||||
let compute_dollars = price.is_some();
|
let compute_dollars = price.is_some();
|
||||||
@@ -262,10 +307,205 @@ impl Vecs {
|
|||||||
let txindex_to_fee =
|
let txindex_to_fee =
|
||||||
EagerVec::forced_import_compressed(&db, "fee", version + VERSION + Version::ZERO)?;
|
EagerVec::forced_import_compressed(&db, "fee", version + VERSION + Version::ZERO)?;
|
||||||
|
|
||||||
let txindex_to_feerate =
|
let txindex_to_fee_rate =
|
||||||
EagerVec::forced_import_compressed(&db, "feerate", version + VERSION + Version::ZERO)?;
|
EagerVec::forced_import_compressed(&db, "fee_rate", version + VERSION + Version::ZERO)?;
|
||||||
|
|
||||||
Ok(Self {
|
let dateindex_to_block_count_target = LazyVecFrom1::init(
|
||||||
|
"block_count_target",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes.dateindex_to_dateindex.boxed_clone(),
|
||||||
|
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DAY)),
|
||||||
|
);
|
||||||
|
let weekindex_to_block_count_target = LazyVecFrom1::init(
|
||||||
|
"block_count_target",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes.weekindex_to_weekindex.boxed_clone(),
|
||||||
|
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_WEEK)),
|
||||||
|
);
|
||||||
|
let monthindex_to_block_count_target = LazyVecFrom1::init(
|
||||||
|
"block_count_target",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes.monthindex_to_monthindex.boxed_clone(),
|
||||||
|
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_MONTH)),
|
||||||
|
);
|
||||||
|
let quarterindex_to_block_count_target = LazyVecFrom1::init(
|
||||||
|
"block_count_target",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes.quarterindex_to_quarterindex.boxed_clone(),
|
||||||
|
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_QUARTER)),
|
||||||
|
);
|
||||||
|
let semesterindex_to_block_count_target = LazyVecFrom1::init(
|
||||||
|
"block_count_target",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes.semesterindex_to_semesterindex.boxed_clone(),
|
||||||
|
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_SEMESTER)),
|
||||||
|
);
|
||||||
|
let yearindex_to_block_count_target = LazyVecFrom1::init(
|
||||||
|
"block_count_target",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes.yearindex_to_yearindex.boxed_clone(),
|
||||||
|
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_YEAR)),
|
||||||
|
);
|
||||||
|
let decadeindex_to_block_count_target = LazyVecFrom1::init(
|
||||||
|
"block_count_target",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes.decadeindex_to_decadeindex.boxed_clone(),
|
||||||
|
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DECADE)),
|
||||||
|
);
|
||||||
|
|
||||||
|
let this = Self {
|
||||||
|
dateindex_to_block_count_target,
|
||||||
|
weekindex_to_block_count_target,
|
||||||
|
monthindex_to_block_count_target,
|
||||||
|
quarterindex_to_block_count_target,
|
||||||
|
semesterindex_to_block_count_target,
|
||||||
|
yearindex_to_block_count_target,
|
||||||
|
decadeindex_to_block_count_target,
|
||||||
|
height_to_interval: EagerVec::forced_import_compressed(
|
||||||
|
&db,
|
||||||
|
"interval",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
)?,
|
||||||
|
timeindexes_to_timestamp: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"timestamp",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_first(),
|
||||||
|
)?,
|
||||||
|
indexes_to_block_interval: ComputedVecsFromHeight::forced_import(
|
||||||
|
&db,
|
||||||
|
"block_interval",
|
||||||
|
Source::None,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default()
|
||||||
|
.add_percentiles()
|
||||||
|
.add_minmax()
|
||||||
|
.add_average(),
|
||||||
|
)?,
|
||||||
|
indexes_to_block_count: ComputedVecsFromHeight::forced_import(
|
||||||
|
&db,
|
||||||
|
"block_count",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_sum().add_cumulative(),
|
||||||
|
)?,
|
||||||
|
indexes_to_1w_block_count: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"1w_block_count",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_1m_block_count: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"1m_block_count",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_1y_block_count: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"1y_block_count",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_block_weight: ComputedVecsFromHeight::forced_import(
|
||||||
|
&db,
|
||||||
|
"block_weight",
|
||||||
|
Source::None,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default()
|
||||||
|
.add_sum()
|
||||||
|
.add_minmax()
|
||||||
|
.add_average()
|
||||||
|
.add_percentiles()
|
||||||
|
.add_cumulative(),
|
||||||
|
)?,
|
||||||
|
indexes_to_block_size: ComputedVecsFromHeight::forced_import(
|
||||||
|
&db,
|
||||||
|
"block_size",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default()
|
||||||
|
.add_sum()
|
||||||
|
.add_minmax()
|
||||||
|
.add_average()
|
||||||
|
.add_percentiles()
|
||||||
|
.add_cumulative(),
|
||||||
|
)?,
|
||||||
|
height_to_vbytes: EagerVec::forced_import_compressed(
|
||||||
|
&db,
|
||||||
|
"vbytes",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
)?,
|
||||||
|
indexes_to_block_vbytes: ComputedVecsFromHeight::forced_import(
|
||||||
|
&db,
|
||||||
|
"block_vbytes",
|
||||||
|
Source::None,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default()
|
||||||
|
.add_sum()
|
||||||
|
.add_minmax()
|
||||||
|
.add_average()
|
||||||
|
.add_percentiles()
|
||||||
|
.add_cumulative(),
|
||||||
|
)?,
|
||||||
|
difficultyepoch_to_timestamp: EagerVec::forced_import_compressed(
|
||||||
|
&db,
|
||||||
|
"timestamp",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
)?,
|
||||||
|
halvingepoch_to_timestamp: EagerVec::forced_import_compressed(
|
||||||
|
&db,
|
||||||
|
"timestamp",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
)?,
|
||||||
|
|
||||||
|
dateindex_to_fee_dominance: EagerVec::forced_import_compressed(
|
||||||
|
&db,
|
||||||
|
"fee_dominance",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
)?,
|
||||||
|
dateindex_to_subsidy_dominance: EagerVec::forced_import_compressed(
|
||||||
|
&db,
|
||||||
|
"subsidy_dominance",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
)?,
|
||||||
|
indexes_to_difficulty: ComputedVecsFromHeight::forced_import(
|
||||||
|
&db,
|
||||||
|
"difficulty",
|
||||||
|
Source::None,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_difficultyepoch: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"difficultyepoch",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_halvingepoch: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"halvingepoch",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
indexes_to_tx_count: ComputedVecsFromHeight::forced_import(
|
indexes_to_tx_count: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"tx_count",
|
"tx_count",
|
||||||
@@ -343,9 +583,9 @@ impl Vecs {
|
|||||||
.add_minmax()
|
.add_minmax()
|
||||||
.add_average(),
|
.add_average(),
|
||||||
)?,
|
)?,
|
||||||
indexes_to_feerate: ComputedVecsFromTxindex::forced_import(
|
indexes_to_fee_rate: ComputedVecsFromTxindex::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"feerate",
|
"fee_rate",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -577,6 +817,77 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
VecBuilderOptions::default().add_last(),
|
VecBuilderOptions::default().add_last(),
|
||||||
)?,
|
)?,
|
||||||
|
indexes_to_subsidy_usd_1y_sma: compute_dollars.then(|| {
|
||||||
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"subsidy_usd_1y_sma",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}),
|
||||||
|
indexes_to_puell_multiple: compute_dollars.then(|| {
|
||||||
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"puell_multiple",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}),
|
||||||
|
indexes_to_hash_rate: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"hash_rate",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ONE,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_hash_rate_1w_sma: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"hash_rate_1w_sma",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_hash_rate_1m_sma: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"hash_rate_1m_sma",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_hash_rate_2m_sma: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"hash_rate_2m_sma",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_hash_rate_1y_sma: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"hash_rate_1y_sma",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_difficulty_as_hash: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"difficulty_as_hash",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
|
||||||
txindex_to_is_coinbase,
|
txindex_to_is_coinbase,
|
||||||
inputindex_to_value,
|
inputindex_to_value,
|
||||||
// indexes_to_input_value,
|
// indexes_to_input_value,
|
||||||
@@ -584,12 +895,21 @@ impl Vecs {
|
|||||||
txindex_to_input_value,
|
txindex_to_input_value,
|
||||||
txindex_to_output_value,
|
txindex_to_output_value,
|
||||||
txindex_to_fee,
|
txindex_to_fee,
|
||||||
txindex_to_feerate,
|
txindex_to_fee_rate,
|
||||||
txindex_to_vsize,
|
txindex_to_vsize,
|
||||||
txindex_to_weight,
|
txindex_to_weight,
|
||||||
|
|
||||||
db,
|
db,
|
||||||
})
|
};
|
||||||
|
|
||||||
|
this.db.retain_regions(
|
||||||
|
this.vecs()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|v| v.region_names())
|
||||||
|
.collect(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute(
|
pub fn compute(
|
||||||
@@ -613,6 +933,215 @@ impl Vecs {
|
|||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
self.timeindexes_to_timestamp.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, indexes, starting_indexes, exit| {
|
||||||
|
vec.compute_transform(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
&indexes.dateindex_to_date,
|
||||||
|
|(di, d, ..)| (di, Timestamp::from(d)),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_block_count.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, indexer, _, starting_indexes, exit| {
|
||||||
|
v.compute_range(
|
||||||
|
starting_indexes.height,
|
||||||
|
&indexer.vecs.height_to_weight,
|
||||||
|
|h| (h, StoredU32::from(1_u32)),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_1w_block_count.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_sum(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_block_count.dateindex.unwrap_sum(),
|
||||||
|
7,
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_1m_block_count.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_sum(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_block_count.dateindex.unwrap_sum(),
|
||||||
|
30,
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_1y_block_count.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_sum(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_block_count.dateindex.unwrap_sum(),
|
||||||
|
365,
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
|
||||||
|
self.height_to_interval.compute_transform(
|
||||||
|
starting_indexes.height,
|
||||||
|
&indexer.vecs.height_to_timestamp,
|
||||||
|
|(height, timestamp, ..)| {
|
||||||
|
let interval = height.decremented().map_or(Timestamp::ZERO, |prev_h| {
|
||||||
|
let prev_timestamp = height_to_timestamp_iter.unwrap_get_inner(prev_h);
|
||||||
|
timestamp
|
||||||
|
.checked_sub(prev_timestamp)
|
||||||
|
.unwrap_or(Timestamp::ZERO)
|
||||||
|
});
|
||||||
|
(height, interval)
|
||||||
|
},
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_block_interval.compute_rest(
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
Some(&self.height_to_interval),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_block_weight.compute_rest(
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
Some(&indexer.vecs.height_to_weight),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_block_size.compute_rest(
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
Some(&indexer.vecs.height_to_total_size),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.height_to_vbytes.compute_transform(
|
||||||
|
starting_indexes.height,
|
||||||
|
&indexer.vecs.height_to_weight,
|
||||||
|
|(h, w, ..)| {
|
||||||
|
(
|
||||||
|
h,
|
||||||
|
StoredU64::from(bitcoin::Weight::from(w).to_vbytes_floor()),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_block_vbytes.compute_rest(
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
Some(&self.height_to_vbytes),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
|
||||||
|
|
||||||
|
self.difficultyepoch_to_timestamp.compute_transform(
|
||||||
|
starting_indexes.difficultyepoch,
|
||||||
|
&indexes.difficultyepoch_to_first_height,
|
||||||
|
|(i, h, ..)| (i, height_to_timestamp_iter.unwrap_get_inner(h)),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.halvingepoch_to_timestamp.compute_transform(
|
||||||
|
starting_indexes.halvingepoch,
|
||||||
|
&indexes.halvingepoch_to_first_height,
|
||||||
|
|(i, h, ..)| (i, height_to_timestamp_iter.unwrap_get_inner(h)),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut height_to_difficultyepoch_iter = indexes.height_to_difficultyepoch.into_iter();
|
||||||
|
self.indexes_to_difficultyepoch.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, indexes, starting_indexes, exit| {
|
||||||
|
let mut height_count_iter = indexes.dateindex_to_height_count.into_iter();
|
||||||
|
vec.compute_transform(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
&indexes.dateindex_to_first_height,
|
||||||
|
|(di, height, ..)| {
|
||||||
|
(
|
||||||
|
di,
|
||||||
|
height_to_difficultyepoch_iter.unwrap_get_inner(
|
||||||
|
height + (*height_count_iter.unwrap_get_inner(di) - 1),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut height_to_halvingepoch_iter = indexes.height_to_halvingepoch.into_iter();
|
||||||
|
self.indexes_to_halvingepoch.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, indexes, starting_indexes, exit| {
|
||||||
|
let mut height_count_iter = indexes.dateindex_to_height_count.into_iter();
|
||||||
|
vec.compute_transform(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
&indexes.dateindex_to_first_height,
|
||||||
|
|(di, height, ..)| {
|
||||||
|
(
|
||||||
|
di,
|
||||||
|
height_to_halvingepoch_iter.unwrap_get_inner(
|
||||||
|
height + (*height_count_iter.unwrap_get_inner(di) - 1),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_difficulty.compute_rest(
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
Some(&indexer.vecs.height_to_difficulty),
|
||||||
|
)?;
|
||||||
|
|
||||||
self.indexes_to_tx_count.compute_all(
|
self.indexes_to_tx_count.compute_all(
|
||||||
indexer,
|
indexer,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -722,11 +1251,11 @@ impl Vecs {
|
|||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.txindex_to_feerate.compute_transform2(
|
self.txindex_to_fee_rate.compute_transform2(
|
||||||
starting_indexes.txindex,
|
starting_indexes.txindex,
|
||||||
&self.txindex_to_fee,
|
&self.txindex_to_fee,
|
||||||
&self.txindex_to_vsize,
|
&self.txindex_to_vsize,
|
||||||
|(txindex, fee, vsize, ..)| (txindex, Feerate::from((fee, vsize))),
|
|(txindex, fee, vsize, ..)| (txindex, FeeRate::from((fee, vsize))),
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -739,12 +1268,12 @@ impl Vecs {
|
|||||||
price,
|
price,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.indexes_to_feerate.compute_rest(
|
self.indexes_to_fee_rate.compute_rest(
|
||||||
indexer,
|
indexer,
|
||||||
indexes,
|
indexes,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
Some(&self.txindex_to_feerate),
|
Some(&self.txindex_to_fee_rate),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.indexes_to_tx_weight.compute_rest(
|
self.indexes_to_tx_weight.compute_rest(
|
||||||
@@ -1085,25 +1614,251 @@ impl Vecs {
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
self.dateindex_to_fee_dominance.compute_transform2(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_fee.sats.dateindex.unwrap_sum(),
|
||||||
|
self.indexes_to_coinbase.sats.dateindex.unwrap_sum(),
|
||||||
|
|(i, fee, coinbase, ..)| {
|
||||||
|
(
|
||||||
|
i,
|
||||||
|
StoredF32::from(u64::from(fee) as f64 / u64::from(coinbase) as f64 * 100.0),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
self.dateindex_to_subsidy_dominance.compute_transform2(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_subsidy.sats.dateindex.unwrap_sum(),
|
||||||
|
self.indexes_to_coinbase.sats.dateindex.unwrap_sum(),
|
||||||
|
|(i, subsidy, coinbase, ..)| {
|
||||||
|
(
|
||||||
|
i,
|
||||||
|
StoredF32::from(u64::from(subsidy) as f64 / u64::from(coinbase) as f64 * 100.0),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_difficulty_as_hash.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
let multiplier = 2.0_f64.powi(32) / 600.0;
|
||||||
|
v.compute_transform(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_difficulty.dateindex.unwrap_last(),
|
||||||
|
|(i, v, ..)| (i, StoredF32::from(*v * multiplier)),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let now = Timestamp::now();
|
||||||
|
let today = Date::from(now);
|
||||||
|
self.indexes_to_hash_rate.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_transform3(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_block_count.dateindex.unwrap_sum(),
|
||||||
|
self.indexes_to_difficulty_as_hash
|
||||||
|
.dateindex
|
||||||
|
.as_ref()
|
||||||
|
.unwrap(),
|
||||||
|
&indexes.dateindex_to_date,
|
||||||
|
|(i, block_count_sum, difficulty_as_hash, date, ..)| {
|
||||||
|
let target_multiplier = if date == today {
|
||||||
|
now.day_completion()
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
};
|
||||||
|
(
|
||||||
|
i,
|
||||||
|
StoredF64::from(
|
||||||
|
(f64::from(block_count_sum)
|
||||||
|
/ (target_multiplier * TARGET_BLOCKS_PER_DAY_F64))
|
||||||
|
* f64::from(difficulty_as_hash),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_hash_rate_1w_sma.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_sma(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_hash_rate.dateindex.as_ref().unwrap(),
|
||||||
|
7,
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_hash_rate_1m_sma.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_sma(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_hash_rate.dateindex.as_ref().unwrap(),
|
||||||
|
30,
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_hash_rate_2m_sma.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_sma(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_hash_rate.dateindex.as_ref().unwrap(),
|
||||||
|
2 * 30,
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_hash_rate_1y_sma.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_sma(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_hash_rate.dateindex.as_ref().unwrap(),
|
||||||
|
365,
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if self.indexes_to_subsidy_usd_1y_sma.is_some() {
|
||||||
|
let date_to_coinbase_usd_sum = self
|
||||||
|
.indexes_to_coinbase
|
||||||
|
.dollars
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.dateindex
|
||||||
|
.unwrap_sum();
|
||||||
|
|
||||||
|
self.indexes_to_subsidy_usd_1y_sma
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_sma(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
date_to_coinbase_usd_sum,
|
||||||
|
365,
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_puell_multiple
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_divide(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
date_to_coinbase_usd_sum,
|
||||||
|
self.indexes_to_subsidy_usd_1y_sma
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.dateindex
|
||||||
|
.as_ref()
|
||||||
|
.unwrap(),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||||
[
|
[
|
||||||
vec![
|
vec![
|
||||||
&self.inputindex_to_value as &dyn AnyCollectableVec,
|
&self.height_to_interval as &dyn AnyCollectableVec,
|
||||||
|
&self.height_to_vbytes,
|
||||||
|
&self.difficultyepoch_to_timestamp,
|
||||||
|
&self.halvingepoch_to_timestamp,
|
||||||
|
&self.inputindex_to_value,
|
||||||
&self.txindex_to_fee,
|
&self.txindex_to_fee,
|
||||||
&self.txindex_to_feerate,
|
&self.txindex_to_fee_rate,
|
||||||
&self.txindex_to_input_value,
|
&self.txindex_to_input_value,
|
||||||
&self.txindex_to_is_coinbase,
|
&self.txindex_to_is_coinbase,
|
||||||
&self.txindex_to_output_value,
|
&self.txindex_to_output_value,
|
||||||
&self.txindex_to_vsize,
|
&self.txindex_to_vsize,
|
||||||
&self.txindex_to_weight,
|
&self.txindex_to_weight,
|
||||||
|
&self.dateindex_to_fee_dominance,
|
||||||
|
&self.dateindex_to_subsidy_dominance,
|
||||||
|
&self.dateindex_to_block_count_target,
|
||||||
|
&self.weekindex_to_block_count_target,
|
||||||
|
&self.monthindex_to_block_count_target,
|
||||||
|
&self.quarterindex_to_block_count_target,
|
||||||
|
&self.semesterindex_to_block_count_target,
|
||||||
|
&self.yearindex_to_block_count_target,
|
||||||
|
&self.decadeindex_to_block_count_target,
|
||||||
],
|
],
|
||||||
|
self.indexes_to_hash_rate.vecs(),
|
||||||
|
self.indexes_to_hash_rate_1w_sma.vecs(),
|
||||||
|
self.indexes_to_hash_rate_1m_sma.vecs(),
|
||||||
|
self.indexes_to_hash_rate_2m_sma.vecs(),
|
||||||
|
self.indexes_to_hash_rate_1y_sma.vecs(),
|
||||||
|
self.timeindexes_to_timestamp.vecs(),
|
||||||
|
self.indexes_to_block_count.vecs(),
|
||||||
|
self.indexes_to_1w_block_count.vecs(),
|
||||||
|
self.indexes_to_1m_block_count.vecs(),
|
||||||
|
self.indexes_to_1y_block_count.vecs(),
|
||||||
|
self.indexes_to_block_interval.vecs(),
|
||||||
|
self.indexes_to_block_size.vecs(),
|
||||||
|
self.indexes_to_block_vbytes.vecs(),
|
||||||
|
self.indexes_to_block_weight.vecs(),
|
||||||
|
self.indexes_to_difficulty.vecs(),
|
||||||
|
self.indexes_to_difficultyepoch.vecs(),
|
||||||
|
self.indexes_to_halvingepoch.vecs(),
|
||||||
self.indexes_to_coinbase.vecs(),
|
self.indexes_to_coinbase.vecs(),
|
||||||
self.indexes_to_emptyoutput_count.vecs(),
|
self.indexes_to_emptyoutput_count.vecs(),
|
||||||
self.indexes_to_fee.vecs(),
|
self.indexes_to_fee.vecs(),
|
||||||
self.indexes_to_feerate.vecs(),
|
self.indexes_to_fee_rate.vecs(),
|
||||||
self.indexes_to_input_count.vecs(),
|
self.indexes_to_input_count.vecs(),
|
||||||
self.indexes_to_opreturn_count.vecs(),
|
self.indexes_to_opreturn_count.vecs(),
|
||||||
self.indexes_to_output_count.vecs(),
|
self.indexes_to_output_count.vecs(),
|
||||||
@@ -1111,6 +1866,7 @@ impl Vecs {
|
|||||||
self.indexes_to_p2ms_count.vecs(),
|
self.indexes_to_p2ms_count.vecs(),
|
||||||
self.indexes_to_p2pk33_count.vecs(),
|
self.indexes_to_p2pk33_count.vecs(),
|
||||||
self.indexes_to_p2pk65_count.vecs(),
|
self.indexes_to_p2pk65_count.vecs(),
|
||||||
|
self.indexes_to_difficulty_as_hash.vecs(),
|
||||||
self.indexes_to_p2pkh_count.vecs(),
|
self.indexes_to_p2pkh_count.vecs(),
|
||||||
self.indexes_to_p2sh_count.vecs(),
|
self.indexes_to_p2sh_count.vecs(),
|
||||||
self.indexes_to_p2tr_count.vecs(),
|
self.indexes_to_p2tr_count.vecs(),
|
||||||
@@ -1126,6 +1882,12 @@ impl Vecs {
|
|||||||
self.indexes_to_unknownoutput_count.vecs(),
|
self.indexes_to_unknownoutput_count.vecs(),
|
||||||
self.indexes_to_exact_utxo_count.vecs(),
|
self.indexes_to_exact_utxo_count.vecs(),
|
||||||
self.indexes_to_unclaimed_rewards.vecs(),
|
self.indexes_to_unclaimed_rewards.vecs(),
|
||||||
|
self.indexes_to_subsidy_usd_1y_sma
|
||||||
|
.as_ref()
|
||||||
|
.map_or(vec![], |v| v.vecs()),
|
||||||
|
self.indexes_to_puell_multiple
|
||||||
|
.as_ref()
|
||||||
|
.map_or(vec![], |v| v.vecs()),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
@@ -6,12 +6,12 @@ use brk_structs::{Bitcoin, CheckedSub, Dollars, StoredF64, Version};
|
|||||||
use vecdb::{AnyCollectableVec, Database, Exit, PAGE_SIZE, VecIterator};
|
use vecdb::{AnyCollectableVec, Database, Exit, PAGE_SIZE, VecIterator};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Indexes,
|
Indexes, chain,
|
||||||
grouped::{
|
grouped::{
|
||||||
ComputedRatioVecsFromDateIndex, ComputedValueVecsFromHeight, ComputedVecsFromHeight,
|
ComputedRatioVecsFromDateIndex, ComputedValueVecsFromHeight, ComputedVecsFromHeight,
|
||||||
Source, VecBuilderOptions,
|
Source, VecBuilderOptions,
|
||||||
},
|
},
|
||||||
indexes, price, stateful, transactions,
|
indexes, price, stateful,
|
||||||
};
|
};
|
||||||
|
|
||||||
const VERSION: Version = Version::ZERO;
|
const VERSION: Version = Version::ZERO;
|
||||||
@@ -43,7 +43,7 @@ pub struct Vecs {
|
|||||||
pub indexes_to_cointime_price: ComputedVecsFromHeight<Dollars>,
|
pub indexes_to_cointime_price: ComputedVecsFromHeight<Dollars>,
|
||||||
pub indexes_to_cointime_cap: ComputedVecsFromHeight<Dollars>,
|
pub indexes_to_cointime_cap: ComputedVecsFromHeight<Dollars>,
|
||||||
pub indexes_to_cointime_price_ratio: ComputedRatioVecsFromDateIndex,
|
pub indexes_to_cointime_price_ratio: ComputedRatioVecsFromDateIndex,
|
||||||
// pub indexes_to_thermo_cap_relative_to_investor_cap: ComputedValueVecsFromHeight,
|
// pub indexes_to_thermo_cap_rel_to_investor_cap: ComputedValueVecsFromHeight,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vecs {
|
impl Vecs {
|
||||||
@@ -58,7 +58,7 @@ impl Vecs {
|
|||||||
|
|
||||||
let compute_dollars = price.is_some();
|
let compute_dollars = price.is_some();
|
||||||
|
|
||||||
Ok(Self {
|
let this = Self {
|
||||||
indexes_to_coinblocks_created: ComputedVecsFromHeight::forced_import(
|
indexes_to_coinblocks_created: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"coinblocks_created",
|
"coinblocks_created",
|
||||||
@@ -247,7 +247,16 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
|
|
||||||
db,
|
db,
|
||||||
})
|
};
|
||||||
|
|
||||||
|
this.db.retain_regions(
|
||||||
|
this.vecs()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|v| v.region_names())
|
||||||
|
.collect(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
@@ -257,7 +266,7 @@ impl Vecs {
|
|||||||
indexes: &indexes::Vecs,
|
indexes: &indexes::Vecs,
|
||||||
starting_indexes: &Indexes,
|
starting_indexes: &Indexes,
|
||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
transactions: &transactions::Vecs,
|
chain: &chain::Vecs,
|
||||||
stateful: &stateful::Vecs,
|
stateful: &stateful::Vecs,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
@@ -266,7 +275,7 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
price,
|
price,
|
||||||
transactions,
|
chain,
|
||||||
stateful,
|
stateful,
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
@@ -281,7 +290,7 @@ impl Vecs {
|
|||||||
indexes: &indexes::Vecs,
|
indexes: &indexes::Vecs,
|
||||||
starting_indexes: &Indexes,
|
starting_indexes: &Indexes,
|
||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
transactions: &transactions::Vecs,
|
chain: &chain::Vecs,
|
||||||
stateful: &stateful::Vecs,
|
stateful: &stateful::Vecs,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
@@ -446,7 +455,7 @@ impl Vecs {
|
|||||||
|vec, _, _, starting_indexes, exit| {
|
|vec, _, _, starting_indexes, exit| {
|
||||||
vec.compute_transform(
|
vec.compute_transform(
|
||||||
starting_indexes.height,
|
starting_indexes.height,
|
||||||
transactions
|
chain
|
||||||
.indexes_to_subsidy
|
.indexes_to_subsidy
|
||||||
.dollars
|
.dollars
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -597,7 +606,7 @@ impl Vecs {
|
|||||||
// The price taken won't be correct for time based indexes
|
// The price taken won't be correct for time based indexes
|
||||||
vec.compute_multiply(
|
vec.compute_multiply(
|
||||||
starting_indexes.height,
|
starting_indexes.height,
|
||||||
&price.chainindexes_to_close.height,
|
&price.chainindexes_to_price_close.height,
|
||||||
indexes_to_coinblocks_destroyed.height.as_ref().unwrap(),
|
indexes_to_coinblocks_destroyed.height.as_ref().unwrap(),
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
@@ -613,7 +622,7 @@ impl Vecs {
|
|||||||
|vec, _, _, starting_indexes, exit| {
|
|vec, _, _, starting_indexes, exit| {
|
||||||
vec.compute_multiply(
|
vec.compute_multiply(
|
||||||
starting_indexes.height,
|
starting_indexes.height,
|
||||||
&price.chainindexes_to_close.height,
|
&price.chainindexes_to_price_close.height,
|
||||||
self.indexes_to_coinblocks_created.height.as_ref().unwrap(),
|
self.indexes_to_coinblocks_created.height.as_ref().unwrap(),
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
@@ -629,7 +638,7 @@ impl Vecs {
|
|||||||
|vec, _, _, starting_indexes, exit| {
|
|vec, _, _, starting_indexes, exit| {
|
||||||
vec.compute_multiply(
|
vec.compute_multiply(
|
||||||
starting_indexes.height,
|
starting_indexes.height,
|
||||||
&price.chainindexes_to_close.height,
|
&price.chainindexes_to_price_close.height,
|
||||||
self.indexes_to_coinblocks_stored.height.as_ref().unwrap(),
|
self.indexes_to_coinblocks_stored.height.as_ref().unwrap(),
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ pub struct Vecs {
|
|||||||
pub constant_4: ComputedVecsFromHeight<StoredU16>,
|
pub constant_4: ComputedVecsFromHeight<StoredU16>,
|
||||||
pub constant_50: ComputedVecsFromHeight<StoredU16>,
|
pub constant_50: ComputedVecsFromHeight<StoredU16>,
|
||||||
pub constant_100: ComputedVecsFromHeight<StoredU16>,
|
pub constant_100: ComputedVecsFromHeight<StoredU16>,
|
||||||
|
pub constant_600: ComputedVecsFromHeight<StoredU16>,
|
||||||
pub constant_minus_1: ComputedVecsFromHeight<StoredI16>,
|
pub constant_minus_1: ComputedVecsFromHeight<StoredI16>,
|
||||||
pub constant_minus_2: ComputedVecsFromHeight<StoredI16>,
|
pub constant_minus_2: ComputedVecsFromHeight<StoredI16>,
|
||||||
pub constant_minus_3: ComputedVecsFromHeight<StoredI16>,
|
pub constant_minus_3: ComputedVecsFromHeight<StoredI16>,
|
||||||
@@ -36,7 +37,7 @@ impl Vecs {
|
|||||||
pub fn forced_import(parent: &Path, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
|
pub fn forced_import(parent: &Path, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
|
||||||
let db = Database::open(&parent.join("constants"))?;
|
let db = Database::open(&parent.join("constants"))?;
|
||||||
|
|
||||||
Ok(Self {
|
let this = Self {
|
||||||
constant_0: ComputedVecsFromHeight::forced_import(
|
constant_0: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"constant_0",
|
"constant_0",
|
||||||
@@ -93,6 +94,14 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
VecBuilderOptions::default().add_last(),
|
VecBuilderOptions::default().add_last(),
|
||||||
)?,
|
)?,
|
||||||
|
constant_600: ComputedVecsFromHeight::forced_import(
|
||||||
|
&db,
|
||||||
|
"constant_600",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
constant_minus_1: ComputedVecsFromHeight::forced_import(
|
constant_minus_1: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"constant_minus_1",
|
"constant_minus_1",
|
||||||
@@ -127,7 +136,16 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
|
|
||||||
db,
|
db,
|
||||||
})
|
};
|
||||||
|
|
||||||
|
this.db.retain_regions(
|
||||||
|
this.vecs()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|v| v.region_names())
|
||||||
|
.collect(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute(
|
pub fn compute(
|
||||||
@@ -149,192 +167,61 @@ impl Vecs {
|
|||||||
starting_indexes: &Indexes,
|
starting_indexes: &Indexes,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.constant_0.compute_all(
|
[
|
||||||
indexer,
|
(&mut self.constant_0, 0),
|
||||||
indexes,
|
(&mut self.constant_1, 1),
|
||||||
starting_indexes,
|
(&mut self.constant_2, 2),
|
||||||
exit,
|
(&mut self.constant_3, 3),
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
(&mut self.constant_4, 4),
|
||||||
vec.compute_to(
|
(&mut self.constant_50, 50),
|
||||||
starting_indexes.height,
|
(&mut self.constant_100, 100),
|
||||||
indexes.height_to_date.len(),
|
(&mut self.constant_600, 600),
|
||||||
indexes.height_to_date.version(),
|
]
|
||||||
|i| (i, StoredU16::new(0)),
|
.into_iter()
|
||||||
exit,
|
.try_for_each(|(vec, value)| {
|
||||||
)?;
|
vec.compute_all(
|
||||||
Ok(())
|
indexer,
|
||||||
},
|
indexes,
|
||||||
)?;
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, indexes, starting_indexes, exit| {
|
||||||
|
vec.compute_to(
|
||||||
|
starting_indexes.height,
|
||||||
|
indexes.height_to_date.len(),
|
||||||
|
indexes.height_to_date.version(),
|
||||||
|
|i| (i, StoredU16::new(value)),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
self.constant_1.compute_all(
|
[
|
||||||
indexer,
|
(&mut self.constant_minus_1, -1),
|
||||||
indexes,
|
(&mut self.constant_minus_2, -2),
|
||||||
starting_indexes,
|
(&mut self.constant_minus_3, 3),
|
||||||
exit,
|
(&mut self.constant_minus_4, 4),
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
]
|
||||||
vec.compute_to(
|
.into_iter()
|
||||||
starting_indexes.height,
|
.try_for_each(|(vec, value)| {
|
||||||
indexes.height_to_date.len(),
|
vec.compute_all(
|
||||||
indexes.height_to_date.version(),
|
indexer,
|
||||||
|i| (i, StoredU16::new(1)),
|
indexes,
|
||||||
exit,
|
starting_indexes,
|
||||||
)?;
|
exit,
|
||||||
Ok(())
|
|vec, _, indexes, starting_indexes, exit| {
|
||||||
},
|
vec.compute_to(
|
||||||
)?;
|
starting_indexes.height,
|
||||||
|
indexes.height_to_date.len(),
|
||||||
self.constant_2.compute_all(
|
indexes.height_to_date.version(),
|
||||||
indexer,
|
|i| (i, StoredI16::new(value)),
|
||||||
indexes,
|
exit,
|
||||||
starting_indexes,
|
)?;
|
||||||
exit,
|
Ok(())
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
},
|
||||||
vec.compute_to(
|
)
|
||||||
starting_indexes.height,
|
})?;
|
||||||
indexes.height_to_date.len(),
|
|
||||||
indexes.height_to_date.version(),
|
|
||||||
|i| (i, StoredU16::new(2)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.constant_3.compute_all(
|
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
|
||||||
vec.compute_to(
|
|
||||||
starting_indexes.height,
|
|
||||||
indexes.height_to_date.len(),
|
|
||||||
indexes.height_to_date.version(),
|
|
||||||
|i| (i, StoredU16::new(3)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.constant_4.compute_all(
|
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
|
||||||
vec.compute_to(
|
|
||||||
starting_indexes.height,
|
|
||||||
indexes.height_to_date.len(),
|
|
||||||
indexes.height_to_date.version(),
|
|
||||||
|i| (i, StoredU16::new(4)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.constant_50.compute_all(
|
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
|
||||||
vec.compute_to(
|
|
||||||
starting_indexes.height,
|
|
||||||
indexes.height_to_date.len(),
|
|
||||||
indexes.height_to_date.version(),
|
|
||||||
|i| (i, StoredU16::new(50)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.constant_100.compute_all(
|
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
|
||||||
vec.compute_to(
|
|
||||||
starting_indexes.height,
|
|
||||||
indexes.height_to_date.len(),
|
|
||||||
indexes.height_to_date.version(),
|
|
||||||
|i| (i, StoredU16::new(100)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.constant_minus_1.compute_all(
|
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
|
||||||
vec.compute_to(
|
|
||||||
starting_indexes.height,
|
|
||||||
indexes.height_to_date.len(),
|
|
||||||
indexes.height_to_date.version(),
|
|
||||||
|i| (i, StoredI16::new(-1)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.constant_minus_2.compute_all(
|
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
|
||||||
vec.compute_to(
|
|
||||||
starting_indexes.height,
|
|
||||||
indexes.height_to_date.len(),
|
|
||||||
indexes.height_to_date.version(),
|
|
||||||
|i| (i, StoredI16::new(-2)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.constant_minus_3.compute_all(
|
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
|
||||||
vec.compute_to(
|
|
||||||
starting_indexes.height,
|
|
||||||
indexes.height_to_date.len(),
|
|
||||||
indexes.height_to_date.version(),
|
|
||||||
|i| (i, StoredI16::new(-3)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.constant_minus_4.compute_all(
|
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
|
||||||
vec.compute_to(
|
|
||||||
starting_indexes.height,
|
|
||||||
indexes.height_to_date.len(),
|
|
||||||
indexes.height_to_date.version(),
|
|
||||||
|i| (i, StoredI16::new(-4)),
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -348,6 +235,7 @@ impl Vecs {
|
|||||||
self.constant_4.vecs(),
|
self.constant_4.vecs(),
|
||||||
self.constant_50.vecs(),
|
self.constant_50.vecs(),
|
||||||
self.constant_100.vecs(),
|
self.constant_100.vecs(),
|
||||||
|
self.constant_600.vecs(),
|
||||||
self.constant_minus_1.vecs(),
|
self.constant_minus_1.vecs(),
|
||||||
self.constant_minus_2.vecs(),
|
self.constant_minus_2.vecs(),
|
||||||
self.constant_minus_3.vecs(),
|
self.constant_minus_3.vecs(),
|
||||||
|
|||||||
@@ -16,30 +16,39 @@ pub struct Vecs {
|
|||||||
db: Database,
|
db: Database,
|
||||||
fetcher: Fetcher,
|
fetcher: Fetcher,
|
||||||
|
|
||||||
pub dateindex_to_ohlc_in_cents: RawVec<DateIndex, OHLCCents>,
|
pub dateindex_to_price_ohlc_in_cents: RawVec<DateIndex, OHLCCents>,
|
||||||
pub height_to_ohlc_in_cents: RawVec<Height, OHLCCents>,
|
pub height_to_price_ohlc_in_cents: RawVec<Height, OHLCCents>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vecs {
|
impl Vecs {
|
||||||
pub fn forced_import(parent: &Path, fetcher: Fetcher, version: Version) -> Result<Self> {
|
pub fn forced_import(parent: &Path, fetcher: Fetcher, version: Version) -> Result<Self> {
|
||||||
let db = Database::open(&parent.join("fetched"))?;
|
let db = Database::open(&parent.join("fetched"))?;
|
||||||
|
|
||||||
Ok(Self {
|
let this = Self {
|
||||||
fetcher,
|
fetcher,
|
||||||
|
|
||||||
dateindex_to_ohlc_in_cents: RawVec::forced_import(
|
dateindex_to_price_ohlc_in_cents: RawVec::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"ohlc_in_cents",
|
"price_ohlc_in_cents",
|
||||||
version + Version::ZERO,
|
version + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
height_to_ohlc_in_cents: RawVec::forced_import(
|
height_to_price_ohlc_in_cents: RawVec::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"ohlc_in_cents",
|
"price_ohlc_in_cents",
|
||||||
version + Version::ZERO,
|
version + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
|
|
||||||
db,
|
db,
|
||||||
})
|
};
|
||||||
|
|
||||||
|
this.db.retain_regions(
|
||||||
|
this.vecs()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|v| v.region_names())
|
||||||
|
.collect(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute(
|
pub fn compute(
|
||||||
@@ -64,12 +73,12 @@ impl Vecs {
|
|||||||
let height_to_timestamp = &indexer.vecs.height_to_timestamp;
|
let height_to_timestamp = &indexer.vecs.height_to_timestamp;
|
||||||
let index = starting_indexes
|
let index = starting_indexes
|
||||||
.height
|
.height
|
||||||
.min(Height::from(self.height_to_ohlc_in_cents.len()));
|
.min(Height::from(self.height_to_price_ohlc_in_cents.len()));
|
||||||
height_to_timestamp
|
height_to_timestamp
|
||||||
.iter_at(index)
|
.iter_at(index)
|
||||||
.try_for_each(|(i, v)| -> Result<()> {
|
.try_for_each(|(i, v)| -> Result<()> {
|
||||||
let v = v.into_owned();
|
let v = v.into_owned();
|
||||||
self.height_to_ohlc_in_cents.forced_push_at(
|
self.height_to_price_ohlc_in_cents.forced_push_at(
|
||||||
i,
|
i,
|
||||||
self.fetcher
|
self.fetcher
|
||||||
.get_height(
|
.get_height(
|
||||||
@@ -84,11 +93,11 @@ impl Vecs {
|
|||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
self.height_to_ohlc_in_cents.safe_flush(exit)?;
|
self.height_to_price_ohlc_in_cents.safe_flush(exit)?;
|
||||||
|
|
||||||
let index = starting_indexes
|
let index = starting_indexes
|
||||||
.dateindex
|
.dateindex
|
||||||
.min(DateIndex::from(self.dateindex_to_ohlc_in_cents.len()));
|
.min(DateIndex::from(self.dateindex_to_price_ohlc_in_cents.len()));
|
||||||
let mut prev = None;
|
let mut prev = None;
|
||||||
indexes
|
indexes
|
||||||
.dateindex_to_date
|
.dateindex_to_date
|
||||||
@@ -98,7 +107,7 @@ impl Vecs {
|
|||||||
if prev.is_none() {
|
if prev.is_none() {
|
||||||
let i = i.unwrap_to_usize();
|
let i = i.unwrap_to_usize();
|
||||||
prev.replace(if i > 0 {
|
prev.replace(if i > 0 {
|
||||||
self.dateindex_to_ohlc_in_cents
|
self.dateindex_to_price_ohlc_in_cents
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.unwrap_get_inner_(i - 1)
|
.unwrap_get_inner_(i - 1)
|
||||||
} else {
|
} else {
|
||||||
@@ -106,7 +115,8 @@ impl Vecs {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let ohlc = if i.unwrap_to_usize() + 100 >= self.dateindex_to_ohlc_in_cents.len()
|
let ohlc = if i.unwrap_to_usize() + 100
|
||||||
|
>= self.dateindex_to_price_ohlc_in_cents.len()
|
||||||
&& let Ok(mut ohlc) = self.fetcher.get_date(d)
|
&& let Ok(mut ohlc) = self.fetcher.get_date(d)
|
||||||
{
|
{
|
||||||
let prev_open = *prev.as_ref().unwrap().close;
|
let prev_open = *prev.as_ref().unwrap().close;
|
||||||
@@ -120,20 +130,20 @@ impl Vecs {
|
|||||||
|
|
||||||
prev.replace(ohlc.clone());
|
prev.replace(ohlc.clone());
|
||||||
|
|
||||||
self.dateindex_to_ohlc_in_cents
|
self.dateindex_to_price_ohlc_in_cents
|
||||||
.forced_push_at(i, ohlc, exit)?;
|
.forced_push_at(i, ohlc, exit)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
self.dateindex_to_ohlc_in_cents.safe_flush(exit)?;
|
self.dateindex_to_price_ohlc_in_cents.safe_flush(exit)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||||
vec![
|
vec![
|
||||||
&self.dateindex_to_ohlc_in_cents as &dyn AnyCollectableVec,
|
&self.dateindex_to_price_ohlc_in_cents as &dyn AnyCollectableVec,
|
||||||
&self.height_to_ohlc_in_cents,
|
&self.height_to_price_ohlc_in_cents,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use allocative::Allocative;
|
||||||
use brk_error::{Error, Result};
|
use brk_error::{Error, Result};
|
||||||
use brk_structs::{CheckedSub, StoredU64, Version};
|
use brk_structs::{CheckedSub, StoredU64, Version};
|
||||||
use vecdb::{
|
use vecdb::{
|
||||||
@@ -9,7 +10,7 @@ use crate::utils::get_percentile;
|
|||||||
|
|
||||||
use super::ComputedType;
|
use super::ComputedType;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Allocative)]
|
||||||
pub struct EagerVecBuilder<I, T>
|
pub struct EagerVecBuilder<I, T>
|
||||||
where
|
where
|
||||||
I: StoredIndex,
|
I: StoredIndex,
|
||||||
@@ -19,11 +20,11 @@ where
|
|||||||
pub average: Option<Box<EagerVec<I, T>>>,
|
pub average: Option<Box<EagerVec<I, T>>>,
|
||||||
pub sum: Option<Box<EagerVec<I, T>>>,
|
pub sum: Option<Box<EagerVec<I, T>>>,
|
||||||
pub max: Option<Box<EagerVec<I, T>>>,
|
pub max: Option<Box<EagerVec<I, T>>>,
|
||||||
pub _90p: Option<Box<EagerVec<I, T>>>,
|
pub p90: Option<Box<EagerVec<I, T>>>,
|
||||||
pub _75p: Option<Box<EagerVec<I, T>>>,
|
pub p75: Option<Box<EagerVec<I, T>>>,
|
||||||
pub median: Option<Box<EagerVec<I, T>>>,
|
pub median: Option<Box<EagerVec<I, T>>>,
|
||||||
pub _25p: Option<Box<EagerVec<I, T>>>,
|
pub p25: Option<Box<EagerVec<I, T>>>,
|
||||||
pub _10p: Option<Box<EagerVec<I, T>>>,
|
pub p10: Option<Box<EagerVec<I, T>>>,
|
||||||
pub min: Option<Box<EagerVec<I, T>>>,
|
pub min: Option<Box<EagerVec<I, T>>>,
|
||||||
pub last: Option<Box<EagerVec<I, T>>>,
|
pub last: Option<Box<EagerVec<I, T>>>,
|
||||||
pub cumulative: Option<Box<EagerVec<I, T>>>,
|
pub cumulative: Option<Box<EagerVec<I, T>>>,
|
||||||
@@ -118,7 +119,7 @@ where
|
|||||||
Box::new(
|
Box::new(
|
||||||
EagerVec::forced_import(
|
EagerVec::forced_import(
|
||||||
db,
|
db,
|
||||||
&maybe_suffix("average"),
|
&maybe_suffix("avg"),
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
format,
|
format,
|
||||||
)
|
)
|
||||||
@@ -151,44 +152,44 @@ where
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_90p: options._90p.then(|| {
|
p90: options.p90.then(|| {
|
||||||
Box::new(
|
Box::new(
|
||||||
EagerVec::forced_import(
|
EagerVec::forced_import(
|
||||||
db,
|
db,
|
||||||
&maybe_suffix("90p"),
|
&maybe_suffix("p90"),
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
format,
|
format,
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_75p: options._75p.then(|| {
|
p75: options.p75.then(|| {
|
||||||
Box::new(
|
Box::new(
|
||||||
EagerVec::forced_import(
|
EagerVec::forced_import(
|
||||||
db,
|
db,
|
||||||
&maybe_suffix("75p"),
|
&maybe_suffix("p75"),
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
format,
|
format,
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_25p: options._25p.then(|| {
|
p25: options.p25.then(|| {
|
||||||
Box::new(
|
Box::new(
|
||||||
EagerVec::forced_import(
|
EagerVec::forced_import(
|
||||||
db,
|
db,
|
||||||
&maybe_suffix("25p"),
|
&maybe_suffix("p25"),
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
format,
|
format,
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
_10p: options._10p.then(|| {
|
p10: options.p10.then(|| {
|
||||||
Box::new(
|
Box::new(
|
||||||
EagerVec::forced_import(
|
EagerVec::forced_import(
|
||||||
db,
|
db,
|
||||||
&maybe_suffix("10p"),
|
&maybe_suffix("p10"),
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
format,
|
format,
|
||||||
)
|
)
|
||||||
@@ -292,11 +293,11 @@ where
|
|||||||
let needs_average_sum_or_cumulative =
|
let needs_average_sum_or_cumulative =
|
||||||
needs_sum_or_cumulative || self.average.is_some();
|
needs_sum_or_cumulative || self.average.is_some();
|
||||||
let needs_sorted = self.max.is_some()
|
let needs_sorted = self.max.is_some()
|
||||||
|| self._90p.is_some()
|
|| self.p90.is_some()
|
||||||
|| self._75p.is_some()
|
|| self.p75.is_some()
|
||||||
|| self.median.is_some()
|
|| self.median.is_some()
|
||||||
|| self._25p.is_some()
|
|| self.p25.is_some()
|
||||||
|| self._10p.is_some()
|
|| self.p10.is_some()
|
||||||
|| self.min.is_some();
|
|| self.min.is_some();
|
||||||
let needs_values = needs_sorted || needs_average_sum_or_cumulative;
|
let needs_values = needs_sorted || needs_average_sum_or_cumulative;
|
||||||
|
|
||||||
@@ -333,24 +334,24 @@ where
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(_90p) = self._90p.as_mut() {
|
if let Some(p90) = self.p90.as_mut() {
|
||||||
_90p.forced_push_at(index, get_percentile(&values, 0.90), exit)?;
|
p90.forced_push_at(index, get_percentile(&values, 0.90), exit)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(_75p) = self._75p.as_mut() {
|
if let Some(p75) = self.p75.as_mut() {
|
||||||
_75p.forced_push_at(index, get_percentile(&values, 0.75), exit)?;
|
p75.forced_push_at(index, get_percentile(&values, 0.75), exit)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(median) = self.median.as_mut() {
|
if let Some(median) = self.median.as_mut() {
|
||||||
median.forced_push_at(index, get_percentile(&values, 0.50), exit)?;
|
median.forced_push_at(index, get_percentile(&values, 0.50), exit)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(_25p) = self._25p.as_mut() {
|
if let Some(p25) = self.p25.as_mut() {
|
||||||
_25p.forced_push_at(index, get_percentile(&values, 0.25), exit)?;
|
p25.forced_push_at(index, get_percentile(&values, 0.25), exit)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(_10p) = self._10p.as_mut() {
|
if let Some(p10) = self.p10.as_mut() {
|
||||||
_10p.forced_push_at(index, get_percentile(&values, 0.10), exit)?;
|
p10.forced_push_at(index, get_percentile(&values, 0.10), exit)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(min) = self.min.as_mut() {
|
if let Some(min) = self.min.as_mut() {
|
||||||
@@ -401,11 +402,11 @@ where
|
|||||||
where
|
where
|
||||||
I2: StoredIndex + StoredRaw + CheckedSub<I2>,
|
I2: StoredIndex + StoredRaw + CheckedSub<I2>,
|
||||||
{
|
{
|
||||||
if self._90p.is_some()
|
if self.p90.is_some()
|
||||||
|| self._75p.is_some()
|
|| self.p75.is_some()
|
||||||
|| self.median.is_some()
|
|| self.median.is_some()
|
||||||
|| self._25p.is_some()
|
|| self.p25.is_some()
|
||||||
|| self._10p.is_some()
|
|| self.p10.is_some()
|
||||||
{
|
{
|
||||||
panic!("unsupported");
|
panic!("unsupported");
|
||||||
}
|
}
|
||||||
@@ -558,24 +559,24 @@ where
|
|||||||
self.max.as_ref().unwrap()
|
self.max.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn unwrap_90p(&self) -> &EagerVec<I, T> {
|
pub fn unwrap_p90(&self) -> &EagerVec<I, T> {
|
||||||
self._90p.as_ref().unwrap()
|
self.p90.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn unwrap_75p(&self) -> &EagerVec<I, T> {
|
pub fn unwrap_p75(&self) -> &EagerVec<I, T> {
|
||||||
self._75p.as_ref().unwrap()
|
self.p75.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn unwrap_median(&self) -> &EagerVec<I, T> {
|
pub fn unwrap_median(&self) -> &EagerVec<I, T> {
|
||||||
self.median.as_ref().unwrap()
|
self.median.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn unwrap_25p(&self) -> &EagerVec<I, T> {
|
pub fn unwrap_p25(&self) -> &EagerVec<I, T> {
|
||||||
self._25p.as_ref().unwrap()
|
self.p25.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn unwrap_10p(&self) -> &EagerVec<I, T> {
|
pub fn unwrap_p10(&self) -> &EagerVec<I, T> {
|
||||||
self._10p.as_ref().unwrap()
|
self.p10.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
pub fn unwrap_min(&self) -> &EagerVec<I, T> {
|
pub fn unwrap_min(&self) -> &EagerVec<I, T> {
|
||||||
self.min.as_ref().unwrap()
|
self.min.as_ref().unwrap()
|
||||||
@@ -615,17 +616,17 @@ where
|
|||||||
if let Some(cumulative) = self.cumulative.as_ref() {
|
if let Some(cumulative) = self.cumulative.as_ref() {
|
||||||
v.push(cumulative.as_ref());
|
v.push(cumulative.as_ref());
|
||||||
}
|
}
|
||||||
if let Some(_90p) = self._90p.as_ref() {
|
if let Some(p90) = self.p90.as_ref() {
|
||||||
v.push(_90p.as_ref());
|
v.push(p90.as_ref());
|
||||||
}
|
}
|
||||||
if let Some(_75p) = self._75p.as_ref() {
|
if let Some(p75) = self.p75.as_ref() {
|
||||||
v.push(_75p.as_ref());
|
v.push(p75.as_ref());
|
||||||
}
|
}
|
||||||
if let Some(_25p) = self._25p.as_ref() {
|
if let Some(p25) = self.p25.as_ref() {
|
||||||
v.push(_25p.as_ref());
|
v.push(p25.as_ref());
|
||||||
}
|
}
|
||||||
if let Some(_10p) = self._10p.as_ref() {
|
if let Some(p10) = self.p10.as_ref() {
|
||||||
v.push(_10p.as_ref());
|
v.push(p10.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
v
|
v
|
||||||
@@ -656,17 +657,17 @@ where
|
|||||||
if let Some(cumulative) = self.cumulative.as_mut() {
|
if let Some(cumulative) = self.cumulative.as_mut() {
|
||||||
cumulative.safe_flush(exit)?;
|
cumulative.safe_flush(exit)?;
|
||||||
}
|
}
|
||||||
if let Some(_90p) = self._90p.as_mut() {
|
if let Some(p90) = self.p90.as_mut() {
|
||||||
_90p.safe_flush(exit)?;
|
p90.safe_flush(exit)?;
|
||||||
}
|
}
|
||||||
if let Some(_75p) = self._75p.as_mut() {
|
if let Some(p75) = self.p75.as_mut() {
|
||||||
_75p.safe_flush(exit)?;
|
p75.safe_flush(exit)?;
|
||||||
}
|
}
|
||||||
if let Some(_25p) = self._25p.as_mut() {
|
if let Some(p25) = self.p25.as_mut() {
|
||||||
_25p.safe_flush(exit)?;
|
p25.safe_flush(exit)?;
|
||||||
}
|
}
|
||||||
if let Some(_10p) = self._10p.as_mut() {
|
if let Some(p10) = self.p10.as_mut() {
|
||||||
_10p.safe_flush(exit)?;
|
p10.safe_flush(exit)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -697,17 +698,17 @@ where
|
|||||||
if let Some(cumulative) = self.cumulative.as_mut() {
|
if let Some(cumulative) = self.cumulative.as_mut() {
|
||||||
cumulative.validate_computed_version_or_reset(Version::ZERO + version)?;
|
cumulative.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||||
}
|
}
|
||||||
if let Some(_90p) = self._90p.as_mut() {
|
if let Some(p90) = self.p90.as_mut() {
|
||||||
_90p.validate_computed_version_or_reset(Version::ZERO + version)?;
|
p90.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||||
}
|
}
|
||||||
if let Some(_75p) = self._75p.as_mut() {
|
if let Some(p75) = self.p75.as_mut() {
|
||||||
_75p.validate_computed_version_or_reset(Version::ZERO + version)?;
|
p75.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||||
}
|
}
|
||||||
if let Some(_25p) = self._25p.as_mut() {
|
if let Some(p25) = self.p25.as_mut() {
|
||||||
_25p.validate_computed_version_or_reset(Version::ZERO + version)?;
|
p25.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||||
}
|
}
|
||||||
if let Some(_10p) = self._10p.as_mut() {
|
if let Some(p10) = self.p10.as_mut() {
|
||||||
_10p.validate_computed_version_or_reset(Version::ZERO + version)?;
|
p10.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -719,11 +720,11 @@ pub struct VecBuilderOptions {
|
|||||||
average: bool,
|
average: bool,
|
||||||
sum: bool,
|
sum: bool,
|
||||||
max: bool,
|
max: bool,
|
||||||
_90p: bool,
|
p90: bool,
|
||||||
_75p: bool,
|
p75: bool,
|
||||||
median: bool,
|
median: bool,
|
||||||
_25p: bool,
|
p25: bool,
|
||||||
_10p: bool,
|
p10: bool,
|
||||||
min: bool,
|
min: bool,
|
||||||
first: bool,
|
first: bool,
|
||||||
last: bool,
|
last: bool,
|
||||||
@@ -743,24 +744,24 @@ impl VecBuilderOptions {
|
|||||||
self.max
|
self.max
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _90p(&self) -> bool {
|
pub fn p90(&self) -> bool {
|
||||||
self._90p
|
self.p90
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _75p(&self) -> bool {
|
pub fn p75(&self) -> bool {
|
||||||
self._75p
|
self.p75
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn median(&self) -> bool {
|
pub fn median(&self) -> bool {
|
||||||
self.median
|
self.median
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _25p(&self) -> bool {
|
pub fn p25(&self) -> bool {
|
||||||
self._25p
|
self.p25
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _10p(&self) -> bool {
|
pub fn p10(&self) -> bool {
|
||||||
self._10p
|
self.p10
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn min(&self) -> bool {
|
pub fn min(&self) -> bool {
|
||||||
@@ -816,26 +817,26 @@ impl VecBuilderOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn add_90p(mut self) -> Self {
|
pub fn add_p90(mut self) -> Self {
|
||||||
self._90p = true;
|
self.p90 = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn add_75p(mut self) -> Self {
|
pub fn add_p75(mut self) -> Self {
|
||||||
self._75p = true;
|
self.p75 = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn add_25p(mut self) -> Self {
|
pub fn add_p25(mut self) -> Self {
|
||||||
self._25p = true;
|
self.p25 = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn add_10p(mut self) -> Self {
|
pub fn add_p10(mut self) -> Self {
|
||||||
self._10p = true;
|
self.p10 = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -875,26 +876,26 @@ impl VecBuilderOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn rm_90p(mut self) -> Self {
|
pub fn rm_p90(mut self) -> Self {
|
||||||
self._90p = false;
|
self.p90 = false;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn rm_75p(mut self) -> Self {
|
pub fn rm_p75(mut self) -> Self {
|
||||||
self._75p = false;
|
self.p75 = false;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn rm_25p(mut self) -> Self {
|
pub fn rm_p25(mut self) -> Self {
|
||||||
self._25p = false;
|
self.p25 = false;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn rm_10p(mut self) -> Self {
|
pub fn rm_p10(mut self) -> Self {
|
||||||
self._10p = false;
|
self.p10 = false;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -911,20 +912,20 @@ impl VecBuilderOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_percentiles(mut self) -> Self {
|
pub fn add_percentiles(mut self) -> Self {
|
||||||
self._90p = true;
|
self.p90 = true;
|
||||||
self._75p = true;
|
self.p75 = true;
|
||||||
self.median = true;
|
self.median = true;
|
||||||
self._25p = true;
|
self.p25 = true;
|
||||||
self._10p = true;
|
self.p10 = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_percentiles(mut self) -> Self {
|
pub fn remove_percentiles(mut self) -> Self {
|
||||||
self._90p = false;
|
self.p90 = false;
|
||||||
self._75p = false;
|
self.p75 = false;
|
||||||
self.median = false;
|
self.median = false;
|
||||||
self._25p = false;
|
self.p25 = false;
|
||||||
self._10p = false;
|
self.p10 = false;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -933,11 +934,11 @@ impl VecBuilderOptions {
|
|||||||
self.average,
|
self.average,
|
||||||
self.sum,
|
self.sum,
|
||||||
self.max,
|
self.max,
|
||||||
self._90p,
|
self.p90,
|
||||||
self._75p,
|
self.p75,
|
||||||
self.median,
|
self.median,
|
||||||
self._25p,
|
self.p25,
|
||||||
self._10p,
|
self.p10,
|
||||||
self.min,
|
self.min,
|
||||||
self.first,
|
self.first,
|
||||||
self.last,
|
self.last,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use allocative::Allocative;
|
||||||
use brk_structs::Version;
|
use brk_structs::Version;
|
||||||
use vecdb::{
|
use vecdb::{
|
||||||
AnyBoxedIterableVec, AnyCloneableIterableVec, AnyCollectableVec, FromCoarserIndex,
|
AnyBoxedIterableVec, AnyCloneableIterableVec, AnyCollectableVec, FromCoarserIndex,
|
||||||
@@ -9,7 +10,7 @@ use crate::grouped::{EagerVecBuilder, VecBuilderOptions};
|
|||||||
use super::ComputedType;
|
use super::ComputedType;
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Allocative)]
|
||||||
pub struct LazyVecBuilder<I, T, S1I, S2T>
|
pub struct LazyVecBuilder<I, T, S1I, S2T>
|
||||||
where
|
where
|
||||||
I: StoredIndex,
|
I: StoredIndex,
|
||||||
@@ -142,7 +143,7 @@ where
|
|||||||
}),
|
}),
|
||||||
average: options.average.then(|| {
|
average: options.average.then(|| {
|
||||||
Box::new(LazyVecFrom2::init(
|
Box::new(LazyVecFrom2::init(
|
||||||
&maybe_suffix("average"),
|
&maybe_suffix("avg"),
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
source_extra
|
source_extra
|
||||||
.average
|
.average
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use allocative::Allocative;
|
||||||
use brk_error::Result;
|
use brk_error::Result;
|
||||||
|
|
||||||
use brk_indexer::Indexer;
|
use brk_indexer::Indexer;
|
||||||
@@ -10,7 +11,7 @@ use crate::{Indexes, grouped::LazyVecBuilder, indexes};
|
|||||||
|
|
||||||
use super::{ComputedType, EagerVecBuilder, Source, VecBuilderOptions};
|
use super::{ComputedType, EagerVecBuilder, Source, VecBuilderOptions};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Allocative)]
|
||||||
pub struct ComputedVecsFromDateIndex<T>
|
pub struct ComputedVecsFromDateIndex<T>
|
||||||
where
|
where
|
||||||
T: ComputedType + PartialOrd,
|
T: ComputedType + PartialOrd,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use allocative::Allocative;
|
||||||
use brk_error::Result;
|
use brk_error::Result;
|
||||||
|
|
||||||
use brk_indexer::Indexer;
|
use brk_indexer::Indexer;
|
||||||
@@ -15,7 +16,7 @@ use crate::{
|
|||||||
|
|
||||||
use super::{ComputedType, EagerVecBuilder, VecBuilderOptions};
|
use super::{ComputedType, EagerVecBuilder, VecBuilderOptions};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Allocative)]
|
||||||
pub struct ComputedVecsFromHeight<T>
|
pub struct ComputedVecsFromHeight<T>
|
||||||
where
|
where
|
||||||
T: ComputedType + PartialOrd,
|
T: ComputedType + PartialOrd,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use allocative::Allocative;
|
||||||
use brk_error::Result;
|
use brk_error::Result;
|
||||||
use brk_indexer::Indexer;
|
use brk_indexer::Indexer;
|
||||||
use brk_structs::{
|
use brk_structs::{
|
||||||
@@ -17,7 +18,7 @@ use crate::{
|
|||||||
|
|
||||||
use super::{ComputedType, EagerVecBuilder, VecBuilderOptions};
|
use super::{ComputedType, EagerVecBuilder, VecBuilderOptions};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Allocative)]
|
||||||
pub struct ComputedVecsFromTxindex<T>
|
pub struct ComputedVecsFromTxindex<T>
|
||||||
where
|
where
|
||||||
T: ComputedType + PartialOrd,
|
T: ComputedType + PartialOrd,
|
||||||
@@ -319,24 +320,24 @@ impl ComputedVecsFromTxindex<Bitcoin> {
|
|||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
if let Some(_90p) = self.height._90p.as_mut() {
|
if let Some(_90p) = self.height.p90.as_mut() {
|
||||||
_90p.forced_push_at(
|
_90p.forced_push_at(
|
||||||
height,
|
height,
|
||||||
Bitcoin::from(
|
Bitcoin::from(
|
||||||
sats.height
|
sats.height
|
||||||
.unwrap_90p()
|
.unwrap_p90()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.unwrap_get_inner(height),
|
.unwrap_get_inner(height),
|
||||||
),
|
),
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
if let Some(_75p) = self.height._75p.as_mut() {
|
if let Some(_75p) = self.height.p75.as_mut() {
|
||||||
_75p.forced_push_at(
|
_75p.forced_push_at(
|
||||||
height,
|
height,
|
||||||
Bitcoin::from(
|
Bitcoin::from(
|
||||||
sats.height
|
sats.height
|
||||||
.unwrap_75p()
|
.unwrap_p75()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.unwrap_get_inner(height),
|
.unwrap_get_inner(height),
|
||||||
),
|
),
|
||||||
@@ -355,24 +356,24 @@ impl ComputedVecsFromTxindex<Bitcoin> {
|
|||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
if let Some(_25p) = self.height._25p.as_mut() {
|
if let Some(_25p) = self.height.p25.as_mut() {
|
||||||
_25p.forced_push_at(
|
_25p.forced_push_at(
|
||||||
height,
|
height,
|
||||||
Bitcoin::from(
|
Bitcoin::from(
|
||||||
sats.height
|
sats.height
|
||||||
.unwrap_25p()
|
.unwrap_p25()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.unwrap_get_inner(height),
|
.unwrap_get_inner(height),
|
||||||
),
|
),
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
if let Some(_10p) = self.height._10p.as_mut() {
|
if let Some(_10p) = self.height.p10.as_mut() {
|
||||||
_10p.forced_push_at(
|
_10p.forced_push_at(
|
||||||
height,
|
height,
|
||||||
Bitcoin::from(
|
Bitcoin::from(
|
||||||
sats.height
|
sats.height
|
||||||
.unwrap_10p()
|
.unwrap_p10()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.unwrap_get_inner(height),
|
.unwrap_get_inner(height),
|
||||||
),
|
),
|
||||||
@@ -447,7 +448,7 @@ impl ComputedVecsFromTxindex<Dollars> {
|
|||||||
|
|
||||||
let starting_index = self.height.starting_index(starting_indexes.height);
|
let starting_index = self.height.starting_index(starting_indexes.height);
|
||||||
|
|
||||||
let mut close_iter = price.chainindexes_to_close.height.into_iter();
|
let mut close_iter = price.chainindexes_to_price_close.height.into_iter();
|
||||||
|
|
||||||
(starting_index.unwrap_to_usize()..indexer.vecs.height_to_weight.len())
|
(starting_index.unwrap_to_usize()..indexer.vecs.height_to_weight.len())
|
||||||
.map(Height::from)
|
.map(Height::from)
|
||||||
@@ -502,25 +503,25 @@ impl ComputedVecsFromTxindex<Dollars> {
|
|||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
if let Some(_90p) = self.height._90p.as_mut() {
|
if let Some(_90p) = self.height.p90.as_mut() {
|
||||||
_90p.forced_push_at(
|
_90p.forced_push_at(
|
||||||
height,
|
height,
|
||||||
price
|
price
|
||||||
* bitcoin
|
* bitcoin
|
||||||
.height
|
.height
|
||||||
.unwrap_90p()
|
.unwrap_p90()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.unwrap_get_inner(height),
|
.unwrap_get_inner(height),
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
if let Some(_75p) = self.height._75p.as_mut() {
|
if let Some(_75p) = self.height.p75.as_mut() {
|
||||||
_75p.forced_push_at(
|
_75p.forced_push_at(
|
||||||
height,
|
height,
|
||||||
price
|
price
|
||||||
* bitcoin
|
* bitcoin
|
||||||
.height
|
.height
|
||||||
.unwrap_75p()
|
.unwrap_p75()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.unwrap_get_inner(height),
|
.unwrap_get_inner(height),
|
||||||
exit,
|
exit,
|
||||||
@@ -538,25 +539,25 @@ impl ComputedVecsFromTxindex<Dollars> {
|
|||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
if let Some(_25p) = self.height._25p.as_mut() {
|
if let Some(_25p) = self.height.p25.as_mut() {
|
||||||
_25p.forced_push_at(
|
_25p.forced_push_at(
|
||||||
height,
|
height,
|
||||||
price
|
price
|
||||||
* bitcoin
|
* bitcoin
|
||||||
.height
|
.height
|
||||||
.unwrap_25p()
|
.unwrap_p25()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.unwrap_get_inner(height),
|
.unwrap_get_inner(height),
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
if let Some(_10p) = self.height._10p.as_mut() {
|
if let Some(_10p) = self.height.p10.as_mut() {
|
||||||
_10p.forced_push_at(
|
_10p.forced_push_at(
|
||||||
height,
|
height,
|
||||||
price
|
price
|
||||||
* bitcoin
|
* bitcoin
|
||||||
.height
|
.height
|
||||||
.unwrap_10p()
|
.unwrap_p10()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.unwrap_get_inner(height),
|
.unwrap_get_inner(height),
|
||||||
exit,
|
exit,
|
||||||
|
|||||||
@@ -22,18 +22,18 @@ pub struct ComputedRatioVecsFromDateIndex {
|
|||||||
pub ratio: ComputedVecsFromDateIndex<StoredF32>,
|
pub ratio: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
pub ratio_1w_sma: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
pub ratio_1w_sma: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||||
pub ratio_1m_sma: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
pub ratio_1m_sma: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||||
pub ratio_p99: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
pub ratio_pct99: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||||
pub ratio_p98: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
pub ratio_pct98: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||||
pub ratio_p95: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
pub ratio_pct95: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||||
pub ratio_p5: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
pub ratio_pct5: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||||
pub ratio_p2: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
pub ratio_pct2: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||||
pub ratio_p1: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
pub ratio_pct1: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||||
pub ratio_p99_as_price: Option<ComputedVecsFromDateIndex<Dollars>>,
|
pub ratio_pct99_in_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||||
pub ratio_p98_as_price: Option<ComputedVecsFromDateIndex<Dollars>>,
|
pub ratio_pct98_in_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||||
pub ratio_p95_as_price: Option<ComputedVecsFromDateIndex<Dollars>>,
|
pub ratio_pct95_in_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||||
pub ratio_p5_as_price: Option<ComputedVecsFromDateIndex<Dollars>>,
|
pub ratio_pct5_in_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||||
pub ratio_p2_as_price: Option<ComputedVecsFromDateIndex<Dollars>>,
|
pub ratio_pct2_in_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||||
pub ratio_p1_as_price: Option<ComputedVecsFromDateIndex<Dollars>>,
|
pub ratio_pct1_in_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||||
|
|
||||||
pub ratio_sd: Option<ComputedStandardDeviationVecsFromDateIndex>,
|
pub ratio_sd: Option<ComputedStandardDeviationVecsFromDateIndex>,
|
||||||
pub ratio_4y_sd: Option<ComputedStandardDeviationVecsFromDateIndex>,
|
pub ratio_4y_sd: Option<ComputedStandardDeviationVecsFromDateIndex>,
|
||||||
@@ -141,10 +141,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
ratio_p99: extended.then(|| {
|
ratio_pct99: extended.then(|| {
|
||||||
ComputedVecsFromDateIndex::forced_import(
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_ratio_p99"),
|
&format!("{name}_ratio_pct99"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -152,10 +152,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
ratio_p98: extended.then(|| {
|
ratio_pct98: extended.then(|| {
|
||||||
ComputedVecsFromDateIndex::forced_import(
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_ratio_p98"),
|
&format!("{name}_ratio_pct98"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -163,10 +163,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
ratio_p95: extended.then(|| {
|
ratio_pct95: extended.then(|| {
|
||||||
ComputedVecsFromDateIndex::forced_import(
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_ratio_p95"),
|
&format!("{name}_ratio_pct95"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -174,10 +174,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
ratio_p5: extended.then(|| {
|
ratio_pct5: extended.then(|| {
|
||||||
ComputedVecsFromDateIndex::forced_import(
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_ratio_p5"),
|
&format!("{name}_ratio_pct5"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -185,10 +185,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
ratio_p2: extended.then(|| {
|
ratio_pct2: extended.then(|| {
|
||||||
ComputedVecsFromDateIndex::forced_import(
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_ratio_p2"),
|
&format!("{name}_ratio_pct2"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -196,10 +196,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
ratio_p1: extended.then(|| {
|
ratio_pct1: extended.then(|| {
|
||||||
ComputedVecsFromDateIndex::forced_import(
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_ratio_p1"),
|
&format!("{name}_ratio_pct1"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -207,10 +207,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
ratio_p99_as_price: extended.then(|| {
|
ratio_pct99_in_usd: extended.then(|| {
|
||||||
ComputedVecsFromDateIndex::forced_import(
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_ratio_p99_as_price"),
|
&format!("{name}_ratio_pct99_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -218,10 +218,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
ratio_p98_as_price: extended.then(|| {
|
ratio_pct98_in_usd: extended.then(|| {
|
||||||
ComputedVecsFromDateIndex::forced_import(
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_ratio_p98_as_price"),
|
&format!("{name}_ratio_pct98_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -229,10 +229,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
ratio_p95_as_price: extended.then(|| {
|
ratio_pct95_in_usd: extended.then(|| {
|
||||||
ComputedVecsFromDateIndex::forced_import(
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_ratio_p95_as_price"),
|
&format!("{name}_ratio_pct95_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -240,10 +240,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
ratio_p5_as_price: extended.then(|| {
|
ratio_pct5_in_usd: extended.then(|| {
|
||||||
ComputedVecsFromDateIndex::forced_import(
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_ratio_p5_as_price"),
|
&format!("{name}_ratio_pct5_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -251,10 +251,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
ratio_p2_as_price: extended.then(|| {
|
ratio_pct2_in_usd: extended.then(|| {
|
||||||
ComputedVecsFromDateIndex::forced_import(
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_ratio_p2_as_price"),
|
&format!("{name}_ratio_pct2_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -262,10 +262,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
ratio_p1_as_price: extended.then(|| {
|
ratio_pct1_in_usd: extended.then(|| {
|
||||||
ComputedVecsFromDateIndex::forced_import(
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_ratio_p1_as_price"),
|
&format!("{name}_ratio_pct1_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -320,26 +320,25 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
price: &price::Vecs,
|
price: &price::Vecs,
|
||||||
starting_indexes: &Indexes,
|
starting_indexes: &Indexes,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
date_to_price_opt: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
price_opt: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let date_to_price = date_to_price_opt.unwrap_or_else(|| unsafe {
|
let closes = price.timeindexes_to_price_close.dateindex.as_ref().unwrap();
|
||||||
|
|
||||||
|
let price = price_opt.unwrap_or_else(|| unsafe {
|
||||||
std::mem::transmute(&self.price.as_ref().unwrap().dateindex)
|
std::mem::transmute(&self.price.as_ref().unwrap().dateindex)
|
||||||
});
|
});
|
||||||
|
|
||||||
let closes = price.timeindexes_to_close.dateindex.as_ref().unwrap();
|
|
||||||
|
|
||||||
self.ratio.compute_all(
|
self.ratio.compute_all(
|
||||||
indexer,
|
indexer,
|
||||||
indexes,
|
indexes,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
|v, _, _, starting_indexes, exit| {
|
|v, _, _, starting_indexes, exit| {
|
||||||
let mut price = date_to_price.iter();
|
v.compute_transform2(
|
||||||
v.compute_transform(
|
|
||||||
starting_indexes.dateindex,
|
starting_indexes.dateindex,
|
||||||
closes,
|
closes,
|
||||||
|(i, close, ..)| {
|
price,
|
||||||
let price = price.unwrap_get_inner(i);
|
|(i, close, price, ..)| {
|
||||||
if price == Dollars::ZERO {
|
if price == Dollars::ZERO {
|
||||||
(i, StoredF32::from(1.0))
|
(i, StoredF32::from(1.0))
|
||||||
} else {
|
} else {
|
||||||
@@ -424,42 +423,42 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
.iter_at(starting_dateindex)
|
.iter_at(starting_dateindex)
|
||||||
.try_for_each(|(index, ratio)| -> Result<()> {
|
.try_for_each(|(index, ratio)| -> Result<()> {
|
||||||
if index < min_ratio_date {
|
if index < min_ratio_date {
|
||||||
self.ratio_p5
|
self.ratio_pct5
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.forced_push_at(index, StoredF32::NAN, exit)?;
|
.forced_push_at(index, StoredF32::NAN, exit)?;
|
||||||
self.ratio_p2
|
self.ratio_pct2
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.forced_push_at(index, StoredF32::NAN, exit)?;
|
.forced_push_at(index, StoredF32::NAN, exit)?;
|
||||||
self.ratio_p1
|
self.ratio_pct1
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.forced_push_at(index, StoredF32::NAN, exit)?;
|
.forced_push_at(index, StoredF32::NAN, exit)?;
|
||||||
self.ratio_p95
|
self.ratio_pct95
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.forced_push_at(index, StoredF32::NAN, exit)?;
|
.forced_push_at(index, StoredF32::NAN, exit)?;
|
||||||
self.ratio_p98
|
self.ratio_pct98
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.forced_push_at(index, StoredF32::NAN, exit)?;
|
.forced_push_at(index, StoredF32::NAN, exit)?;
|
||||||
self.ratio_p99
|
self.ratio_pct99
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
@@ -471,42 +470,42 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
let pos = sorted.binary_search(&ratio).unwrap_or_else(|pos| pos);
|
let pos = sorted.binary_search(&ratio).unwrap_or_else(|pos| pos);
|
||||||
sorted.insert(pos, ratio);
|
sorted.insert(pos, ratio);
|
||||||
|
|
||||||
self.ratio_p1
|
self.ratio_pct1
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.forced_push_at(index, get_percentile(&sorted, 0.01), exit)?;
|
.forced_push_at(index, get_percentile(&sorted, 0.01), exit)?;
|
||||||
self.ratio_p2
|
self.ratio_pct2
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.forced_push_at(index, get_percentile(&sorted, 0.02), exit)?;
|
.forced_push_at(index, get_percentile(&sorted, 0.02), exit)?;
|
||||||
self.ratio_p5
|
self.ratio_pct5
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.forced_push_at(index, get_percentile(&sorted, 0.05), exit)?;
|
.forced_push_at(index, get_percentile(&sorted, 0.05), exit)?;
|
||||||
self.ratio_p95
|
self.ratio_pct95
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.forced_push_at(index, get_percentile(&sorted, 0.95), exit)?;
|
.forced_push_at(index, get_percentile(&sorted, 0.95), exit)?;
|
||||||
self.ratio_p98
|
self.ratio_pct98
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.forced_push_at(index, get_percentile(&sorted, 0.98), exit)?;
|
.forced_push_at(index, get_percentile(&sorted, 0.98), exit)?;
|
||||||
self.ratio_p99
|
self.ratio_pct99
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
@@ -522,49 +521,49 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.try_for_each(|v| v.safe_flush(exit))?;
|
.try_for_each(|v| v.safe_flush(exit))?;
|
||||||
|
|
||||||
self.ratio_p1.as_mut().unwrap().compute_rest(
|
self.ratio_pct1.as_mut().unwrap().compute_rest(
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
None as Option<&EagerVec<_, _>>,
|
None as Option<&EagerVec<_, _>>,
|
||||||
)?;
|
)?;
|
||||||
self.ratio_p2.as_mut().unwrap().compute_rest(
|
self.ratio_pct2.as_mut().unwrap().compute_rest(
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
None as Option<&EagerVec<_, _>>,
|
None as Option<&EagerVec<_, _>>,
|
||||||
)?;
|
)?;
|
||||||
self.ratio_p5.as_mut().unwrap().compute_rest(
|
self.ratio_pct5.as_mut().unwrap().compute_rest(
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
None as Option<&EagerVec<_, _>>,
|
None as Option<&EagerVec<_, _>>,
|
||||||
)?;
|
)?;
|
||||||
self.ratio_p95.as_mut().unwrap().compute_rest(
|
self.ratio_pct95.as_mut().unwrap().compute_rest(
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
None as Option<&EagerVec<_, _>>,
|
None as Option<&EagerVec<_, _>>,
|
||||||
)?;
|
)?;
|
||||||
self.ratio_p98.as_mut().unwrap().compute_rest(
|
self.ratio_pct98.as_mut().unwrap().compute_rest(
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
None as Option<&EagerVec<_, _>>,
|
None as Option<&EagerVec<_, _>>,
|
||||||
)?;
|
)?;
|
||||||
self.ratio_p99.as_mut().unwrap().compute_rest(
|
self.ratio_pct99.as_mut().unwrap().compute_rest(
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
None as Option<&EagerVec<_, _>>,
|
None as Option<&EagerVec<_, _>>,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let date_to_price = date_to_price_opt.unwrap_or_else(|| unsafe {
|
let date_to_price = price_opt.unwrap_or_else(|| unsafe {
|
||||||
std::mem::transmute(&self.price.as_ref().unwrap().dateindex)
|
std::mem::transmute(&self.price.as_ref().unwrap().dateindex)
|
||||||
});
|
});
|
||||||
|
|
||||||
self.ratio_p99_as_price.as_mut().unwrap().compute_all(
|
self.ratio_pct99_in_usd.as_mut().unwrap().compute_all(
|
||||||
indexer,
|
indexer,
|
||||||
indexes,
|
indexes,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
|vec, _, _, starting_indexes, exit| {
|
|vec, _, _, starting_indexes, exit| {
|
||||||
let mut iter = self
|
let mut iter = self
|
||||||
.ratio_p99
|
.ratio_pct99
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dateindex
|
.dateindex
|
||||||
@@ -584,10 +583,10 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let compute_as_price =
|
let compute_in_usd =
|
||||||
|as_price: Option<&mut ComputedVecsFromDateIndex<Dollars>>,
|
|in_usd: Option<&mut ComputedVecsFromDateIndex<Dollars>>,
|
||||||
source: Option<&ComputedVecsFromDateIndex<StoredF32>>| {
|
source: Option<&ComputedVecsFromDateIndex<StoredF32>>| {
|
||||||
as_price.unwrap().compute_all(
|
in_usd.unwrap().compute_all(
|
||||||
indexer,
|
indexer,
|
||||||
indexes,
|
indexes,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
@@ -608,12 +607,12 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
compute_as_price(self.ratio_p1_as_price.as_mut(), self.ratio_p1.as_ref())?;
|
compute_in_usd(self.ratio_pct1_in_usd.as_mut(), self.ratio_pct1.as_ref())?;
|
||||||
compute_as_price(self.ratio_p2_as_price.as_mut(), self.ratio_p2.as_ref())?;
|
compute_in_usd(self.ratio_pct2_in_usd.as_mut(), self.ratio_pct2.as_ref())?;
|
||||||
compute_as_price(self.ratio_p5_as_price.as_mut(), self.ratio_p5.as_ref())?;
|
compute_in_usd(self.ratio_pct5_in_usd.as_mut(), self.ratio_pct5.as_ref())?;
|
||||||
compute_as_price(self.ratio_p95_as_price.as_mut(), self.ratio_p95.as_ref())?;
|
compute_in_usd(self.ratio_pct95_in_usd.as_mut(), self.ratio_pct95.as_ref())?;
|
||||||
compute_as_price(self.ratio_p98_as_price.as_mut(), self.ratio_p98.as_ref())?;
|
compute_in_usd(self.ratio_pct98_in_usd.as_mut(), self.ratio_pct98.as_ref())?;
|
||||||
compute_as_price(self.ratio_p99_as_price.as_mut(), self.ratio_p99.as_ref())?;
|
compute_in_usd(self.ratio_pct99_in_usd.as_mut(), self.ratio_pct99.as_ref())?;
|
||||||
|
|
||||||
self.ratio_sd.as_mut().unwrap().compute_all(
|
self.ratio_sd.as_mut().unwrap().compute_all(
|
||||||
indexer,
|
indexer,
|
||||||
@@ -653,22 +652,22 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
|
|
||||||
fn mut_ratio_vecs(&mut self) -> Vec<&mut EagerVec<DateIndex, StoredF32>> {
|
fn mut_ratio_vecs(&mut self) -> Vec<&mut EagerVec<DateIndex, StoredF32>> {
|
||||||
[
|
[
|
||||||
self.ratio_p1
|
self.ratio_pct1
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
|
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
|
||||||
self.ratio_p2
|
self.ratio_pct2
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
|
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
|
||||||
self.ratio_p5
|
self.ratio_pct5
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
|
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
|
||||||
self.ratio_p95
|
self.ratio_pct95
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
|
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
|
||||||
self.ratio_p98
|
self.ratio_pct98
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
|
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
|
||||||
self.ratio_p99
|
self.ratio_pct99
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
|
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
|
||||||
]
|
]
|
||||||
@@ -687,22 +686,22 @@ impl ComputedRatioVecsFromDateIndex {
|
|||||||
self.ratio_1y_sd.as_ref().map_or(vec![], |v| v.vecs()),
|
self.ratio_1y_sd.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_2y_sd.as_ref().map_or(vec![], |v| v.vecs()),
|
self.ratio_2y_sd.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_4y_sd.as_ref().map_or(vec![], |v| v.vecs()),
|
self.ratio_4y_sd.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_p1.as_ref().map_or(vec![], |v| v.vecs()),
|
self.ratio_pct1.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_p2.as_ref().map_or(vec![], |v| v.vecs()),
|
self.ratio_pct2.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_p5.as_ref().map_or(vec![], |v| v.vecs()),
|
self.ratio_pct5.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_p95.as_ref().map_or(vec![], |v| v.vecs()),
|
self.ratio_pct95.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_p98.as_ref().map_or(vec![], |v| v.vecs()),
|
self.ratio_pct98.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_p99.as_ref().map_or(vec![], |v| v.vecs()),
|
self.ratio_pct99.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_p1_as_price.as_ref().map_or(vec![], |v| v.vecs()),
|
self.ratio_pct1_in_usd.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_p2_as_price.as_ref().map_or(vec![], |v| v.vecs()),
|
self.ratio_pct2_in_usd.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_p5_as_price.as_ref().map_or(vec![], |v| v.vecs()),
|
self.ratio_pct5_in_usd.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_p95_as_price
|
self.ratio_pct95_in_usd
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(vec![], |v| v.vecs()),
|
.map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_p98_as_price
|
self.ratio_pct98_in_usd
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(vec![], |v| v.vecs()),
|
.map_or(vec![], |v| v.vecs()),
|
||||||
self.ratio_p99_as_price
|
self.ratio_pct99_in_usd
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(vec![], |v| v.vecs()),
|
.map_or(vec![], |v| v.vecs()),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub struct ComputedStandardDeviationVecsFromDateIndex {
|
|||||||
|
|
||||||
pub sma: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
pub sma: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||||
pub sd: ComputedVecsFromDateIndex<StoredF32>,
|
pub sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
pub _0sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub _0sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub p0_5sd: ComputedVecsFromDateIndex<StoredF32>,
|
pub p0_5sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
pub p1sd: ComputedVecsFromDateIndex<StoredF32>,
|
pub p1sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
pub p1_5sd: ComputedVecsFromDateIndex<StoredF32>,
|
pub p1_5sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
@@ -29,18 +29,18 @@ pub struct ComputedStandardDeviationVecsFromDateIndex {
|
|||||||
pub m2sd: ComputedVecsFromDateIndex<StoredF32>,
|
pub m2sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
pub m2_5sd: ComputedVecsFromDateIndex<StoredF32>,
|
pub m2_5sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
pub m3sd: ComputedVecsFromDateIndex<StoredF32>,
|
pub m3sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
pub p0_5sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub p0_5sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub p1sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub p1sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub p1_5sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub p1_5sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub p2sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub p2sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub p2_5sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub p2_5sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub p3sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub p3sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub m0_5sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub m0_5sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub m1sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub m1sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub m1_5sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub m1_5sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub m2sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub m2sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub m2_5sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub m2_5sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub m3sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
pub m3sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
|
||||||
pub zscore: ComputedVecsFromDateIndex<StoredF32>,
|
pub zscore: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,105 +175,105 @@ impl ComputedStandardDeviationVecsFromDateIndex {
|
|||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
_0sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
_0sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_0sd_as_price"),
|
&format!("{name}_0sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
p0_5sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
p0_5sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_p0_5sd_as_price"),
|
&format!("{name}_p0_5sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
p1sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
p1sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_p1sd_as_price"),
|
&format!("{name}_p1sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
p1_5sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
p1_5sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_p1_5sd_as_price"),
|
&format!("{name}_p1_5sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
p2sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
p2sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_p2sd_as_price"),
|
&format!("{name}_p2sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
p2_5sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
p2_5sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_p2_5sd_as_price"),
|
&format!("{name}_p2_5sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
p3sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
p3sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_p3sd_as_price"),
|
&format!("{name}_p3sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
m0_5sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
m0_5sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_m0_5sd_as_price"),
|
&format!("{name}_m0_5sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
m1sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
m1sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_m1sd_as_price"),
|
&format!("{name}_m1sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
m1_5sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
m1_5sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_m1_5sd_as_price"),
|
&format!("{name}_m1_5sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
m2sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
m2sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_m2sd_as_price"),
|
&format!("{name}_m2sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
m2_5sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
m2_5sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_m2_5sd_as_price"),
|
&format!("{name}_m2_5sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
m3sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
m3sd_in_usd: ComputedVecsFromDateIndex::forced_import(
|
||||||
db,
|
db,
|
||||||
&format!("{name}_m3sd_as_price"),
|
&format!("{name}_m3sd_in_usd"),
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -297,7 +297,7 @@ impl ComputedStandardDeviationVecsFromDateIndex {
|
|||||||
starting_indexes: &Indexes,
|
starting_indexes: &Indexes,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
source: &impl CollectableVec<DateIndex, StoredF32>,
|
source: &impl CollectableVec<DateIndex, StoredF32>,
|
||||||
source_as_price: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
source_in_usd: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let min_date = DateIndex::try_from(Date::MIN_RATIO).unwrap();
|
let min_date = DateIndex::try_from(Date::MIN_RATIO).unwrap();
|
||||||
|
|
||||||
@@ -326,7 +326,7 @@ impl ComputedStandardDeviationVecsFromDateIndex {
|
|||||||
exit,
|
exit,
|
||||||
sma_opt,
|
sma_opt,
|
||||||
source,
|
source,
|
||||||
source_as_price,
|
source_in_usd,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,7 +339,7 @@ impl ComputedStandardDeviationVecsFromDateIndex {
|
|||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
sma_opt: Option<&impl AnyIterableVec<DateIndex, StoredF32>>,
|
sma_opt: Option<&impl AnyIterableVec<DateIndex, StoredF32>>,
|
||||||
source: &impl CollectableVec<DateIndex, StoredF32>,
|
source: &impl CollectableVec<DateIndex, StoredF32>,
|
||||||
source_as_price: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
source_in_usd: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let sma = sma_opt.unwrap_or_else(|| unsafe {
|
let sma = sma_opt.unwrap_or_else(|| unsafe {
|
||||||
std::mem::transmute(&self.sma.as_ref().unwrap().dateindex)
|
std::mem::transmute(&self.sma.as_ref().unwrap().dateindex)
|
||||||
@@ -571,14 +571,14 @@ impl ComputedStandardDeviationVecsFromDateIndex {
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let Some(price) = source_as_price else {
|
let Some(price) = source_in_usd else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let compute_as_price =
|
let compute_in_usd =
|
||||||
|as_price: &mut ComputedVecsFromDateIndex<Dollars>,
|
|in_usd: &mut ComputedVecsFromDateIndex<Dollars>,
|
||||||
mut iter: BoxedVecIterator<DateIndex, StoredF32>| {
|
mut iter: BoxedVecIterator<DateIndex, StoredF32>| {
|
||||||
as_price.compute_all(
|
in_usd.compute_all(
|
||||||
indexer,
|
indexer,
|
||||||
indexes,
|
indexes,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
@@ -598,53 +598,53 @@ impl ComputedStandardDeviationVecsFromDateIndex {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
compute_as_price(&mut self._0sd_as_price, sma.iter())?;
|
compute_in_usd(&mut self._0sd_in_usd, sma.iter())?;
|
||||||
compute_as_price(
|
compute_in_usd(
|
||||||
&mut self.p0_5sd_as_price,
|
&mut self.p0_5sd_in_usd,
|
||||||
self.p0_5sd.dateindex.as_ref().unwrap().iter(),
|
self.p0_5sd.dateindex.as_ref().unwrap().iter(),
|
||||||
)?;
|
)?;
|
||||||
compute_as_price(
|
compute_in_usd(
|
||||||
&mut self.p1sd_as_price,
|
&mut self.p1sd_in_usd,
|
||||||
self.p1sd.dateindex.as_ref().unwrap().iter(),
|
self.p1sd.dateindex.as_ref().unwrap().iter(),
|
||||||
)?;
|
)?;
|
||||||
compute_as_price(
|
compute_in_usd(
|
||||||
&mut self.p1_5sd_as_price,
|
&mut self.p1_5sd_in_usd,
|
||||||
self.p1_5sd.dateindex.as_ref().unwrap().iter(),
|
self.p1_5sd.dateindex.as_ref().unwrap().iter(),
|
||||||
)?;
|
)?;
|
||||||
compute_as_price(
|
compute_in_usd(
|
||||||
&mut self.p2sd_as_price,
|
&mut self.p2sd_in_usd,
|
||||||
self.p2sd.dateindex.as_ref().unwrap().iter(),
|
self.p2sd.dateindex.as_ref().unwrap().iter(),
|
||||||
)?;
|
)?;
|
||||||
compute_as_price(
|
compute_in_usd(
|
||||||
&mut self.p2_5sd_as_price,
|
&mut self.p2_5sd_in_usd,
|
||||||
self.p2_5sd.dateindex.as_ref().unwrap().iter(),
|
self.p2_5sd.dateindex.as_ref().unwrap().iter(),
|
||||||
)?;
|
)?;
|
||||||
compute_as_price(
|
compute_in_usd(
|
||||||
&mut self.p3sd_as_price,
|
&mut self.p3sd_in_usd,
|
||||||
self.p3sd.dateindex.as_ref().unwrap().iter(),
|
self.p3sd.dateindex.as_ref().unwrap().iter(),
|
||||||
)?;
|
)?;
|
||||||
compute_as_price(
|
compute_in_usd(
|
||||||
&mut self.m0_5sd_as_price,
|
&mut self.m0_5sd_in_usd,
|
||||||
self.m0_5sd.dateindex.as_ref().unwrap().iter(),
|
self.m0_5sd.dateindex.as_ref().unwrap().iter(),
|
||||||
)?;
|
)?;
|
||||||
compute_as_price(
|
compute_in_usd(
|
||||||
&mut self.m1sd_as_price,
|
&mut self.m1sd_in_usd,
|
||||||
self.m1sd.dateindex.as_ref().unwrap().iter(),
|
self.m1sd.dateindex.as_ref().unwrap().iter(),
|
||||||
)?;
|
)?;
|
||||||
compute_as_price(
|
compute_in_usd(
|
||||||
&mut self.m1_5sd_as_price,
|
&mut self.m1_5sd_in_usd,
|
||||||
self.m1_5sd.dateindex.as_ref().unwrap().iter(),
|
self.m1_5sd.dateindex.as_ref().unwrap().iter(),
|
||||||
)?;
|
)?;
|
||||||
compute_as_price(
|
compute_in_usd(
|
||||||
&mut self.m2sd_as_price,
|
&mut self.m2sd_in_usd,
|
||||||
self.m2sd.dateindex.as_ref().unwrap().iter(),
|
self.m2sd.dateindex.as_ref().unwrap().iter(),
|
||||||
)?;
|
)?;
|
||||||
compute_as_price(
|
compute_in_usd(
|
||||||
&mut self.m2_5sd_as_price,
|
&mut self.m2_5sd_in_usd,
|
||||||
self.m2_5sd.dateindex.as_ref().unwrap().iter(),
|
self.m2_5sd.dateindex.as_ref().unwrap().iter(),
|
||||||
)?;
|
)?;
|
||||||
compute_as_price(
|
compute_in_usd(
|
||||||
&mut self.m3sd_as_price,
|
&mut self.m3sd_in_usd,
|
||||||
self.m3sd.dateindex.as_ref().unwrap().iter(),
|
self.m3sd.dateindex.as_ref().unwrap().iter(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -685,19 +685,19 @@ impl ComputedStandardDeviationVecsFromDateIndex {
|
|||||||
self.m2sd.vecs(),
|
self.m2sd.vecs(),
|
||||||
self.m2_5sd.vecs(),
|
self.m2_5sd.vecs(),
|
||||||
self.m3sd.vecs(),
|
self.m3sd.vecs(),
|
||||||
self._0sd_as_price.vecs(),
|
self._0sd_in_usd.vecs(),
|
||||||
self.p0_5sd_as_price.vecs(),
|
self.p0_5sd_in_usd.vecs(),
|
||||||
self.p1sd_as_price.vecs(),
|
self.p1sd_in_usd.vecs(),
|
||||||
self.p1_5sd_as_price.vecs(),
|
self.p1_5sd_in_usd.vecs(),
|
||||||
self.p2sd_as_price.vecs(),
|
self.p2sd_in_usd.vecs(),
|
||||||
self.p2_5sd_as_price.vecs(),
|
self.p2_5sd_in_usd.vecs(),
|
||||||
self.p3sd_as_price.vecs(),
|
self.p3sd_in_usd.vecs(),
|
||||||
self.m0_5sd_as_price.vecs(),
|
self.m0_5sd_in_usd.vecs(),
|
||||||
self.m1sd_as_price.vecs(),
|
self.m1sd_in_usd.vecs(),
|
||||||
self.m1_5sd_as_price.vecs(),
|
self.m1_5sd_in_usd.vecs(),
|
||||||
self.m2sd_as_price.vecs(),
|
self.m2sd_in_usd.vecs(),
|
||||||
self.m2_5sd_as_price.vecs(),
|
self.m2_5sd_in_usd.vecs(),
|
||||||
self.m3sd_as_price.vecs(),
|
self.m3sd_in_usd.vecs(),
|
||||||
self.zscore.vecs(),
|
self.zscore.vecs(),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|||||||
@@ -138,10 +138,10 @@ impl ComputedValueVecsFromDateIndex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let dateindex_to_bitcoin = self.bitcoin.dateindex.as_ref().unwrap();
|
let dateindex_to_bitcoin = self.bitcoin.dateindex.as_ref().unwrap();
|
||||||
let dateindex_to_close = price
|
let dateindex_to_price_close = price
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.timeindexes_to_close
|
.timeindexes_to_price_close
|
||||||
.dateindex
|
.dateindex
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -156,7 +156,7 @@ impl ComputedValueVecsFromDateIndex {
|
|||||||
v.compute_from_bitcoin(
|
v.compute_from_bitcoin(
|
||||||
starting_indexes.dateindex,
|
starting_indexes.dateindex,
|
||||||
dateindex_to_bitcoin,
|
dateindex_to_bitcoin,
|
||||||
dateindex_to_close,
|
dateindex_to_price_close,
|
||||||
exit,
|
exit,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use allocative::Allocative;
|
||||||
use brk_error::Result;
|
use brk_error::Result;
|
||||||
use brk_indexer::Indexer;
|
use brk_indexer::Indexer;
|
||||||
use brk_structs::{Bitcoin, Dollars, Height, Sats, Version};
|
use brk_structs::{Bitcoin, Dollars, Height, Sats, Version};
|
||||||
@@ -12,7 +13,7 @@ use crate::{
|
|||||||
|
|
||||||
use super::{ComputedVecsFromHeight, VecBuilderOptions};
|
use super::{ComputedVecsFromHeight, VecBuilderOptions};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Allocative)]
|
||||||
pub struct ComputedValueVecsFromHeight {
|
pub struct ComputedValueVecsFromHeight {
|
||||||
pub sats: ComputedVecsFromHeight<Sats>,
|
pub sats: ComputedVecsFromHeight<Sats>,
|
||||||
pub bitcoin: ComputedVecsFromHeight<Bitcoin>,
|
pub bitcoin: ComputedVecsFromHeight<Bitcoin>,
|
||||||
@@ -139,7 +140,7 @@ impl ComputedValueVecsFromHeight {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let height_to_bitcoin = self.bitcoin.height.as_ref().unwrap();
|
let height_to_bitcoin = self.bitcoin.height.as_ref().unwrap();
|
||||||
let height_to_close = &price.as_ref().unwrap().chainindexes_to_close.height;
|
let height_to_price_close = &price.as_ref().unwrap().chainindexes_to_price_close.height;
|
||||||
|
|
||||||
if let Some(dollars) = self.dollars.as_mut() {
|
if let Some(dollars) = self.dollars.as_mut() {
|
||||||
dollars.compute_all(
|
dollars.compute_all(
|
||||||
@@ -151,7 +152,7 @@ impl ComputedValueVecsFromHeight {
|
|||||||
v.compute_from_bitcoin(
|
v.compute_from_bitcoin(
|
||||||
starting_indexes.height,
|
starting_indexes.height,
|
||||||
height_to_bitcoin,
|
height_to_bitcoin,
|
||||||
height_to_close,
|
height_to_price_close,
|
||||||
exit,
|
exit,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use allocative::Allocative;
|
||||||
use brk_error::Result;
|
use brk_error::Result;
|
||||||
use brk_indexer::Indexer;
|
use brk_indexer::Indexer;
|
||||||
use brk_structs::{Bitcoin, Close, Dollars, Height, Sats, TxIndex, Version};
|
use brk_structs::{Bitcoin, Close, Dollars, Height, Sats, TxIndex, Version};
|
||||||
@@ -10,7 +11,7 @@ use crate::{Indexes, grouped::Source, indexes, price};
|
|||||||
|
|
||||||
use super::{ComputedVecsFromTxindex, VecBuilderOptions};
|
use super::{ComputedVecsFromTxindex, VecBuilderOptions};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Allocative)]
|
||||||
pub struct ComputedValueVecsFromTxindex {
|
pub struct ComputedValueVecsFromTxindex {
|
||||||
pub sats: ComputedVecsFromTxindex<Sats>,
|
pub sats: ComputedVecsFromTxindex<Sats>,
|
||||||
pub bitcoin_txindex: LazyVecFrom1<TxIndex, Bitcoin, TxIndex, Sats>,
|
pub bitcoin_txindex: LazyVecFrom1<TxIndex, Bitcoin, TxIndex, Sats>,
|
||||||
@@ -78,23 +79,25 @@ impl ComputedValueVecsFromTxindex {
|
|||||||
version + VERSION,
|
version + VERSION,
|
||||||
bitcoin_txindex.boxed_clone(),
|
bitcoin_txindex.boxed_clone(),
|
||||||
indexes.txindex_to_height.boxed_clone(),
|
indexes.txindex_to_height.boxed_clone(),
|
||||||
price.chainindexes_to_close.height.boxed_clone(),
|
price.chainindexes_to_price_close.height.boxed_clone(),
|
||||||
|txindex: TxIndex,
|
|txindex: TxIndex,
|
||||||
txindex_to_btc_iter,
|
txindex_to_in_btc_iter,
|
||||||
txindex_to_height_iter,
|
txindex_to_height_iter,
|
||||||
height_to_close_iter| {
|
height_to_price_close_iter| {
|
||||||
let txindex = txindex.unwrap_to_usize();
|
let txindex = txindex.unwrap_to_usize();
|
||||||
txindex_to_btc_iter.next_at(txindex).and_then(|(_, value)| {
|
txindex_to_in_btc_iter
|
||||||
let btc = value.into_owned();
|
.next_at(txindex)
|
||||||
txindex_to_height_iter
|
.and_then(|(_, value)| {
|
||||||
.next_at(txindex)
|
let btc = value.into_owned();
|
||||||
.and_then(|(_, value)| {
|
txindex_to_height_iter
|
||||||
let height = value.into_owned();
|
.next_at(txindex)
|
||||||
height_to_close_iter
|
.and_then(|(_, value)| {
|
||||||
.next_at(height.unwrap_to_usize())
|
let height = value.into_owned();
|
||||||
.map(|(_, close)| *close.into_owned() * btc)
|
height_to_price_close_iter
|
||||||
})
|
.next_at(height.unwrap_to_usize())
|
||||||
})
|
.map(|(_, close)| *close.into_owned() * btc)
|
||||||
|
})
|
||||||
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -102,13 +102,13 @@ impl ComputedHeightValueVecs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let height_to_bitcoin = &self.bitcoin;
|
let height_to_bitcoin = &self.bitcoin;
|
||||||
let height_to_close = &price.as_ref().unwrap().chainindexes_to_close.height;
|
let height_to_price_close = &price.as_ref().unwrap().chainindexes_to_price_close.height;
|
||||||
|
|
||||||
if let Some(dollars) = self.dollars.as_mut() {
|
if let Some(dollars) = self.dollars.as_mut() {
|
||||||
dollars.compute_from_bitcoin(
|
dollars.compute_from_bitcoin(
|
||||||
starting_indexes.height,
|
starting_indexes.height,
|
||||||
height_to_bitcoin,
|
height_to_bitcoin,
|
||||||
height_to_close,
|
height_to_price_close,
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ impl Vecs {
|
|||||||
|index, _| Some(index),
|
|index, _| Some(index),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(Self {
|
let this = Self {
|
||||||
emptyoutputindex_to_emptyoutputindex,
|
emptyoutputindex_to_emptyoutputindex,
|
||||||
inputindex_to_inputindex,
|
inputindex_to_inputindex,
|
||||||
opreturnindex_to_opreturnindex,
|
opreturnindex_to_opreturnindex,
|
||||||
@@ -472,7 +472,16 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
|
|
||||||
db,
|
db,
|
||||||
})
|
};
|
||||||
|
|
||||||
|
this.db.retain_regions(
|
||||||
|
this.vecs()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|v| v.region_names())
|
||||||
|
.collect(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute(
|
pub fn compute(
|
||||||
|
|||||||
@@ -9,23 +9,23 @@ use brk_structs::Version;
|
|||||||
use log::info;
|
use log::info;
|
||||||
use vecdb::{AnyCollectableVec, Exit, Format};
|
use vecdb::{AnyCollectableVec, Exit, Format};
|
||||||
|
|
||||||
mod blocks;
|
mod chain;
|
||||||
mod cointime;
|
mod cointime;
|
||||||
mod constants;
|
mod constants;
|
||||||
mod fetched;
|
mod fetched;
|
||||||
mod grouped;
|
mod grouped;
|
||||||
mod indexes;
|
mod indexes;
|
||||||
mod market;
|
mod market;
|
||||||
mod mining;
|
mod pools;
|
||||||
mod price;
|
mod price;
|
||||||
mod stateful;
|
mod stateful;
|
||||||
mod states;
|
mod states;
|
||||||
mod traits;
|
mod traits;
|
||||||
mod transactions;
|
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use indexes::Indexes;
|
use indexes::Indexes;
|
||||||
|
|
||||||
|
pub use pools::*;
|
||||||
pub use states::PriceToAmount;
|
pub use states::PriceToAmount;
|
||||||
use states::*;
|
use states::*;
|
||||||
|
|
||||||
@@ -33,17 +33,16 @@ use states::*;
|
|||||||
pub struct Computer {
|
pub struct Computer {
|
||||||
pub indexes: indexes::Vecs,
|
pub indexes: indexes::Vecs,
|
||||||
pub constants: constants::Vecs,
|
pub constants: constants::Vecs,
|
||||||
pub blocks: blocks::Vecs,
|
|
||||||
pub mining: mining::Vecs,
|
|
||||||
pub market: market::Vecs,
|
pub market: market::Vecs,
|
||||||
|
pub pools: pools::Vecs,
|
||||||
pub price: Option<price::Vecs>,
|
pub price: Option<price::Vecs>,
|
||||||
pub transactions: transactions::Vecs,
|
pub chain: chain::Vecs,
|
||||||
pub stateful: stateful::Vecs,
|
pub stateful: stateful::Vecs,
|
||||||
pub fetched: Option<fetched::Vecs>,
|
pub fetched: Option<fetched::Vecs>,
|
||||||
pub cointime: cointime::Vecs,
|
pub cointime: cointime::Vecs,
|
||||||
}
|
}
|
||||||
|
|
||||||
const VERSION: Version = Version::TWO;
|
const VERSION: Version = Version::new(4);
|
||||||
|
|
||||||
impl Computer {
|
impl Computer {
|
||||||
/// Do NOT import multiple times or things will break !!!
|
/// Do NOT import multiple times or things will break !!!
|
||||||
@@ -52,6 +51,8 @@ impl Computer {
|
|||||||
indexer: &Indexer,
|
indexer: &Indexer,
|
||||||
fetcher: Option<Fetcher>,
|
fetcher: Option<Fetcher>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
|
info!("Importing computer...");
|
||||||
|
|
||||||
let computed_path = outputs_path.join("computed");
|
let computed_path = outputs_path.join("computed");
|
||||||
|
|
||||||
let indexes =
|
let indexes =
|
||||||
@@ -66,8 +67,6 @@ impl Computer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
blocks: blocks::Vecs::forced_import(&computed_path, VERSION + Version::ZERO, &indexes)?,
|
|
||||||
mining: mining::Vecs::forced_import(&computed_path, VERSION + Version::ZERO, &indexes)?,
|
|
||||||
constants: constants::Vecs::forced_import(
|
constants: constants::Vecs::forced_import(
|
||||||
&computed_path,
|
&computed_path,
|
||||||
VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
@@ -81,13 +80,19 @@ impl Computer {
|
|||||||
&indexes,
|
&indexes,
|
||||||
price.as_ref(),
|
price.as_ref(),
|
||||||
)?,
|
)?,
|
||||||
transactions: transactions::Vecs::forced_import(
|
chain: chain::Vecs::forced_import(
|
||||||
&computed_path,
|
&computed_path,
|
||||||
VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
indexer,
|
indexer,
|
||||||
&indexes,
|
&indexes,
|
||||||
price.as_ref(),
|
price.as_ref(),
|
||||||
)?,
|
)?,
|
||||||
|
pools: pools::Vecs::forced_import(
|
||||||
|
&computed_path,
|
||||||
|
VERSION + Version::ZERO,
|
||||||
|
&indexes,
|
||||||
|
price.as_ref(),
|
||||||
|
)?,
|
||||||
cointime: cointime::Vecs::forced_import(
|
cointime: cointime::Vecs::forced_import(
|
||||||
&computed_path,
|
&computed_path,
|
||||||
VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
@@ -113,14 +118,6 @@ impl Computer {
|
|||||||
self.constants
|
self.constants
|
||||||
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
||||||
|
|
||||||
info!("Computing blocks...");
|
|
||||||
self.blocks
|
|
||||||
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
|
||||||
|
|
||||||
info!("Computing mining...");
|
|
||||||
self.mining
|
|
||||||
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
|
||||||
|
|
||||||
if let Some(fetched) = self.fetched.as_mut() {
|
if let Some(fetched) = self.fetched.as_mut() {
|
||||||
info!("Computing fetched...");
|
info!("Computing fetched...");
|
||||||
fetched.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
fetched.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
||||||
@@ -135,44 +132,59 @@ impl Computer {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Computing transactions...");
|
std::thread::scope(|scope| -> Result<()> {
|
||||||
self.transactions.compute(
|
let chain = scope.spawn(|| -> Result<()> {
|
||||||
|
info!("Computing chain...");
|
||||||
|
self.chain.compute(
|
||||||
|
indexer,
|
||||||
|
&self.indexes,
|
||||||
|
&starting_indexes,
|
||||||
|
self.price.as_ref(),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(price) = self.price.as_ref() {
|
||||||
|
info!("Computing market...");
|
||||||
|
self.market
|
||||||
|
.compute(indexer, &self.indexes, price, &starting_indexes, exit)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// let _ = generate_allocation_files(&self.pools);
|
||||||
|
|
||||||
|
chain.join().unwrap()?;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
self.pools.compute(
|
||||||
indexer,
|
indexer,
|
||||||
&self.indexes,
|
&self.indexes,
|
||||||
&starting_indexes,
|
&starting_indexes,
|
||||||
|
&self.chain,
|
||||||
self.price.as_ref(),
|
self.price.as_ref(),
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if let Some(price) = self.price.as_ref() {
|
// return Ok(());
|
||||||
info!("Computing market...");
|
|
||||||
self.market.compute(
|
|
||||||
indexer,
|
|
||||||
&self.indexes,
|
|
||||||
price,
|
|
||||||
&mut self.transactions,
|
|
||||||
&starting_indexes,
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("Computing stateful...");
|
info!("Computing stateful...");
|
||||||
self.stateful.compute(
|
self.stateful.compute(
|
||||||
indexer,
|
indexer,
|
||||||
&self.indexes,
|
&self.indexes,
|
||||||
&self.transactions,
|
&self.chain,
|
||||||
self.price.as_ref(),
|
self.price.as_ref(),
|
||||||
&self.market,
|
|
||||||
&mut starting_indexes,
|
&mut starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
info!("Computing cointime...");
|
||||||
self.cointime.compute(
|
self.cointime.compute(
|
||||||
indexer,
|
indexer,
|
||||||
&self.indexes,
|
&self.indexes,
|
||||||
&starting_indexes,
|
&starting_indexes,
|
||||||
self.price.as_ref(),
|
self.price.as_ref(),
|
||||||
&self.transactions,
|
&self.chain,
|
||||||
&self.stateful,
|
&self.stateful,
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
@@ -184,12 +196,11 @@ impl Computer {
|
|||||||
[
|
[
|
||||||
self.constants.vecs(),
|
self.constants.vecs(),
|
||||||
self.indexes.vecs(),
|
self.indexes.vecs(),
|
||||||
self.blocks.vecs(),
|
|
||||||
self.mining.vecs(),
|
|
||||||
self.market.vecs(),
|
self.market.vecs(),
|
||||||
self.transactions.vecs(),
|
self.chain.vecs(),
|
||||||
self.stateful.vecs(),
|
self.stateful.vecs(),
|
||||||
self.cointime.vecs(),
|
self.cointime.vecs(),
|
||||||
|
self.pools.vecs(),
|
||||||
self.fetched.as_ref().map_or(vec![], |v| v.vecs()),
|
self.fetched.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
self.price.as_ref().map_or(vec![], |v| v.vecs()),
|
self.price.as_ref().map_or(vec![], |v| v.vecs()),
|
||||||
]
|
]
|
||||||
@@ -202,3 +213,36 @@ impl Computer {
|
|||||||
Box::leak(Box::new(self.clone()))
|
Box::leak(Box::new(self.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pub fn generate_allocation_files(monitored: &pools::Vecs) -> Result<()> {
|
||||||
|
// info!("Generating Allocative files...");
|
||||||
|
|
||||||
|
// let mut flamegraph = allocative::FlameGraphBuilder::default();
|
||||||
|
// flamegraph.visit_root(monitored);
|
||||||
|
// let output = flamegraph.finish();
|
||||||
|
|
||||||
|
// let folder = format!(
|
||||||
|
// "at-{}",
|
||||||
|
// jiff::Timestamp::now().strftime("%Y-%m-%d_%Hh%Mm%Ss"),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// let path = std::path::PathBuf::from(&format!("./target/flamegraph/{folder}"));
|
||||||
|
// std::fs::create_dir_all(&path)?;
|
||||||
|
|
||||||
|
// // fs::write(path.join("flamegraph.src"), &output.flamegraph())?;
|
||||||
|
|
||||||
|
// let mut fg_svg = Vec::new();
|
||||||
|
// inferno::flamegraph::from_reader(
|
||||||
|
// &mut inferno::flamegraph::Options::default(),
|
||||||
|
// output.flamegraph().write().as_bytes(),
|
||||||
|
// &mut fg_svg,
|
||||||
|
// )?;
|
||||||
|
|
||||||
|
// std::fs::write(path.join("flamegraph.svg"), &fg_svg)?;
|
||||||
|
|
||||||
|
// std::fs::write(path.join("warnings.txt"), output.warnings())?;
|
||||||
|
|
||||||
|
// info!("Successfully generated Allocative files");
|
||||||
|
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
|||||||
+452
-264
File diff suppressed because it is too large
Load Diff
@@ -1,151 +0,0 @@
|
|||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use brk_error::Result;
|
|
||||||
use brk_indexer::Indexer;
|
|
||||||
use brk_structs::{DifficultyEpoch, HalvingEpoch, StoredF64, Version};
|
|
||||||
use vecdb::{AnyCollectableVec, Database, Exit, PAGE_SIZE, VecIterator};
|
|
||||||
|
|
||||||
use crate::grouped::Source;
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
Indexes,
|
|
||||||
grouped::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, VecBuilderOptions},
|
|
||||||
indexes,
|
|
||||||
};
|
|
||||||
|
|
||||||
const VERSION: Version = Version::ZERO;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Vecs {
|
|
||||||
db: Database,
|
|
||||||
|
|
||||||
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
|
|
||||||
pub indexes_to_difficultyepoch: ComputedVecsFromDateIndex<DifficultyEpoch>,
|
|
||||||
pub indexes_to_halvingepoch: ComputedVecsFromDateIndex<HalvingEpoch>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Vecs {
|
|
||||||
pub fn forced_import(parent: &Path, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
|
|
||||||
let db = Database::open(&parent.join("mining"))?;
|
|
||||||
db.set_min_len(PAGE_SIZE * 1_000_000)?;
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
indexes_to_difficulty: ComputedVecsFromHeight::forced_import(
|
|
||||||
&db,
|
|
||||||
"difficulty",
|
|
||||||
Source::None,
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
indexes,
|
|
||||||
VecBuilderOptions::default().add_last(),
|
|
||||||
)?,
|
|
||||||
indexes_to_difficultyepoch: ComputedVecsFromDateIndex::forced_import(
|
|
||||||
&db,
|
|
||||||
"difficultyepoch",
|
|
||||||
Source::Compute,
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
indexes,
|
|
||||||
VecBuilderOptions::default().add_last(),
|
|
||||||
)?,
|
|
||||||
indexes_to_halvingepoch: ComputedVecsFromDateIndex::forced_import(
|
|
||||||
&db,
|
|
||||||
"halvingepoch",
|
|
||||||
Source::Compute,
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
indexes,
|
|
||||||
VecBuilderOptions::default().add_last(),
|
|
||||||
)?,
|
|
||||||
|
|
||||||
db,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compute(
|
|
||||||
&mut self,
|
|
||||||
indexer: &Indexer,
|
|
||||||
indexes: &indexes::Vecs,
|
|
||||||
starting_indexes: &Indexes,
|
|
||||||
exit: &Exit,
|
|
||||||
) -> Result<()> {
|
|
||||||
self.compute_(indexer, indexes, starting_indexes, exit)?;
|
|
||||||
self.db.flush_then_punch()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compute_(
|
|
||||||
&mut self,
|
|
||||||
indexer: &Indexer,
|
|
||||||
indexes: &indexes::Vecs,
|
|
||||||
starting_indexes: &Indexes,
|
|
||||||
exit: &Exit,
|
|
||||||
) -> Result<()> {
|
|
||||||
let mut height_to_difficultyepoch_iter = indexes.height_to_difficultyepoch.into_iter();
|
|
||||||
self.indexes_to_difficultyepoch.compute_all(
|
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
|
||||||
let mut height_count_iter = indexes.dateindex_to_height_count.into_iter();
|
|
||||||
vec.compute_transform(
|
|
||||||
starting_indexes.dateindex,
|
|
||||||
&indexes.dateindex_to_first_height,
|
|
||||||
|(di, height, ..)| {
|
|
||||||
(
|
|
||||||
di,
|
|
||||||
height_to_difficultyepoch_iter.unwrap_get_inner(
|
|
||||||
height + (*height_count_iter.unwrap_get_inner(di) - 1),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut height_to_halvingepoch_iter = indexes.height_to_halvingepoch.into_iter();
|
|
||||||
self.indexes_to_halvingepoch.compute_all(
|
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
|vec, _, indexes, starting_indexes, exit| {
|
|
||||||
let mut height_count_iter = indexes.dateindex_to_height_count.into_iter();
|
|
||||||
vec.compute_transform(
|
|
||||||
starting_indexes.dateindex,
|
|
||||||
&indexes.dateindex_to_first_height,
|
|
||||||
|(di, height, ..)| {
|
|
||||||
(
|
|
||||||
di,
|
|
||||||
height_to_halvingepoch_iter.unwrap_get_inner(
|
|
||||||
height + (*height_count_iter.unwrap_get_inner(di) - 1),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.indexes_to_difficulty.compute_rest(
|
|
||||||
indexes,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
Some(&indexer.vecs.height_to_difficulty),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
|
||||||
[
|
|
||||||
self.indexes_to_difficulty.vecs(),
|
|
||||||
self.indexes_to_difficultyepoch.vecs(),
|
|
||||||
self.indexes_to_halvingepoch.vecs(),
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.flatten()
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,287 @@
|
|||||||
|
use allocative::Allocative;
|
||||||
|
use num_enum::{FromPrimitive, IntoPrimitive};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||||
|
|
||||||
|
// Created from the list in `pools.rs`
|
||||||
|
// Can be used as index for said list
|
||||||
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
|
#[derive(
|
||||||
|
Debug,
|
||||||
|
Copy,
|
||||||
|
Clone,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
Serialize,
|
||||||
|
Deserialize,
|
||||||
|
FromPrimitive,
|
||||||
|
IntoPrimitive,
|
||||||
|
FromBytes,
|
||||||
|
IntoBytes,
|
||||||
|
Immutable,
|
||||||
|
KnownLayout,
|
||||||
|
Allocative,
|
||||||
|
)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum PoolId {
|
||||||
|
#[default]
|
||||||
|
Unknown,
|
||||||
|
BlockFills,
|
||||||
|
UltimusPool,
|
||||||
|
TerraPool,
|
||||||
|
Luxor,
|
||||||
|
OneThash,
|
||||||
|
BtcCom,
|
||||||
|
Bitfarms,
|
||||||
|
HuobiPool,
|
||||||
|
WayiCn,
|
||||||
|
CanoePool,
|
||||||
|
BtcTop,
|
||||||
|
BitcoinCom,
|
||||||
|
Pool175btc,
|
||||||
|
GbMiners,
|
||||||
|
AXbt,
|
||||||
|
AsicMiner,
|
||||||
|
BitMinter,
|
||||||
|
BitcoinRussia,
|
||||||
|
BtcServ,
|
||||||
|
SimplecoinUs,
|
||||||
|
BtcGuild,
|
||||||
|
Eligius,
|
||||||
|
OzCoin,
|
||||||
|
EclipseMc,
|
||||||
|
MaxBtc,
|
||||||
|
TripleMining,
|
||||||
|
CoinLab,
|
||||||
|
Pool50btc,
|
||||||
|
GhashIo,
|
||||||
|
StMiningCorp,
|
||||||
|
Bitparking,
|
||||||
|
Mmpool,
|
||||||
|
Polmine,
|
||||||
|
KncMiner,
|
||||||
|
Bitalo,
|
||||||
|
F2Pool,
|
||||||
|
Hhtt,
|
||||||
|
MegaBigPower,
|
||||||
|
MtRed,
|
||||||
|
NmcBit,
|
||||||
|
YourbtcNet,
|
||||||
|
GiveMeCoins,
|
||||||
|
BraiinsPool,
|
||||||
|
AntPool,
|
||||||
|
MultiCoinCo,
|
||||||
|
BcpoolIo,
|
||||||
|
Cointerra,
|
||||||
|
KanoPool,
|
||||||
|
SoloCk,
|
||||||
|
CkPool,
|
||||||
|
NiceHash,
|
||||||
|
BitClub,
|
||||||
|
BitcoinAffiliateNetwork,
|
||||||
|
Btcc,
|
||||||
|
BwPool,
|
||||||
|
ExxBw,
|
||||||
|
Bitsolo,
|
||||||
|
BitFury,
|
||||||
|
TwentyOneInc,
|
||||||
|
DigitalBtc,
|
||||||
|
EightBaochi,
|
||||||
|
MyBtcCoinPool,
|
||||||
|
TbDice,
|
||||||
|
HashPool,
|
||||||
|
Nexious,
|
||||||
|
BravoMining,
|
||||||
|
HotPool,
|
||||||
|
OkExPool,
|
||||||
|
BcMonster,
|
||||||
|
OneHash,
|
||||||
|
Bixin,
|
||||||
|
TatmasPool,
|
||||||
|
ViaBtc,
|
||||||
|
ConnectBtc,
|
||||||
|
BatPool,
|
||||||
|
Waterhole,
|
||||||
|
DcExploration,
|
||||||
|
Dcex,
|
||||||
|
BtPool,
|
||||||
|
FiftyEightCoin,
|
||||||
|
BitcoinIndia,
|
||||||
|
ShawnP0wers,
|
||||||
|
PHashIo,
|
||||||
|
RigPool,
|
||||||
|
HaoZhuZhu,
|
||||||
|
SevenPool,
|
||||||
|
MiningKings,
|
||||||
|
HashBx,
|
||||||
|
DPool,
|
||||||
|
Rawpool,
|
||||||
|
Haominer,
|
||||||
|
Helix,
|
||||||
|
BitcoinUkraine,
|
||||||
|
Poolin,
|
||||||
|
SecretSuperstar,
|
||||||
|
TigerpoolNet,
|
||||||
|
SigmapoolCom,
|
||||||
|
OkpoolTop,
|
||||||
|
Hummerpool,
|
||||||
|
Tangpool,
|
||||||
|
BytePool,
|
||||||
|
SpiderPool,
|
||||||
|
NovaBlock,
|
||||||
|
MiningCity,
|
||||||
|
BinancePool,
|
||||||
|
Minerium,
|
||||||
|
LubianCom,
|
||||||
|
Okkong,
|
||||||
|
AaoPool,
|
||||||
|
EmcdPool,
|
||||||
|
FoundryUsa,
|
||||||
|
SbiCrypto,
|
||||||
|
ArkPool,
|
||||||
|
PureBtcCom,
|
||||||
|
MaraPool,
|
||||||
|
KuCoinPool,
|
||||||
|
EntrustCharityPool,
|
||||||
|
OkMiner,
|
||||||
|
Titan,
|
||||||
|
PegaPool,
|
||||||
|
BtcNuggets,
|
||||||
|
CloudHashing,
|
||||||
|
DigitalXMintsy,
|
||||||
|
Telco214,
|
||||||
|
BtcPoolParty,
|
||||||
|
Multipool,
|
||||||
|
TransactionCoinMining,
|
||||||
|
BtcDig,
|
||||||
|
TrickysBtcPool,
|
||||||
|
BtcMp,
|
||||||
|
Eobot,
|
||||||
|
Unomp,
|
||||||
|
Patels,
|
||||||
|
GoGreenLight,
|
||||||
|
EkanemBtc,
|
||||||
|
Canoe,
|
||||||
|
Tiger,
|
||||||
|
OneM1x,
|
||||||
|
Zulupool,
|
||||||
|
SecPool,
|
||||||
|
Ocean,
|
||||||
|
WhitePool,
|
||||||
|
Wk057,
|
||||||
|
FutureBitApolloSolo,
|
||||||
|
CarbonNegative,
|
||||||
|
PortlandHodl,
|
||||||
|
Phoenix,
|
||||||
|
Neopool,
|
||||||
|
MaxiPool,
|
||||||
|
BitFuFuPool,
|
||||||
|
LuckyPool,
|
||||||
|
MiningDutch,
|
||||||
|
PublicPool,
|
||||||
|
MiningSquared,
|
||||||
|
InnopolisTech,
|
||||||
|
BtcLab,
|
||||||
|
Parasite,
|
||||||
|
Dummy158,
|
||||||
|
Dummy159,
|
||||||
|
Dummy160,
|
||||||
|
Dummy161,
|
||||||
|
Dummy162,
|
||||||
|
Dummy163,
|
||||||
|
Dummy164,
|
||||||
|
Dummy165,
|
||||||
|
Dummy166,
|
||||||
|
Dummy167,
|
||||||
|
Dummy168,
|
||||||
|
Dummy169,
|
||||||
|
Dummy170,
|
||||||
|
Dummy171,
|
||||||
|
Dummy172,
|
||||||
|
Dummy173,
|
||||||
|
Dummy174,
|
||||||
|
Dummy175,
|
||||||
|
Dummy176,
|
||||||
|
Dummy177,
|
||||||
|
Dummy178,
|
||||||
|
Dummy179,
|
||||||
|
Dummy180,
|
||||||
|
Dummy181,
|
||||||
|
Dummy182,
|
||||||
|
Dummy183,
|
||||||
|
Dummy184,
|
||||||
|
Dummy185,
|
||||||
|
Dummy186,
|
||||||
|
Dummy187,
|
||||||
|
Dummy188,
|
||||||
|
Dummy189,
|
||||||
|
Dummy190,
|
||||||
|
Dummy191,
|
||||||
|
Dummy192,
|
||||||
|
Dummy193,
|
||||||
|
Dummy194,
|
||||||
|
Dummy195,
|
||||||
|
Dummy196,
|
||||||
|
Dummy197,
|
||||||
|
Dummy198,
|
||||||
|
Dummy199,
|
||||||
|
Dummy200,
|
||||||
|
Dummy201,
|
||||||
|
Dummy202,
|
||||||
|
Dummy203,
|
||||||
|
Dummy204,
|
||||||
|
Dummy205,
|
||||||
|
Dummy206,
|
||||||
|
Dummy207,
|
||||||
|
Dummy208,
|
||||||
|
Dummy209,
|
||||||
|
Dummy210,
|
||||||
|
Dummy211,
|
||||||
|
Dummy212,
|
||||||
|
Dummy213,
|
||||||
|
Dummy214,
|
||||||
|
Dummy215,
|
||||||
|
Dummy216,
|
||||||
|
Dummy217,
|
||||||
|
Dummy218,
|
||||||
|
Dummy219,
|
||||||
|
Dummy220,
|
||||||
|
Dummy221,
|
||||||
|
Dummy222,
|
||||||
|
Dummy223,
|
||||||
|
Dummy224,
|
||||||
|
Dummy225,
|
||||||
|
Dummy226,
|
||||||
|
Dummy227,
|
||||||
|
Dummy228,
|
||||||
|
Dummy229,
|
||||||
|
Dummy230,
|
||||||
|
Dummy231,
|
||||||
|
Dummy232,
|
||||||
|
Dummy233,
|
||||||
|
Dummy234,
|
||||||
|
Dummy235,
|
||||||
|
Dummy236,
|
||||||
|
Dummy237,
|
||||||
|
Dummy238,
|
||||||
|
Dummy239,
|
||||||
|
Dummy240,
|
||||||
|
Dummy241,
|
||||||
|
Dummy242,
|
||||||
|
Dummy243,
|
||||||
|
Dummy244,
|
||||||
|
Dummy245,
|
||||||
|
Dummy246,
|
||||||
|
Dummy247,
|
||||||
|
Dummy248,
|
||||||
|
Dummy249,
|
||||||
|
Dummy250,
|
||||||
|
Dummy251,
|
||||||
|
Dummy252,
|
||||||
|
Dummy253,
|
||||||
|
Dummy254,
|
||||||
|
Dummy255,
|
||||||
|
}
|
||||||
@@ -0,0 +1,240 @@
|
|||||||
|
use std::{collections::BTreeMap, path::Path};
|
||||||
|
|
||||||
|
use allocative::Allocative;
|
||||||
|
use brk_error::Result;
|
||||||
|
use brk_indexer::Indexer;
|
||||||
|
use brk_store::AnyStore;
|
||||||
|
use brk_structs::{AddressBytes, Height, OutputIndex, OutputType};
|
||||||
|
use rayon::prelude::*;
|
||||||
|
use vecdb::{
|
||||||
|
AnyCollectableVec, AnyIterableVec, AnyStoredVec, AnyVec, Database, Exit, GenericStoredVec,
|
||||||
|
PAGE_SIZE, RawVec, StoredIndex, VecIterator, Version,
|
||||||
|
};
|
||||||
|
|
||||||
|
mod id;
|
||||||
|
mod pool;
|
||||||
|
#[allow(clippy::module_inception)]
|
||||||
|
mod pools;
|
||||||
|
mod vecs;
|
||||||
|
|
||||||
|
pub use id::*;
|
||||||
|
pub use pool::*;
|
||||||
|
pub use pools::*;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
chain,
|
||||||
|
indexes::{self, Indexes},
|
||||||
|
price,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Allocative)]
|
||||||
|
pub struct Vecs {
|
||||||
|
db: Database,
|
||||||
|
pools: &'static Pools,
|
||||||
|
height_to_pool: RawVec<Height, PoolId>,
|
||||||
|
|
||||||
|
vecs: BTreeMap<PoolId, vecs::Vecs>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vecs {
|
||||||
|
pub fn forced_import(
|
||||||
|
parent_path: &Path,
|
||||||
|
parent_version: Version,
|
||||||
|
indexes: &indexes::Vecs,
|
||||||
|
price: Option<&price::Vecs>,
|
||||||
|
) -> Result<Self> {
|
||||||
|
let db = Database::open(&parent_path.join("pools"))?;
|
||||||
|
db.set_min_len(PAGE_SIZE * 1_000_000)?;
|
||||||
|
let pools = pools();
|
||||||
|
|
||||||
|
let version = parent_version + Version::new(3) + Version::new(pools.len() as u64);
|
||||||
|
|
||||||
|
let this = Self {
|
||||||
|
height_to_pool: RawVec::forced_import(&db, "pool", version + Version::ZERO)?,
|
||||||
|
vecs: pools
|
||||||
|
.iter()
|
||||||
|
.map(|pool| {
|
||||||
|
vecs::Vecs::forced_import(
|
||||||
|
&db,
|
||||||
|
pool.id,
|
||||||
|
pools,
|
||||||
|
version + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
price,
|
||||||
|
)
|
||||||
|
.map(|vecs| (pool.id, vecs))
|
||||||
|
})
|
||||||
|
.collect::<Result<BTreeMap<_, _>>>()?,
|
||||||
|
pools,
|
||||||
|
db,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.db.retain_regions(
|
||||||
|
this.vecs()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|v| v.region_names())
|
||||||
|
.collect(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compute(
|
||||||
|
&mut self,
|
||||||
|
indexer: &Indexer,
|
||||||
|
indexes: &indexes::Vecs,
|
||||||
|
starting_indexes: &Indexes,
|
||||||
|
chain: &chain::Vecs,
|
||||||
|
price: Option<&price::Vecs>,
|
||||||
|
exit: &Exit,
|
||||||
|
) -> Result<()> {
|
||||||
|
self.compute_(indexer, indexes, starting_indexes, chain, price, exit)?;
|
||||||
|
self.db.flush_then_punch()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_(
|
||||||
|
&mut self,
|
||||||
|
indexer: &Indexer,
|
||||||
|
indexes: &indexes::Vecs,
|
||||||
|
starting_indexes: &Indexes,
|
||||||
|
chain: &chain::Vecs,
|
||||||
|
price: Option<&price::Vecs>,
|
||||||
|
exit: &Exit,
|
||||||
|
) -> Result<()> {
|
||||||
|
self.compute_height_to_pool(indexer, indexes, starting_indexes, exit)?;
|
||||||
|
|
||||||
|
self.vecs.par_iter_mut().try_for_each(|(_, vecs)| {
|
||||||
|
vecs.compute(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
&self.height_to_pool,
|
||||||
|
chain,
|
||||||
|
price,
|
||||||
|
exit,
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_height_to_pool(
|
||||||
|
&mut self,
|
||||||
|
indexer: &Indexer,
|
||||||
|
indexes: &indexes::Vecs,
|
||||||
|
starting_indexes: &Indexes,
|
||||||
|
exit: &Exit,
|
||||||
|
) -> Result<()> {
|
||||||
|
self.height_to_pool.validate_computed_version_or_reset(
|
||||||
|
self.height_to_pool.version() + indexer.stores.height_to_coinbase_tag.version(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut height_to_first_txindex_iter = indexer.vecs.height_to_first_txindex.iter();
|
||||||
|
let mut txindex_to_first_outputindex_iter =
|
||||||
|
indexer.vecs.txindex_to_first_outputindex.iter();
|
||||||
|
let mut txindex_to_output_count_iter = indexes.txindex_to_output_count.iter();
|
||||||
|
let mut outputindex_to_outputtype_iter = indexer.vecs.outputindex_to_outputtype.iter();
|
||||||
|
let mut outputindex_to_typeindex_iter = indexer.vecs.outputindex_to_typeindex.iter();
|
||||||
|
let mut p2pk65addressindex_to_p2pk65bytes_iter =
|
||||||
|
indexer.vecs.p2pk65addressindex_to_p2pk65bytes.iter();
|
||||||
|
let mut p2pk33addressindex_to_p2pk33bytes_iter =
|
||||||
|
indexer.vecs.p2pk33addressindex_to_p2pk33bytes.iter();
|
||||||
|
let mut p2pkhaddressindex_to_p2pkhbytes_iter =
|
||||||
|
indexer.vecs.p2pkhaddressindex_to_p2pkhbytes.iter();
|
||||||
|
let mut p2shaddressindex_to_p2shbytes_iter =
|
||||||
|
indexer.vecs.p2shaddressindex_to_p2shbytes.iter();
|
||||||
|
let mut p2wpkhaddressindex_to_p2wpkhbytes_iter =
|
||||||
|
indexer.vecs.p2wpkhaddressindex_to_p2wpkhbytes.iter();
|
||||||
|
let mut p2wshaddressindex_to_p2wshbytes_iter =
|
||||||
|
indexer.vecs.p2wshaddressindex_to_p2wshbytes.iter();
|
||||||
|
let mut p2traddressindex_to_p2trbytes_iter =
|
||||||
|
indexer.vecs.p2traddressindex_to_p2trbytes.iter();
|
||||||
|
let mut p2aaddressindex_to_p2abytes_iter = indexer.vecs.p2aaddressindex_to_p2abytes.iter();
|
||||||
|
|
||||||
|
let unknown = self.pools.get_unknown();
|
||||||
|
|
||||||
|
let min = starting_indexes
|
||||||
|
.height
|
||||||
|
.unwrap_to_usize()
|
||||||
|
.min(self.height_to_pool.len());
|
||||||
|
|
||||||
|
indexer
|
||||||
|
.stores
|
||||||
|
.height_to_coinbase_tag
|
||||||
|
.iter()
|
||||||
|
.skip(min)
|
||||||
|
.try_for_each(|(height, coinbase_tag)| -> Result<()> {
|
||||||
|
let txindex = height_to_first_txindex_iter.unwrap_get_inner(height);
|
||||||
|
let outputindex = txindex_to_first_outputindex_iter.unwrap_get_inner(txindex);
|
||||||
|
let outputcount = txindex_to_output_count_iter.unwrap_get_inner(txindex);
|
||||||
|
|
||||||
|
let pool = (*outputindex..(*outputindex + *outputcount))
|
||||||
|
.map(OutputIndex::from)
|
||||||
|
.find_map(|outputindex| {
|
||||||
|
let outputtype =
|
||||||
|
outputindex_to_outputtype_iter.unwrap_get_inner(outputindex);
|
||||||
|
let typeindex = outputindex_to_typeindex_iter.unwrap_get_inner(outputindex);
|
||||||
|
|
||||||
|
let address = match outputtype {
|
||||||
|
OutputType::P2PK65 => Some(AddressBytes::from(
|
||||||
|
p2pk65addressindex_to_p2pk65bytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2PK33 => Some(AddressBytes::from(
|
||||||
|
p2pk33addressindex_to_p2pk33bytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2PKH => Some(AddressBytes::from(
|
||||||
|
p2pkhaddressindex_to_p2pkhbytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2SH => Some(AddressBytes::from(
|
||||||
|
p2shaddressindex_to_p2shbytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2WPKH => Some(AddressBytes::from(
|
||||||
|
p2wpkhaddressindex_to_p2wpkhbytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2WSH => Some(AddressBytes::from(
|
||||||
|
p2wshaddressindex_to_p2wshbytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2TR => Some(AddressBytes::from(
|
||||||
|
p2traddressindex_to_p2trbytes_iter
|
||||||
|
.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
OutputType::P2A => Some(AddressBytes::from(
|
||||||
|
p2aaddressindex_to_p2abytes_iter.unwrap_get_inner(typeindex.into()),
|
||||||
|
)),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
address
|
||||||
|
.and_then(|address| self.pools.find_from_address(&address.to_string()))
|
||||||
|
})
|
||||||
|
.or_else(|| self.pools.find_from_coinbase_tag(&coinbase_tag))
|
||||||
|
.unwrap_or(unknown);
|
||||||
|
|
||||||
|
self.height_to_pool.push_if_needed(height, pool.id)?;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
self.height_to_pool.safe_flush(exit)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||||
|
[
|
||||||
|
self.vecs
|
||||||
|
.iter()
|
||||||
|
.flat_map(|(_, vecs)| vecs.vecs())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
vec![&self.height_to_pool],
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
use allocative::Allocative;
|
||||||
|
|
||||||
|
use crate::pools::PoolId;
|
||||||
|
|
||||||
|
#[derive(Debug, Allocative)]
|
||||||
|
pub struct Pool {
|
||||||
|
pub id: PoolId,
|
||||||
|
pub name: &'static str,
|
||||||
|
pub addresses: Box<[&'static str]>,
|
||||||
|
pub tags: Box<[&'static str]>,
|
||||||
|
pub tags_lowercase: Box<[String]>,
|
||||||
|
pub link: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pool {
|
||||||
|
pub fn serialized_id(&self) -> String {
|
||||||
|
let value = serde_json::to_value(self.id).unwrap();
|
||||||
|
value.as_str().unwrap().to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(usize, JSONPool)> for Pool {
|
||||||
|
fn from((index, pool): (usize, JSONPool)) -> Self {
|
||||||
|
Self {
|
||||||
|
id: (index as u8).into(),
|
||||||
|
name: pool.name,
|
||||||
|
addresses: pool.addresses,
|
||||||
|
tags_lowercase: pool
|
||||||
|
.tags
|
||||||
|
.iter()
|
||||||
|
.map(|t| t.to_lowercase())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_boxed_slice(),
|
||||||
|
tags: pool.tags,
|
||||||
|
link: pool.link,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct JSONPool {
|
||||||
|
pub name: &'static str,
|
||||||
|
pub addresses: Box<[&'static str]>,
|
||||||
|
pub tags: Box<[&'static str]>,
|
||||||
|
pub link: &'static str,
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,467 @@
|
|||||||
|
use allocative::Allocative;
|
||||||
|
use brk_error::Result;
|
||||||
|
use brk_indexer::Indexer;
|
||||||
|
use brk_structs::{Height, Sats, StoredF32, StoredU16, StoredU32};
|
||||||
|
use vecdb::{AnyCollectableVec, AnyIterableVec, Database, Exit, StoredIndex, VecIterator, Version};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
PoolId, Pools, chain,
|
||||||
|
grouped::{
|
||||||
|
ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source,
|
||||||
|
VecBuilderOptions,
|
||||||
|
},
|
||||||
|
indexes::{self, Indexes},
|
||||||
|
price,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Allocative)]
|
||||||
|
pub struct Vecs {
|
||||||
|
id: PoolId,
|
||||||
|
|
||||||
|
indexes_to_blocks_mined: ComputedVecsFromHeight<StoredU32>,
|
||||||
|
indexes_to_1w_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
|
||||||
|
indexes_to_1m_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
|
||||||
|
indexes_to_1y_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
|
||||||
|
indexes_to_subsidy: ComputedValueVecsFromHeight,
|
||||||
|
indexes_to_fee: ComputedValueVecsFromHeight,
|
||||||
|
indexes_to_coinbase: ComputedValueVecsFromHeight,
|
||||||
|
indexes_to_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
|
indexes_to_1d_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
|
indexes_to_1w_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
|
indexes_to_1m_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
|
indexes_to_1y_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||||
|
indexes_to_days_since_block: ComputedVecsFromDateIndex<StoredU16>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vecs {
|
||||||
|
pub fn forced_import(
|
||||||
|
db: &Database,
|
||||||
|
id: PoolId,
|
||||||
|
pools: &Pools,
|
||||||
|
parent_version: Version,
|
||||||
|
indexes: &indexes::Vecs,
|
||||||
|
price: Option<&price::Vecs>,
|
||||||
|
) -> Result<Self> {
|
||||||
|
let pool = pools.get(id);
|
||||||
|
let name = pool.serialized_id();
|
||||||
|
let suffix = |s: &str| format!("{name}_{s}");
|
||||||
|
let compute_dollars = price.is_some();
|
||||||
|
let version = parent_version + Version::ZERO;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
id,
|
||||||
|
indexes_to_blocks_mined: ComputedVecsFromHeight::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("blocks_mined"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_sum().add_cumulative(),
|
||||||
|
)?,
|
||||||
|
indexes_to_1w_blocks_mined: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("1w_blocks_mined"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_1m_blocks_mined: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("1m_blocks_mined"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_1y_blocks_mined: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("1y_blocks_mined"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_subsidy: ComputedValueVecsFromHeight::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("subsidy"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
VecBuilderOptions::default().add_sum().add_cumulative(),
|
||||||
|
compute_dollars,
|
||||||
|
indexes,
|
||||||
|
)?,
|
||||||
|
indexes_to_fee: ComputedValueVecsFromHeight::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("fee"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
VecBuilderOptions::default().add_sum().add_cumulative(),
|
||||||
|
compute_dollars,
|
||||||
|
indexes,
|
||||||
|
)?,
|
||||||
|
indexes_to_coinbase: ComputedValueVecsFromHeight::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("coinbase"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
VecBuilderOptions::default().add_sum().add_cumulative(),
|
||||||
|
compute_dollars,
|
||||||
|
indexes,
|
||||||
|
)?,
|
||||||
|
indexes_to_dominance: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("dominance"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_1d_dominance: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("1d_dominance"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_1w_dominance: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("1w_dominance"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_1m_dominance: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("1m_dominance"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_1y_dominance: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("1y_dominance"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
indexes_to_days_since_block: ComputedVecsFromDateIndex::forced_import(
|
||||||
|
db,
|
||||||
|
&suffix("days_since_block"),
|
||||||
|
Source::Compute,
|
||||||
|
version + Version::ZERO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn compute(
|
||||||
|
&mut self,
|
||||||
|
indexer: &Indexer,
|
||||||
|
indexes: &indexes::Vecs,
|
||||||
|
starting_indexes: &Indexes,
|
||||||
|
height_to_pool: &impl AnyIterableVec<Height, PoolId>,
|
||||||
|
chain: &chain::Vecs,
|
||||||
|
price: Option<&price::Vecs>,
|
||||||
|
exit: &Exit,
|
||||||
|
) -> Result<()> {
|
||||||
|
self.indexes_to_blocks_mined.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, _, starting_indexes, exit| {
|
||||||
|
vec.compute_transform(
|
||||||
|
starting_indexes.height,
|
||||||
|
height_to_pool,
|
||||||
|
|(h, id, ..)| {
|
||||||
|
(
|
||||||
|
h,
|
||||||
|
if id == self.id {
|
||||||
|
StoredU32::ONE
|
||||||
|
} else {
|
||||||
|
StoredU32::ZERO
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_1w_blocks_mined.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_sum(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
|
||||||
|
7,
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_1m_blocks_mined.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_sum(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
|
||||||
|
30,
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_1y_blocks_mined.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_sum(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
|
||||||
|
365,
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let height_to_blocks_mined = self.indexes_to_blocks_mined.height.as_ref().unwrap();
|
||||||
|
|
||||||
|
self.indexes_to_subsidy.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
price,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, _, starting_indexes, exit| {
|
||||||
|
vec.compute_transform2(
|
||||||
|
starting_indexes.height,
|
||||||
|
height_to_blocks_mined,
|
||||||
|
chain.indexes_to_subsidy.sats.height.as_ref().unwrap(),
|
||||||
|
|(h, mined, sats, ..)| {
|
||||||
|
(
|
||||||
|
h,
|
||||||
|
if mined == StoredU32::ONE {
|
||||||
|
sats
|
||||||
|
} else {
|
||||||
|
Sats::ZERO
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_fee.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
price,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, _, starting_indexes, exit| {
|
||||||
|
vec.compute_transform2(
|
||||||
|
starting_indexes.height,
|
||||||
|
height_to_blocks_mined,
|
||||||
|
chain.indexes_to_fee.sats.height.unwrap_sum(),
|
||||||
|
|(h, mined, sats, ..)| {
|
||||||
|
(
|
||||||
|
h,
|
||||||
|
if mined == StoredU32::ONE {
|
||||||
|
sats
|
||||||
|
} else {
|
||||||
|
Sats::ZERO
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_coinbase.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
price,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, _, starting_indexes, exit| {
|
||||||
|
vec.compute_transform2(
|
||||||
|
starting_indexes.height,
|
||||||
|
height_to_blocks_mined,
|
||||||
|
chain.indexes_to_coinbase.sats.height.as_ref().unwrap(),
|
||||||
|
|(h, mined, sats, ..)| {
|
||||||
|
(
|
||||||
|
h,
|
||||||
|
if mined == StoredU32::ONE {
|
||||||
|
sats
|
||||||
|
} else {
|
||||||
|
Sats::ZERO
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_dominance.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, _, starting_indexes, exit| {
|
||||||
|
vec.compute_percentage(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_blocks_mined.dateindex.unwrap_cumulative(),
|
||||||
|
chain.indexes_to_block_count.dateindex.unwrap_cumulative(),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_1d_dominance.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, _, starting_indexes, exit| {
|
||||||
|
vec.compute_percentage(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
|
||||||
|
chain.indexes_to_block_count.dateindex.unwrap_sum(),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_1w_dominance.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, _, starting_indexes, exit| {
|
||||||
|
vec.compute_percentage(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_1w_blocks_mined.dateindex.as_ref().unwrap(),
|
||||||
|
chain.indexes_to_1w_block_count.dateindex.as_ref().unwrap(),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_1m_dominance.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, _, starting_indexes, exit| {
|
||||||
|
vec.compute_percentage(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_1m_blocks_mined.dateindex.as_ref().unwrap(),
|
||||||
|
chain.indexes_to_1m_block_count.dateindex.as_ref().unwrap(),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_1y_dominance.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|vec, _, _, starting_indexes, exit| {
|
||||||
|
vec.compute_percentage(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_1y_blocks_mined.dateindex.as_ref().unwrap(),
|
||||||
|
chain.indexes_to_1y_block_count.dateindex.as_ref().unwrap(),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.indexes_to_days_since_block.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
let mut prev = None;
|
||||||
|
v.compute_transform2(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
|
||||||
|
self.indexes_to_blocks_mined.dateindex.unwrap_cumulative(),
|
||||||
|
|(i, sum, cumulative, slf)| {
|
||||||
|
if prev.is_none() {
|
||||||
|
let i = i.unwrap_to_usize();
|
||||||
|
prev.replace(if i > 0 {
|
||||||
|
slf.into_iter().unwrap_get_inner_(i - 1)
|
||||||
|
} else {
|
||||||
|
StoredU16::ZERO
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let days = if !cumulative.is_zero() && sum.is_zero() {
|
||||||
|
prev.unwrap() + StoredU16::ONE
|
||||||
|
} else {
|
||||||
|
StoredU16::ZERO
|
||||||
|
};
|
||||||
|
prev.replace(days);
|
||||||
|
(i, days)
|
||||||
|
},
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||||
|
[
|
||||||
|
self.indexes_to_blocks_mined.vecs(),
|
||||||
|
self.indexes_to_1w_blocks_mined.vecs(),
|
||||||
|
self.indexes_to_1m_blocks_mined.vecs(),
|
||||||
|
self.indexes_to_1y_blocks_mined.vecs(),
|
||||||
|
self.indexes_to_subsidy.vecs(),
|
||||||
|
self.indexes_to_fee.vecs(),
|
||||||
|
self.indexes_to_coinbase.vecs(),
|
||||||
|
self.indexes_to_dominance.vecs(),
|
||||||
|
self.indexes_to_1d_dominance.vecs(),
|
||||||
|
self.indexes_to_1w_dominance.vecs(),
|
||||||
|
self.indexes_to_1m_dominance.vecs(),
|
||||||
|
self.indexes_to_1y_dominance.vecs(),
|
||||||
|
self.indexes_to_days_since_block.vecs(),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
+454
-384
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@ use vecdb::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
Indexes,
|
Indexes,
|
||||||
grouped::{ComputedVecsFromHeight, Source, VecBuilderOptions},
|
grouped::{ComputedVecsFromHeight, Source, VecBuilderOptions},
|
||||||
indexes, market, price,
|
indexes, price,
|
||||||
stateful::{
|
stateful::{
|
||||||
common,
|
common,
|
||||||
r#trait::{CohortVecs, DynCohortVecs},
|
r#trait::{CohortVecs, DynCohortVecs},
|
||||||
@@ -29,8 +29,8 @@ pub struct Vecs {
|
|||||||
|
|
||||||
pub inner: common::Vecs,
|
pub inner: common::Vecs,
|
||||||
|
|
||||||
pub height_to_address_count: EagerVec<Height, StoredU64>,
|
pub height_to_addr_count: EagerVec<Height, StoredU64>,
|
||||||
pub indexes_to_address_count: ComputedVecsFromHeight<StoredU64>,
|
pub indexes_to_addr_count: ComputedVecsFromHeight<StoredU64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vecs {
|
impl Vecs {
|
||||||
@@ -43,7 +43,7 @@ impl Vecs {
|
|||||||
indexes: &indexes::Vecs,
|
indexes: &indexes::Vecs,
|
||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
states_path: Option<&Path>,
|
states_path: Option<&Path>,
|
||||||
compute_relative_to_all: bool,
|
compute_rel_to_all: bool,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let compute_dollars = price.is_some();
|
let compute_dollars = price.is_some();
|
||||||
|
|
||||||
@@ -58,15 +58,15 @@ impl Vecs {
|
|||||||
compute_dollars,
|
compute_dollars,
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
height_to_address_count: EagerVec::forced_import(
|
height_to_addr_count: EagerVec::forced_import(
|
||||||
db,
|
db,
|
||||||
&suffix("address_count"),
|
&suffix("addr_count"),
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
format,
|
format,
|
||||||
)?,
|
)?,
|
||||||
indexes_to_address_count: ComputedVecsFromHeight::forced_import(
|
indexes_to_addr_count: ComputedVecsFromHeight::forced_import(
|
||||||
db,
|
db,
|
||||||
&suffix("address_count"),
|
&suffix("addr_count"),
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -79,8 +79,8 @@ impl Vecs {
|
|||||||
version,
|
version,
|
||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
compute_relative_to_all,
|
|
||||||
false,
|
false,
|
||||||
|
compute_rel_to_all,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
})
|
})
|
||||||
@@ -90,7 +90,7 @@ impl Vecs {
|
|||||||
impl DynCohortVecs for Vecs {
|
impl DynCohortVecs for Vecs {
|
||||||
fn min_height_vecs_len(&self) -> usize {
|
fn min_height_vecs_len(&self) -> usize {
|
||||||
[
|
[
|
||||||
self.height_to_address_count.len(),
|
self.height_to_addr_count.len(),
|
||||||
self.inner.min_height_vecs_len(),
|
self.inner.min_height_vecs_len(),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -110,8 +110,8 @@ impl DynCohortVecs for Vecs {
|
|||||||
self.starting_height = Some(starting_height);
|
self.starting_height = Some(starting_height);
|
||||||
|
|
||||||
if let Some(prev_height) = starting_height.decremented() {
|
if let Some(prev_height) = starting_height.decremented() {
|
||||||
self.state.as_mut().unwrap().address_count = *self
|
self.state.as_mut().unwrap().addr_count = *self
|
||||||
.height_to_address_count
|
.height_to_addr_count
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.unwrap_get_inner(prev_height);
|
.unwrap_get_inner(prev_height);
|
||||||
}
|
}
|
||||||
@@ -120,9 +120,9 @@ impl DynCohortVecs for Vecs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn validate_computed_versions(&mut self, base_version: Version) -> Result<()> {
|
fn validate_computed_versions(&mut self, base_version: Version) -> Result<()> {
|
||||||
self.height_to_address_count
|
self.height_to_addr_count
|
||||||
.validate_computed_version_or_reset(
|
.validate_computed_version_or_reset(
|
||||||
base_version + self.height_to_address_count.inner_version(),
|
base_version + self.height_to_addr_count.inner_version(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.inner.validate_computed_versions(base_version)
|
self.inner.validate_computed_versions(base_version)
|
||||||
@@ -133,9 +133,9 @@ impl DynCohortVecs for Vecs {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.height_to_address_count.forced_push_at(
|
self.height_to_addr_count.forced_push_at(
|
||||||
height,
|
height,
|
||||||
self.state.as_ref().unwrap().address_count.into(),
|
self.state.as_ref().unwrap().addr_count.into(),
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ impl DynCohortVecs for Vecs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn safe_flush_stateful_vecs(&mut self, height: Height, exit: &Exit) -> Result<()> {
|
fn safe_flush_stateful_vecs(&mut self, height: Height, exit: &Exit) -> Result<()> {
|
||||||
self.height_to_address_count.safe_flush(exit)?;
|
self.height_to_addr_count.safe_flush(exit)?;
|
||||||
|
|
||||||
self.inner
|
self.inner
|
||||||
.safe_flush_stateful_vecs(height, exit, &mut self.state.as_mut().unwrap().inner)
|
.safe_flush_stateful_vecs(height, exit, &mut self.state.as_mut().unwrap().inner)
|
||||||
@@ -177,11 +177,11 @@ impl DynCohortVecs for Vecs {
|
|||||||
starting_indexes: &Indexes,
|
starting_indexes: &Indexes,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.indexes_to_address_count.compute_rest(
|
self.indexes_to_addr_count.compute_rest(
|
||||||
indexes,
|
indexes,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
Some(&self.height_to_address_count),
|
Some(&self.height_to_addr_count),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.inner
|
self.inner
|
||||||
@@ -191,8 +191,8 @@ impl DynCohortVecs for Vecs {
|
|||||||
fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||||
[
|
[
|
||||||
self.inner.vecs(),
|
self.inner.vecs(),
|
||||||
self.indexes_to_address_count.vecs(),
|
self.indexes_to_addr_count.vecs(),
|
||||||
vec![&self.height_to_address_count],
|
vec![&self.height_to_addr_count],
|
||||||
]
|
]
|
||||||
.concat()
|
.concat()
|
||||||
}
|
}
|
||||||
@@ -205,11 +205,11 @@ impl CohortVecs for Vecs {
|
|||||||
others: &[&Self],
|
others: &[&Self],
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.height_to_address_count.compute_sum_of_others(
|
self.height_to_addr_count.compute_sum_of_others(
|
||||||
starting_indexes.height,
|
starting_indexes.height,
|
||||||
others
|
others
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| &v.height_to_address_count)
|
.map(|v| &v.height_to_addr_count)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.as_slice(),
|
.as_slice(),
|
||||||
exit,
|
exit,
|
||||||
@@ -228,9 +228,10 @@ impl CohortVecs for Vecs {
|
|||||||
indexes: &indexes::Vecs,
|
indexes: &indexes::Vecs,
|
||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
starting_indexes: &Indexes,
|
starting_indexes: &Indexes,
|
||||||
market: &market::Vecs,
|
|
||||||
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
||||||
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
||||||
|
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||||
|
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||||
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
@@ -240,9 +241,10 @@ impl CohortVecs for Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
market,
|
|
||||||
height_to_supply,
|
height_to_supply,
|
||||||
dateindex_to_supply,
|
dateindex_to_supply,
|
||||||
|
height_to_market_cap,
|
||||||
|
dateindex_to_market_cap,
|
||||||
height_to_realized_cap,
|
height_to_realized_cap,
|
||||||
dateindex_to_realized_cap,
|
dateindex_to_realized_cap,
|
||||||
exit,
|
exit,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use derive_deref::{Deref, DerefMut};
|
|||||||
use vecdb::{AnyIterableVec, Database, Exit, Format};
|
use vecdb::{AnyIterableVec, Database, Exit, Format};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Indexes, indexes, market, price,
|
Indexes, indexes, price,
|
||||||
stateful::{
|
stateful::{
|
||||||
address_cohort,
|
address_cohort,
|
||||||
r#trait::{CohortVecs, DynCohortVecs},
|
r#trait::{CohortVecs, DynCohortVecs},
|
||||||
@@ -520,9 +520,10 @@ impl Vecs {
|
|||||||
indexes: &indexes::Vecs,
|
indexes: &indexes::Vecs,
|
||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
starting_indexes: &Indexes,
|
starting_indexes: &Indexes,
|
||||||
market: &market::Vecs,
|
|
||||||
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
||||||
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
||||||
|
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||||
|
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||||
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
@@ -534,9 +535,10 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
market,
|
|
||||||
height_to_supply,
|
height_to_supply,
|
||||||
dateindex_to_supply,
|
dateindex_to_supply,
|
||||||
|
height_to_market_cap,
|
||||||
|
dateindex_to_market_cap,
|
||||||
height_to_realized_cap,
|
height_to_realized_cap,
|
||||||
dateindex_to_realized_cap,
|
dateindex_to_realized_cap,
|
||||||
exit,
|
exit,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -18,15 +18,18 @@ use brk_structs::{
|
|||||||
use log::info;
|
use log::info;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use vecdb::{
|
use vecdb::{
|
||||||
AnyCollectableVec, AnyStoredVec, AnyVec, CollectableVec, Database, EagerVec, Exit, Format,
|
AnyCloneableIterableVec, AnyCollectableVec, AnyStoredVec, AnyVec, CollectableVec, Database,
|
||||||
GenericStoredVec, ImportOptions, PAGE_SIZE, RawVec, Reader, Stamp, StoredIndex, VecIterator,
|
EagerVec, Exit, Format, GenericStoredVec, ImportOptions, LazyVecFrom1, PAGE_SIZE, RawVec,
|
||||||
|
Reader, Stamp, StoredIndex, VecIterator,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BlockState, Indexes, SupplyState, Transacted,
|
BlockState, Indexes, SupplyState, Transacted, chain,
|
||||||
grouped::{ComputedValueVecsFromHeight, VecBuilderOptions},
|
grouped::{
|
||||||
grouped::{ComputedVecsFromHeight, Source},
|
ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source,
|
||||||
indexes, market, price, transactions,
|
VecBuilderOptions,
|
||||||
|
},
|
||||||
|
indexes, price,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod address_cohort;
|
mod address_cohort;
|
||||||
@@ -70,18 +73,24 @@ pub struct Vecs {
|
|||||||
|
|
||||||
pub height_to_unspendable_supply: EagerVec<Height, Sats>,
|
pub height_to_unspendable_supply: EagerVec<Height, Sats>,
|
||||||
pub height_to_opreturn_supply: EagerVec<Height, Sats>,
|
pub height_to_opreturn_supply: EagerVec<Height, Sats>,
|
||||||
pub addresstype_to_height_to_address_count: AddressTypeToHeightToAddressCount,
|
pub addresstype_to_height_to_addr_count: AddressTypeToHeightToAddressCount,
|
||||||
pub addresstype_to_height_to_empty_address_count: AddressTypeToHeightToAddressCount,
|
pub addresstype_to_height_to_empty_addr_count: AddressTypeToHeightToAddressCount,
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
// Computed
|
// Computed
|
||||||
// ---
|
// ---
|
||||||
pub addresstype_to_indexes_to_address_count: AddressTypeToIndexesToAddressCount,
|
pub addresstype_to_indexes_to_addr_count: AddressTypeToIndexesToAddressCount,
|
||||||
pub addresstype_to_indexes_to_empty_address_count: AddressTypeToIndexesToAddressCount,
|
pub addresstype_to_indexes_to_empty_addr_count: AddressTypeToIndexesToAddressCount,
|
||||||
pub indexes_to_unspendable_supply: ComputedValueVecsFromHeight,
|
pub indexes_to_unspendable_supply: ComputedValueVecsFromHeight,
|
||||||
pub indexes_to_opreturn_supply: ComputedValueVecsFromHeight,
|
pub indexes_to_opreturn_supply: ComputedValueVecsFromHeight,
|
||||||
pub indexes_to_address_count: ComputedVecsFromHeight<StoredU64>,
|
pub indexes_to_addr_count: ComputedVecsFromHeight<StoredU64>,
|
||||||
pub indexes_to_empty_address_count: ComputedVecsFromHeight<StoredU64>,
|
pub indexes_to_empty_addr_count: ComputedVecsFromHeight<StoredU64>,
|
||||||
|
pub height_to_market_cap: Option<LazyVecFrom1<Height, Dollars, Height, Dollars>>,
|
||||||
|
pub indexes_to_market_cap: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||||
|
pub loadedaddressindex_to_loadedaddressindex:
|
||||||
|
LazyVecFrom1<LoadedAddressIndex, LoadedAddressIndex, LoadedAddressIndex, LoadedAddressData>,
|
||||||
|
pub emptyaddressindex_to_emptyaddressindex:
|
||||||
|
LazyVecFrom1<EmptyAddressIndex, EmptyAddressIndex, EmptyAddressIndex, EmptyAddressData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const SAVED_STAMPED_CHANGES: u16 = 10;
|
const SAVED_STAMPED_CHANGES: u16 = 10;
|
||||||
@@ -103,7 +112,31 @@ impl Vecs {
|
|||||||
|
|
||||||
let compute_dollars = price.is_some();
|
let compute_dollars = price.is_some();
|
||||||
|
|
||||||
Ok(Self {
|
let utxo_cohorts =
|
||||||
|
utxo_cohorts::Vecs::forced_import(&db, version, format, indexes, price, &states_path)?;
|
||||||
|
|
||||||
|
let loadedaddressindex_to_loadedaddressdata = RawVec::forced_import_with(
|
||||||
|
ImportOptions::new(&db, "loadedaddressdata", version + VERSION + Version::ZERO)
|
||||||
|
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
|
||||||
|
)?;
|
||||||
|
let emptyaddressindex_to_emptyaddressdata = RawVec::forced_import_with(
|
||||||
|
ImportOptions::new(&db, "emptyaddressdata", version + VERSION + Version::ZERO)
|
||||||
|
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
|
||||||
|
)?;
|
||||||
|
let loadedaddressindex_to_loadedaddressindex = LazyVecFrom1::init(
|
||||||
|
"loadedaddressindex",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
loadedaddressindex_to_loadedaddressdata.boxed_clone(),
|
||||||
|
|index, _| Some(index),
|
||||||
|
);
|
||||||
|
let emptyaddressindex_to_emptyaddressindex = LazyVecFrom1::init(
|
||||||
|
"emptyaddressindex",
|
||||||
|
version + VERSION + Version::ZERO,
|
||||||
|
emptyaddressindex_to_emptyaddressdata.boxed_clone(),
|
||||||
|
|index, _| Some(index),
|
||||||
|
);
|
||||||
|
|
||||||
|
let this = Self {
|
||||||
chain_state: RawVec::forced_import_with(
|
chain_state: RawVec::forced_import_with(
|
||||||
ImportOptions::new(&db, "chain", version + VERSION + Version::ZERO)
|
ImportOptions::new(&db, "chain", version + VERSION + Version::ZERO)
|
||||||
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
|
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
|
||||||
@@ -137,115 +170,146 @@ impl Vecs {
|
|||||||
compute_dollars,
|
compute_dollars,
|
||||||
indexes,
|
indexes,
|
||||||
)?,
|
)?,
|
||||||
indexes_to_address_count: ComputedVecsFromHeight::forced_import(
|
indexes_to_addr_count: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"address_count",
|
"addr_count",
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
VecBuilderOptions::default().add_last(),
|
VecBuilderOptions::default().add_last(),
|
||||||
)?,
|
)?,
|
||||||
indexes_to_empty_address_count: ComputedVecsFromHeight::forced_import(
|
indexes_to_empty_addr_count: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"empty_address_count",
|
"empty_addr_count",
|
||||||
Source::Compute,
|
Source::Compute,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
VecBuilderOptions::default().add_last(),
|
VecBuilderOptions::default().add_last(),
|
||||||
)?,
|
)?,
|
||||||
addresstype_to_height_to_address_count: AddressTypeToHeightToAddressCount::from(
|
height_to_market_cap: compute_dollars.then(|| {
|
||||||
|
LazyVecFrom1::init(
|
||||||
|
"market_cap",
|
||||||
|
version + VERSION + Version::ONE,
|
||||||
|
utxo_cohorts
|
||||||
|
.all
|
||||||
|
.1
|
||||||
|
.height_to_supply_value
|
||||||
|
.dollars
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.boxed_clone(),
|
||||||
|
|height: Height, iter| {
|
||||||
|
iter.next_at(height.unwrap_to_usize()).map(|(_, value)| {
|
||||||
|
let d: Dollars = value.into_owned();
|
||||||
|
d
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
indexes_to_market_cap: compute_dollars.then(|| {
|
||||||
|
ComputedVecsFromDateIndex::forced_import(
|
||||||
|
&db,
|
||||||
|
"market_cap",
|
||||||
|
Source::Compute,
|
||||||
|
version + VERSION + Version::TWO,
|
||||||
|
indexes,
|
||||||
|
VecBuilderOptions::default().add_last(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}),
|
||||||
|
addresstype_to_height_to_addr_count: AddressTypeToHeightToAddressCount::from(
|
||||||
ByAddressType {
|
ByAddressType {
|
||||||
p2pk65: EagerVec::forced_import_compressed(
|
p2pk65: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2pk65_address_count",
|
"p2pk65_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2pk33: EagerVec::forced_import_compressed(
|
p2pk33: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2pk33_address_count",
|
"p2pk33_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2pkh: EagerVec::forced_import_compressed(
|
p2pkh: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2pkh_address_count",
|
"p2pkh_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2sh: EagerVec::forced_import_compressed(
|
p2sh: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2sh_address_count",
|
"p2sh_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2wpkh: EagerVec::forced_import_compressed(
|
p2wpkh: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2wpkh_address_count",
|
"p2wpkh_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2wsh: EagerVec::forced_import_compressed(
|
p2wsh: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2wsh_address_count",
|
"p2wsh_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2tr: EagerVec::forced_import_compressed(
|
p2tr: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2tr_address_count",
|
"p2tr_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2a: EagerVec::forced_import_compressed(
|
p2a: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2a_address_count",
|
"p2a_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
addresstype_to_height_to_empty_address_count: AddressTypeToHeightToAddressCount::from(
|
addresstype_to_height_to_empty_addr_count: AddressTypeToHeightToAddressCount::from(
|
||||||
ByAddressType {
|
ByAddressType {
|
||||||
p2pk65: EagerVec::forced_import_compressed(
|
p2pk65: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2pk65_empty_address_count",
|
"p2pk65_empty_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2pk33: EagerVec::forced_import_compressed(
|
p2pk33: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2pk33_empty_address_count",
|
"p2pk33_empty_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2pkh: EagerVec::forced_import_compressed(
|
p2pkh: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2pkh_empty_address_count",
|
"p2pkh_empty_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2sh: EagerVec::forced_import_compressed(
|
p2sh: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2sh_empty_address_count",
|
"p2sh_empty_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2wpkh: EagerVec::forced_import_compressed(
|
p2wpkh: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2wpkh_empty_address_count",
|
"p2wpkh_empty_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2wsh: EagerVec::forced_import_compressed(
|
p2wsh: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2wsh_empty_address_count",
|
"p2wsh_empty_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2tr: EagerVec::forced_import_compressed(
|
p2tr: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2tr_empty_address_count",
|
"p2tr_empty_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
p2a: EagerVec::forced_import_compressed(
|
p2a: EagerVec::forced_import_compressed(
|
||||||
&db,
|
&db,
|
||||||
"p2a_empty_address_count",
|
"p2a_empty_addr_count",
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
addresstype_to_indexes_to_address_count: AddressTypeToIndexesToAddressCount::from(
|
addresstype_to_indexes_to_addr_count: AddressTypeToIndexesToAddressCount::from(
|
||||||
ByAddressType {
|
ByAddressType {
|
||||||
p2pk65: ComputedVecsFromHeight::forced_import(
|
p2pk65: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2pk65_address_count",
|
"p2pk65_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -253,7 +317,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2pk33: ComputedVecsFromHeight::forced_import(
|
p2pk33: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2pk33_address_count",
|
"p2pk33_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -261,7 +325,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2pkh: ComputedVecsFromHeight::forced_import(
|
p2pkh: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2pkh_address_count",
|
"p2pkh_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -269,7 +333,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2sh: ComputedVecsFromHeight::forced_import(
|
p2sh: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2sh_address_count",
|
"p2sh_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -277,7 +341,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2wpkh: ComputedVecsFromHeight::forced_import(
|
p2wpkh: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2wpkh_address_count",
|
"p2wpkh_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -285,7 +349,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2wsh: ComputedVecsFromHeight::forced_import(
|
p2wsh: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2wsh_address_count",
|
"p2wsh_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -293,7 +357,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2tr: ComputedVecsFromHeight::forced_import(
|
p2tr: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2tr_address_count",
|
"p2tr_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -301,7 +365,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2a: ComputedVecsFromHeight::forced_import(
|
p2a: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2a_address_count",
|
"p2a_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -309,11 +373,11 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
addresstype_to_indexes_to_empty_address_count: AddressTypeToIndexesToAddressCount::from(
|
addresstype_to_indexes_to_empty_addr_count: AddressTypeToIndexesToAddressCount::from(
|
||||||
ByAddressType {
|
ByAddressType {
|
||||||
p2pk65: ComputedVecsFromHeight::forced_import(
|
p2pk65: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2pk65_empty_address_count",
|
"p2pk65_empty_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -321,7 +385,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2pk33: ComputedVecsFromHeight::forced_import(
|
p2pk33: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2pk33_empty_address_count",
|
"p2pk33_empty_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -329,7 +393,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2pkh: ComputedVecsFromHeight::forced_import(
|
p2pkh: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2pkh_empty_address_count",
|
"p2pkh_empty_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -337,7 +401,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2sh: ComputedVecsFromHeight::forced_import(
|
p2sh: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2sh_empty_address_count",
|
"p2sh_empty_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -345,7 +409,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2wpkh: ComputedVecsFromHeight::forced_import(
|
p2wpkh: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2wpkh_empty_address_count",
|
"p2wpkh_empty_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -353,7 +417,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2wsh: ComputedVecsFromHeight::forced_import(
|
p2wsh: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2wsh_empty_address_count",
|
"p2wsh_empty_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -361,7 +425,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2tr: ComputedVecsFromHeight::forced_import(
|
p2tr: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2tr_empty_address_count",
|
"p2tr_empty_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -369,7 +433,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
p2a: ComputedVecsFromHeight::forced_import(
|
p2a: ComputedVecsFromHeight::forced_import(
|
||||||
&db,
|
&db,
|
||||||
"p2a_empty_address_count",
|
"p2a_empty_addr_count",
|
||||||
Source::None,
|
Source::None,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -377,14 +441,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
utxo_cohorts: utxo_cohorts::Vecs::forced_import(
|
utxo_cohorts,
|
||||||
&db,
|
|
||||||
version,
|
|
||||||
format,
|
|
||||||
indexes,
|
|
||||||
price,
|
|
||||||
&states_path,
|
|
||||||
)?,
|
|
||||||
address_cohorts: address_cohorts::Vecs::forced_import(
|
address_cohorts: address_cohorts::Vecs::forced_import(
|
||||||
&db,
|
&db,
|
||||||
version,
|
version,
|
||||||
@@ -427,17 +484,22 @@ impl Vecs {
|
|||||||
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
|
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
|
||||||
)?,
|
)?,
|
||||||
|
|
||||||
loadedaddressindex_to_loadedaddressdata: RawVec::forced_import_with(
|
loadedaddressindex_to_loadedaddressdata,
|
||||||
ImportOptions::new(&db, "loadedaddressdata", version + VERSION + Version::ZERO)
|
emptyaddressindex_to_emptyaddressdata,
|
||||||
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
|
loadedaddressindex_to_loadedaddressindex,
|
||||||
)?,
|
emptyaddressindex_to_emptyaddressindex,
|
||||||
emptyaddressindex_to_emptyaddressdata: RawVec::forced_import_with(
|
|
||||||
ImportOptions::new(&db, "emptyaddressdata", version + VERSION + Version::ZERO)
|
|
||||||
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
|
|
||||||
)?,
|
|
||||||
|
|
||||||
db,
|
db,
|
||||||
})
|
};
|
||||||
|
|
||||||
|
this.db.retain_regions(
|
||||||
|
this.vecs()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|v| v.region_names())
|
||||||
|
.collect(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
@@ -445,22 +507,13 @@ impl Vecs {
|
|||||||
&mut self,
|
&mut self,
|
||||||
indexer: &Indexer,
|
indexer: &Indexer,
|
||||||
indexes: &indexes::Vecs,
|
indexes: &indexes::Vecs,
|
||||||
transactions: &transactions::Vecs,
|
chain: &chain::Vecs,
|
||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
market: &market::Vecs,
|
|
||||||
// Must take ownership as its indexes will be updated for this specific function
|
// Must take ownership as its indexes will be updated for this specific function
|
||||||
starting_indexes: &mut Indexes,
|
starting_indexes: &mut Indexes,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.compute_(
|
self.compute_(indexer, indexes, chain, price, starting_indexes, exit)?;
|
||||||
indexer,
|
|
||||||
indexes,
|
|
||||||
transactions,
|
|
||||||
price,
|
|
||||||
market,
|
|
||||||
starting_indexes,
|
|
||||||
exit,
|
|
||||||
)?;
|
|
||||||
self.db.flush_then_punch()?;
|
self.db.flush_then_punch()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -470,9 +523,8 @@ impl Vecs {
|
|||||||
&mut self,
|
&mut self,
|
||||||
indexer: &Indexer,
|
indexer: &Indexer,
|
||||||
indexes: &indexes::Vecs,
|
indexes: &indexes::Vecs,
|
||||||
transactions: &transactions::Vecs,
|
chain: &chain::Vecs,
|
||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
market: &market::Vecs,
|
|
||||||
// Must take ownership as its indexes will be updated for this specific function
|
// Must take ownership as its indexes will be updated for this specific function
|
||||||
starting_indexes: &mut Indexes,
|
starting_indexes: &mut Indexes,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
@@ -487,8 +539,8 @@ impl Vecs {
|
|||||||
let height_to_first_p2traddressindex = &indexer.vecs.height_to_first_p2traddressindex;
|
let height_to_first_p2traddressindex = &indexer.vecs.height_to_first_p2traddressindex;
|
||||||
let height_to_first_p2wpkhaddressindex = &indexer.vecs.height_to_first_p2wpkhaddressindex;
|
let height_to_first_p2wpkhaddressindex = &indexer.vecs.height_to_first_p2wpkhaddressindex;
|
||||||
let height_to_first_p2wshaddressindex = &indexer.vecs.height_to_first_p2wshaddressindex;
|
let height_to_first_p2wshaddressindex = &indexer.vecs.height_to_first_p2wshaddressindex;
|
||||||
let height_to_output_count = transactions.indexes_to_output_count.height.unwrap_sum();
|
let height_to_output_count = chain.indexes_to_output_count.height.unwrap_sum();
|
||||||
let height_to_input_count = transactions.indexes_to_input_count.height.unwrap_sum();
|
let height_to_input_count = chain.indexes_to_input_count.height.unwrap_sum();
|
||||||
let inputindex_to_outputindex = &indexer.vecs.inputindex_to_outputindex;
|
let inputindex_to_outputindex = &indexer.vecs.inputindex_to_outputindex;
|
||||||
let outputindex_to_value = &indexer.vecs.outputindex_to_value;
|
let outputindex_to_value = &indexer.vecs.outputindex_to_value;
|
||||||
let txindex_to_height = &indexes.txindex_to_height;
|
let txindex_to_height = &indexes.txindex_to_height;
|
||||||
@@ -496,23 +548,23 @@ impl Vecs {
|
|||||||
let outputindex_to_txindex = &indexes.outputindex_to_txindex;
|
let outputindex_to_txindex = &indexes.outputindex_to_txindex;
|
||||||
let outputindex_to_outputtype = &indexer.vecs.outputindex_to_outputtype;
|
let outputindex_to_outputtype = &indexer.vecs.outputindex_to_outputtype;
|
||||||
let outputindex_to_typeindex = &indexer.vecs.outputindex_to_typeindex;
|
let outputindex_to_typeindex = &indexer.vecs.outputindex_to_typeindex;
|
||||||
let height_to_unclaimed_rewards = transactions
|
let height_to_unclaimed_rewards = chain
|
||||||
.indexes_to_unclaimed_rewards
|
.indexes_to_unclaimed_rewards
|
||||||
.sats
|
.sats
|
||||||
.height
|
.height
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let height_to_close = price
|
let height_to_price_close = price
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|price| &price.chainindexes_to_close.height);
|
.map(|price| &price.chainindexes_to_price_close.height);
|
||||||
let dateindex_to_close = price
|
let dateindex_to_price_close = price
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|price| price.timeindexes_to_close.dateindex.as_ref().unwrap());
|
.map(|price| price.timeindexes_to_price_close.dateindex.as_ref().unwrap());
|
||||||
let height_to_date_fixed = &indexes.height_to_date_fixed;
|
let height_to_date_fixed = &indexes.height_to_date_fixed;
|
||||||
let dateindex_to_first_height = &indexes.dateindex_to_first_height;
|
let dateindex_to_first_height = &indexes.dateindex_to_first_height;
|
||||||
let dateindex_to_height_count = &indexes.dateindex_to_height_count;
|
let dateindex_to_height_count = &indexes.dateindex_to_height_count;
|
||||||
|
|
||||||
let mut height_to_close_iter = height_to_close.as_ref().map(|v| v.into_iter());
|
let mut height_to_price_close_iter = height_to_price_close.as_ref().map(|v| v.into_iter());
|
||||||
let mut height_to_timestamp_fixed_iter = height_to_timestamp_fixed.into_iter();
|
let mut height_to_timestamp_fixed_iter = height_to_timestamp_fixed.into_iter();
|
||||||
|
|
||||||
let base_version = Version::ZERO
|
let base_version = Version::ZERO
|
||||||
@@ -536,10 +588,10 @@ impl Vecs {
|
|||||||
+ outputindex_to_outputtype.version()
|
+ outputindex_to_outputtype.version()
|
||||||
+ outputindex_to_typeindex.version()
|
+ outputindex_to_typeindex.version()
|
||||||
+ height_to_unclaimed_rewards.version()
|
+ height_to_unclaimed_rewards.version()
|
||||||
+ height_to_close
|
+ height_to_price_close
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(Version::ZERO, |v| v.version())
|
.map_or(Version::ZERO, |v| v.version())
|
||||||
+ dateindex_to_close
|
+ dateindex_to_price_close
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(Version::ZERO, |v| v.version())
|
.map_or(Version::ZERO, |v| v.version())
|
||||||
+ height_to_date_fixed.version()
|
+ height_to_date_fixed.version()
|
||||||
@@ -635,12 +687,14 @@ impl Vecs {
|
|||||||
.rollback_before(starting_height.into())?,
|
.rollback_before(starting_height.into())?,
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
// .enumerate()
|
||||||
.map(|(i, s)| {
|
// .map(|(i, s)| {
|
||||||
let h = Height::from(s).incremented();
|
// let h = Height::from(s).incremented();
|
||||||
dbg!((i, s, h));
|
// // dbg!((i, s, h));
|
||||||
h
|
// h
|
||||||
})
|
// })
|
||||||
|
.map(Height::from)
|
||||||
|
.map(Height::incremented)
|
||||||
.collect::<BTreeSet<Height>>();
|
.collect::<BTreeSet<Height>>();
|
||||||
|
|
||||||
if set.len() == 1 {
|
if set.len() == 1 {
|
||||||
@@ -687,7 +741,7 @@ impl Vecs {
|
|||||||
.map(|(height, supply)| {
|
.map(|(height, supply)| {
|
||||||
let height = Height::from(height);
|
let height = Height::from(height);
|
||||||
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
|
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
|
||||||
let price = height_to_close_iter
|
let price = height_to_price_close_iter
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map(|i| *i.unwrap_get_inner(height));
|
.map(|i| *i.unwrap_get_inner(height));
|
||||||
BlockState {
|
BlockState {
|
||||||
@@ -758,13 +812,14 @@ impl Vecs {
|
|||||||
let mut height_to_output_count_iter = height_to_output_count.into_iter();
|
let mut height_to_output_count_iter = height_to_output_count.into_iter();
|
||||||
let mut height_to_input_count_iter = height_to_input_count.into_iter();
|
let mut height_to_input_count_iter = height_to_input_count.into_iter();
|
||||||
let mut height_to_unclaimed_rewards_iter = height_to_unclaimed_rewards.into_iter();
|
let mut height_to_unclaimed_rewards_iter = height_to_unclaimed_rewards.into_iter();
|
||||||
let mut dateindex_to_close_iter = dateindex_to_close.as_ref().map(|v| v.into_iter());
|
let mut dateindex_to_price_close_iter =
|
||||||
|
dateindex_to_price_close.as_ref().map(|v| v.into_iter());
|
||||||
let mut height_to_date_fixed_iter = height_to_date_fixed.into_iter();
|
let mut height_to_date_fixed_iter = height_to_date_fixed.into_iter();
|
||||||
let mut dateindex_to_first_height_iter = dateindex_to_first_height.into_iter();
|
let mut dateindex_to_first_height_iter = dateindex_to_first_height.into_iter();
|
||||||
let mut dateindex_to_height_count_iter = dateindex_to_height_count.into_iter();
|
let mut dateindex_to_height_count_iter = dateindex_to_height_count.into_iter();
|
||||||
|
|
||||||
let height_to_close_vec =
|
let height_to_price_close_vec = height_to_price_close
|
||||||
height_to_close.map(|height_to_close| height_to_close.collect().unwrap());
|
.map(|height_to_price_close| height_to_price_close.collect().unwrap());
|
||||||
|
|
||||||
let height_to_timestamp_fixed_vec = height_to_timestamp_fixed.collect().unwrap();
|
let height_to_timestamp_fixed_vec = height_to_timestamp_fixed.collect().unwrap();
|
||||||
let outputindex_range_to_height = RangeMap::from(height_to_first_outputindex);
|
let outputindex_range_to_height = RangeMap::from(height_to_first_outputindex);
|
||||||
@@ -783,12 +838,12 @@ impl Vecs {
|
|||||||
} else {
|
} else {
|
||||||
Sats::ZERO
|
Sats::ZERO
|
||||||
};
|
};
|
||||||
let mut addresstype_to_address_count = AddressTypeToAddressCount::from((
|
let mut addresstype_to_addr_count = AddressTypeToAddressCount::from((
|
||||||
&self.addresstype_to_height_to_address_count,
|
&self.addresstype_to_height_to_addr_count,
|
||||||
starting_height,
|
starting_height,
|
||||||
));
|
));
|
||||||
let mut addresstype_to_empty_address_count = AddressTypeToAddressCount::from((
|
let mut addresstype_to_empty_addr_count = AddressTypeToAddressCount::from((
|
||||||
&self.addresstype_to_height_to_empty_address_count,
|
&self.addresstype_to_height_to_empty_addr_count,
|
||||||
starting_height,
|
starting_height,
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -833,7 +888,7 @@ impl Vecs {
|
|||||||
.for_each(|(_, v)| v.state.as_mut().unwrap().reset_single_iteration_values());
|
.for_each(|(_, v)| v.state.as_mut().unwrap().reset_single_iteration_values());
|
||||||
|
|
||||||
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
|
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
|
||||||
let price = height_to_close_iter
|
let price = height_to_price_close_iter
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map(|i| *i.unwrap_get_inner(height));
|
.map(|i| *i.unwrap_get_inner(height));
|
||||||
let first_outputindex = height_to_first_outputindex_iter
|
let first_outputindex = height_to_first_outputindex_iter
|
||||||
@@ -1101,8 +1156,8 @@ impl Vecs {
|
|||||||
&mut addresstype_to_typeindex_to_loadedaddressdata,
|
&mut addresstype_to_typeindex_to_loadedaddressdata,
|
||||||
&mut addresstype_to_typeindex_to_emptyaddressdata,
|
&mut addresstype_to_typeindex_to_emptyaddressdata,
|
||||||
price,
|
price,
|
||||||
&mut addresstype_to_address_count,
|
&mut addresstype_to_addr_count,
|
||||||
&mut addresstype_to_empty_address_count,
|
&mut addresstype_to_empty_addr_count,
|
||||||
&mut stored_or_new_addresstype_to_typeindex_to_addressdatawithsource,
|
&mut stored_or_new_addresstype_to_typeindex_to_addressdatawithsource,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1112,9 +1167,9 @@ impl Vecs {
|
|||||||
&mut addresstype_to_typeindex_to_loadedaddressdata,
|
&mut addresstype_to_typeindex_to_loadedaddressdata,
|
||||||
&mut addresstype_to_typeindex_to_emptyaddressdata,
|
&mut addresstype_to_typeindex_to_emptyaddressdata,
|
||||||
price,
|
price,
|
||||||
&mut addresstype_to_address_count,
|
&mut addresstype_to_addr_count,
|
||||||
&mut addresstype_to_empty_address_count,
|
&mut addresstype_to_empty_addr_count,
|
||||||
height_to_close_vec.as_ref(),
|
height_to_price_close_vec.as_ref(),
|
||||||
&height_to_timestamp_fixed_vec,
|
&height_to_timestamp_fixed_vec,
|
||||||
height,
|
height,
|
||||||
timestamp,
|
timestamp,
|
||||||
@@ -1173,14 +1228,14 @@ impl Vecs {
|
|||||||
self.height_to_opreturn_supply
|
self.height_to_opreturn_supply
|
||||||
.forced_push_at(height, opreturn_supply, exit)?;
|
.forced_push_at(height, opreturn_supply, exit)?;
|
||||||
|
|
||||||
self.addresstype_to_height_to_address_count.forced_push_at(
|
self.addresstype_to_height_to_addr_count.forced_push_at(
|
||||||
height,
|
height,
|
||||||
&addresstype_to_address_count,
|
&addresstype_to_addr_count,
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.addresstype_to_height_to_empty_address_count
|
self.addresstype_to_height_to_empty_addr_count
|
||||||
.forced_push_at(height, &addresstype_to_empty_address_count, exit)?;
|
.forced_push_at(height, &addresstype_to_empty_addr_count, exit)?;
|
||||||
|
|
||||||
let date = height_to_date_fixed_iter.unwrap_get_inner(height);
|
let date = height_to_date_fixed_iter.unwrap_get_inner(height);
|
||||||
let dateindex = DateIndex::try_from(date).unwrap();
|
let dateindex = DateIndex::try_from(date).unwrap();
|
||||||
@@ -1191,7 +1246,7 @@ impl Vecs {
|
|||||||
let is_date_last_height = date_first_height
|
let is_date_last_height = date_first_height
|
||||||
+ Height::from(date_height_count).decremented().unwrap()
|
+ Height::from(date_height_count).decremented().unwrap()
|
||||||
== height;
|
== height;
|
||||||
let date_price = dateindex_to_close_iter
|
let date_price = dateindex_to_price_close_iter
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map(|v| is_date_last_height.then(|| *v.unwrap_get_inner(dateindex)));
|
.map(|v| is_date_last_height.then(|| *v.unwrap_get_inner(dateindex)));
|
||||||
|
|
||||||
@@ -1254,7 +1309,7 @@ impl Vecs {
|
|||||||
|
|
||||||
info!("Computing rest part 1...");
|
info!("Computing rest part 1...");
|
||||||
|
|
||||||
self.indexes_to_address_count.compute_all(
|
self.indexes_to_addr_count.compute_all(
|
||||||
indexer,
|
indexer,
|
||||||
indexes,
|
indexes,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
@@ -1263,7 +1318,7 @@ impl Vecs {
|
|||||||
v.compute_sum_of_others(
|
v.compute_sum_of_others(
|
||||||
starting_indexes.height,
|
starting_indexes.height,
|
||||||
&self
|
&self
|
||||||
.addresstype_to_height_to_address_count
|
.addresstype_to_height_to_addr_count
|
||||||
.as_typed_vec()
|
.as_typed_vec()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, v)| v)
|
.map(|(_, v)| v)
|
||||||
@@ -1274,7 +1329,7 @@ impl Vecs {
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.indexes_to_empty_address_count.compute_all(
|
self.indexes_to_empty_addr_count.compute_all(
|
||||||
indexer,
|
indexer,
|
||||||
indexes,
|
indexes,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
@@ -1283,7 +1338,7 @@ impl Vecs {
|
|||||||
v.compute_sum_of_others(
|
v.compute_sum_of_others(
|
||||||
starting_indexes.height,
|
starting_indexes.height,
|
||||||
&self
|
&self
|
||||||
.addresstype_to_height_to_empty_address_count
|
.addresstype_to_height_to_empty_addr_count
|
||||||
.as_typed_vec()
|
.as_typed_vec()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, v)| v)
|
.map(|(_, v)| v)
|
||||||
@@ -1311,18 +1366,18 @@ impl Vecs {
|
|||||||
Some(&self.height_to_opreturn_supply),
|
Some(&self.height_to_opreturn_supply),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.addresstype_to_indexes_to_address_count.compute(
|
self.addresstype_to_indexes_to_addr_count.compute(
|
||||||
indexes,
|
indexes,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
&self.addresstype_to_height_to_address_count,
|
&self.addresstype_to_height_to_addr_count,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.addresstype_to_indexes_to_empty_address_count.compute(
|
self.addresstype_to_indexes_to_empty_addr_count.compute(
|
||||||
indexes,
|
indexes,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
exit,
|
exit,
|
||||||
&self.addresstype_to_height_to_empty_address_count,
|
&self.addresstype_to_height_to_empty_addr_count,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.utxo_cohorts
|
self.utxo_cohorts
|
||||||
@@ -1331,6 +1386,33 @@ impl Vecs {
|
|||||||
self.address_cohorts
|
self.address_cohorts
|
||||||
.compute_rest_part1(indexer, indexes, price, starting_indexes, exit)?;
|
.compute_rest_part1(indexer, indexes, price, starting_indexes, exit)?;
|
||||||
|
|
||||||
|
if let Some(indexes_to_market_cap) = self.indexes_to_market_cap.as_mut() {
|
||||||
|
indexes_to_market_cap.compute_all(
|
||||||
|
indexer,
|
||||||
|
indexes,
|
||||||
|
starting_indexes,
|
||||||
|
exit,
|
||||||
|
|v, _, _, starting_indexes, exit| {
|
||||||
|
v.compute_transform(
|
||||||
|
starting_indexes.dateindex,
|
||||||
|
self.utxo_cohorts
|
||||||
|
.all
|
||||||
|
.1
|
||||||
|
.indexes_to_supply
|
||||||
|
.dollars
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.dateindex
|
||||||
|
.as_ref()
|
||||||
|
.unwrap(),
|
||||||
|
|(i, v, ..)| (i, v),
|
||||||
|
exit,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
info!("Computing rest part 2...");
|
info!("Computing rest part 2...");
|
||||||
|
|
||||||
let height_to_supply = &self
|
let height_to_supply = &self
|
||||||
@@ -1348,6 +1430,11 @@ impl Vecs {
|
|||||||
.bitcoin
|
.bitcoin
|
||||||
.dateindex
|
.dateindex
|
||||||
.clone();
|
.clone();
|
||||||
|
let height_to_market_cap = self.height_to_market_cap.clone();
|
||||||
|
let dateindex_to_market_cap = self
|
||||||
|
.indexes_to_market_cap
|
||||||
|
.as_ref()
|
||||||
|
.map(|v| v.dateindex.as_ref().unwrap().clone());
|
||||||
let height_to_realized_cap = self.utxo_cohorts.all.1.height_to_realized_cap.clone();
|
let height_to_realized_cap = self.utxo_cohorts.all.1.height_to_realized_cap.clone();
|
||||||
let dateindex_to_realized_cap = self
|
let dateindex_to_realized_cap = self
|
||||||
.utxo_cohorts
|
.utxo_cohorts
|
||||||
@@ -1357,6 +1444,8 @@ impl Vecs {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|v| v.dateindex.unwrap_last().clone());
|
.map(|v| v.dateindex.unwrap_last().clone());
|
||||||
let dateindex_to_supply_ref = dateindex_to_supply.as_ref().unwrap();
|
let dateindex_to_supply_ref = dateindex_to_supply.as_ref().unwrap();
|
||||||
|
let height_to_market_cap_ref = height_to_market_cap.as_ref();
|
||||||
|
let dateindex_to_market_cap_ref = dateindex_to_market_cap.as_ref();
|
||||||
let height_to_realized_cap_ref = height_to_realized_cap.as_ref();
|
let height_to_realized_cap_ref = height_to_realized_cap.as_ref();
|
||||||
let dateindex_to_realized_cap_ref = dateindex_to_realized_cap.as_ref();
|
let dateindex_to_realized_cap_ref = dateindex_to_realized_cap.as_ref();
|
||||||
|
|
||||||
@@ -1365,9 +1454,10 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
market,
|
|
||||||
height_to_supply,
|
height_to_supply,
|
||||||
dateindex_to_supply_ref,
|
dateindex_to_supply_ref,
|
||||||
|
height_to_market_cap_ref,
|
||||||
|
dateindex_to_market_cap_ref,
|
||||||
height_to_realized_cap_ref,
|
height_to_realized_cap_ref,
|
||||||
dateindex_to_realized_cap_ref,
|
dateindex_to_realized_cap_ref,
|
||||||
exit,
|
exit,
|
||||||
@@ -1378,9 +1468,10 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
market,
|
|
||||||
height_to_supply,
|
height_to_supply,
|
||||||
dateindex_to_supply_ref,
|
dateindex_to_supply_ref,
|
||||||
|
height_to_market_cap_ref,
|
||||||
|
dateindex_to_market_cap_ref,
|
||||||
height_to_realized_cap_ref,
|
height_to_realized_cap_ref,
|
||||||
dateindex_to_realized_cap_ref,
|
dateindex_to_realized_cap_ref,
|
||||||
exit,
|
exit,
|
||||||
@@ -1585,11 +1676,11 @@ impl Vecs {
|
|||||||
.try_for_each(|(_, v)| v.safe_flush_stateful_vecs(height, exit))?;
|
.try_for_each(|(_, v)| v.safe_flush_stateful_vecs(height, exit))?;
|
||||||
self.height_to_unspendable_supply.safe_flush(exit)?;
|
self.height_to_unspendable_supply.safe_flush(exit)?;
|
||||||
self.height_to_opreturn_supply.safe_flush(exit)?;
|
self.height_to_opreturn_supply.safe_flush(exit)?;
|
||||||
self.addresstype_to_height_to_address_count
|
self.addresstype_to_height_to_addr_count
|
||||||
.as_mut_vec()
|
.as_mut_vec()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.try_for_each(|v| v.safe_flush(exit))?;
|
.try_for_each(|v| v.safe_flush(exit))?;
|
||||||
self.addresstype_to_height_to_empty_address_count
|
self.addresstype_to_height_to_empty_addr_count
|
||||||
.as_mut_vec()
|
.as_mut_vec()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.try_for_each(|v| v.safe_flush(exit))?;
|
.try_for_each(|v| v.safe_flush(exit))?;
|
||||||
@@ -1787,23 +1878,42 @@ impl Vecs {
|
|||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
self.indexes_to_unspendable_supply.vecs(),
|
self.indexes_to_unspendable_supply.vecs(),
|
||||||
self.indexes_to_opreturn_supply.vecs(),
|
self.indexes_to_opreturn_supply.vecs(),
|
||||||
self.indexes_to_address_count.vecs(),
|
self.indexes_to_addr_count.vecs(),
|
||||||
self.indexes_to_empty_address_count.vecs(),
|
self.indexes_to_empty_addr_count.vecs(),
|
||||||
self.addresstype_to_indexes_to_address_count.vecs(),
|
self.addresstype_to_indexes_to_addr_count.vecs(),
|
||||||
self.addresstype_to_indexes_to_empty_address_count.vecs(),
|
self.indexes_to_market_cap
|
||||||
self.addresstype_to_height_to_address_count
|
.as_ref()
|
||||||
|
.map_or(vec![], |v| v.vecs()),
|
||||||
|
self.addresstype_to_indexes_to_empty_addr_count.vecs(),
|
||||||
|
self.addresstype_to_height_to_addr_count
|
||||||
.as_typed_vec()
|
.as_typed_vec()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, v)| v as &dyn AnyCollectableVec)
|
.map(|(_, v)| v as &dyn AnyCollectableVec)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
self.addresstype_to_height_to_empty_address_count
|
self.addresstype_to_height_to_empty_addr_count
|
||||||
.as_typed_vec()
|
.as_typed_vec()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, v)| v as &dyn AnyCollectableVec)
|
.map(|(_, v)| v as &dyn AnyCollectableVec)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
|
self.height_to_market_cap
|
||||||
|
.as_ref()
|
||||||
|
.map_or(vec![], |v| vec![v]),
|
||||||
vec![
|
vec![
|
||||||
&self.height_to_unspendable_supply,
|
&self.height_to_unspendable_supply,
|
||||||
&self.height_to_opreturn_supply,
|
&self.height_to_opreturn_supply,
|
||||||
|
&self.chain_state,
|
||||||
|
&self.p2pk33addressindex_to_anyaddressindex,
|
||||||
|
&self.p2pk65addressindex_to_anyaddressindex,
|
||||||
|
&self.p2pkhaddressindex_to_anyaddressindex,
|
||||||
|
&self.p2shaddressindex_to_anyaddressindex,
|
||||||
|
&self.p2traddressindex_to_anyaddressindex,
|
||||||
|
&self.p2wpkhaddressindex_to_anyaddressindex,
|
||||||
|
&self.p2wshaddressindex_to_anyaddressindex,
|
||||||
|
&self.p2aaddressindex_to_anyaddressindex,
|
||||||
|
&self.loadedaddressindex_to_loadedaddressdata,
|
||||||
|
&self.emptyaddressindex_to_emptyaddressdata,
|
||||||
|
&self.loadedaddressindex_to_loadedaddressindex,
|
||||||
|
&self.emptyaddressindex_to_emptyaddressindex,
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -1824,8 +1934,8 @@ impl AddressTypeToVec<(TypeIndex, Sats)> {
|
|||||||
WithAddressDataSource<EmptyAddressData>,
|
WithAddressDataSource<EmptyAddressData>,
|
||||||
>,
|
>,
|
||||||
price: Option<Dollars>,
|
price: Option<Dollars>,
|
||||||
addresstype_to_address_count: &mut ByAddressType<u64>,
|
addresstype_to_addr_count: &mut ByAddressType<u64>,
|
||||||
addresstype_to_empty_address_count: &mut ByAddressType<u64>,
|
addresstype_to_empty_addr_count: &mut ByAddressType<u64>,
|
||||||
stored_or_new_addresstype_to_typeindex_to_addressdatawithsource: &mut AddressTypeToTypeIndexTree<
|
stored_or_new_addresstype_to_typeindex_to_addressdatawithsource: &mut AddressTypeToTypeIndexTree<
|
||||||
WithAddressDataSource<LoadedAddressData>,
|
WithAddressDataSource<LoadedAddressData>,
|
||||||
>,
|
>,
|
||||||
@@ -1862,9 +1972,9 @@ impl AddressTypeToVec<(TypeIndex, Sats)> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if is_new || from_any_empty {
|
if is_new || from_any_empty {
|
||||||
(*addresstype_to_address_count.get_mut(_type).unwrap()) += 1;
|
(*addresstype_to_addr_count.get_mut(_type).unwrap()) += 1;
|
||||||
if from_any_empty {
|
if from_any_empty {
|
||||||
(*addresstype_to_empty_address_count.get_mut(_type).unwrap()) -= 1;
|
(*addresstype_to_empty_addr_count.get_mut(_type).unwrap()) -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1924,9 +2034,9 @@ impl HeightToAddressTypeToVec<(TypeIndex, Sats)> {
|
|||||||
WithAddressDataSource<EmptyAddressData>,
|
WithAddressDataSource<EmptyAddressData>,
|
||||||
>,
|
>,
|
||||||
price: Option<Dollars>,
|
price: Option<Dollars>,
|
||||||
addresstype_to_address_count: &mut ByAddressType<u64>,
|
addresstype_to_addr_count: &mut ByAddressType<u64>,
|
||||||
addresstype_to_empty_address_count: &mut ByAddressType<u64>,
|
addresstype_to_empty_addr_count: &mut ByAddressType<u64>,
|
||||||
height_to_close_vec: Option<&Vec<brk_structs::Close<Dollars>>>,
|
height_to_price_close_vec: Option<&Vec<brk_structs::Close<Dollars>>>,
|
||||||
height_to_timestamp_fixed_vec: &[Timestamp],
|
height_to_timestamp_fixed_vec: &[Timestamp],
|
||||||
height: Height,
|
height: Height,
|
||||||
timestamp: Timestamp,
|
timestamp: Timestamp,
|
||||||
@@ -1935,7 +2045,7 @@ impl HeightToAddressTypeToVec<(TypeIndex, Sats)> {
|
|||||||
>,
|
>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.0.into_iter().try_for_each(|(prev_height, mut v)| {
|
self.0.into_iter().try_for_each(|(prev_height, mut v)| {
|
||||||
let prev_price = height_to_close_vec
|
let prev_price = height_to_price_close_vec
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|v| **v.get(prev_height.unwrap_to_usize()).unwrap());
|
.map(|v| **v.get(prev_height.unwrap_to_usize()).unwrap());
|
||||||
|
|
||||||
@@ -1975,7 +2085,7 @@ impl HeightToAddressTypeToVec<(TypeIndex, Sats)> {
|
|||||||
|
|
||||||
let amount = prev_amount.checked_sub(value).unwrap();
|
let amount = prev_amount.checked_sub(value).unwrap();
|
||||||
|
|
||||||
let will_be_empty = addressdata.outputs_len - 1 == 0;
|
let will_be_empty = addressdata.utxos - 1 == 0;
|
||||||
|
|
||||||
if will_be_empty
|
if will_be_empty
|
||||||
|| vecs.amount_range.get_mut(amount).0.clone()
|
|| vecs.amount_range.get_mut(amount).0.clone()
|
||||||
@@ -1996,8 +2106,8 @@ impl HeightToAddressTypeToVec<(TypeIndex, Sats)> {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
(*addresstype_to_address_count.get_mut(_type).unwrap()) -= 1;
|
(*addresstype_to_addr_count.get_mut(_type).unwrap()) -= 1;
|
||||||
(*addresstype_to_empty_address_count.get_mut(_type).unwrap()) += 1;
|
(*addresstype_to_empty_addr_count.get_mut(_type).unwrap()) += 1;
|
||||||
|
|
||||||
let addressdata =
|
let addressdata =
|
||||||
typeindex_to_loadedaddressdata.remove(&type_index).unwrap();
|
typeindex_to_loadedaddressdata.remove(&type_index).unwrap();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use brk_indexer::Indexer;
|
|||||||
use brk_structs::{Bitcoin, DateIndex, Dollars, Height, Version};
|
use brk_structs::{Bitcoin, DateIndex, Dollars, Height, Version};
|
||||||
use vecdb::{AnyCollectableVec, AnyIterableVec, Exit};
|
use vecdb::{AnyCollectableVec, AnyIterableVec, Exit};
|
||||||
|
|
||||||
use crate::{Indexes, indexes, market, price};
|
use crate::{Indexes, indexes, price};
|
||||||
|
|
||||||
pub trait DynCohortVecs: Send + Sync {
|
pub trait DynCohortVecs: Send + Sync {
|
||||||
fn min_height_vecs_len(&self) -> usize;
|
fn min_height_vecs_len(&self) -> usize;
|
||||||
@@ -54,9 +54,10 @@ pub trait CohortVecs: DynCohortVecs {
|
|||||||
indexes: &indexes::Vecs,
|
indexes: &indexes::Vecs,
|
||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
starting_indexes: &Indexes,
|
starting_indexes: &Indexes,
|
||||||
market: &market::Vecs,
|
|
||||||
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
||||||
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
||||||
|
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||||
|
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||||
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use brk_structs::{Bitcoin, DateIndex, Dollars, Height, Version};
|
|||||||
use vecdb::{AnyCollectableVec, AnyIterableVec, Database, Exit, Format};
|
use vecdb::{AnyCollectableVec, AnyIterableVec, Database, Exit, Format};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Indexes, UTXOCohortState, indexes, market, price,
|
Indexes, UTXOCohortState, indexes, price,
|
||||||
stateful::{
|
stateful::{
|
||||||
common,
|
common,
|
||||||
r#trait::{CohortVecs, DynCohortVecs},
|
r#trait::{CohortVecs, DynCohortVecs},
|
||||||
@@ -32,8 +32,8 @@ impl Vecs {
|
|||||||
indexes: &indexes::Vecs,
|
indexes: &indexes::Vecs,
|
||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
states_path: Option<&Path>,
|
states_path: Option<&Path>,
|
||||||
compute_relative_to_all: bool,
|
extended: bool,
|
||||||
ratio_extended: bool,
|
compute_rel_to_all: bool,
|
||||||
compute_adjusted: bool,
|
compute_adjusted: bool,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let compute_dollars = price.is_some();
|
let compute_dollars = price.is_some();
|
||||||
@@ -56,8 +56,8 @@ impl Vecs {
|
|||||||
version,
|
version,
|
||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
compute_relative_to_all,
|
extended,
|
||||||
ratio_extended,
|
compute_rel_to_all,
|
||||||
compute_adjusted,
|
compute_adjusted,
|
||||||
)?,
|
)?,
|
||||||
})
|
})
|
||||||
@@ -158,9 +158,10 @@ impl CohortVecs for Vecs {
|
|||||||
indexes: &indexes::Vecs,
|
indexes: &indexes::Vecs,
|
||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
starting_indexes: &Indexes,
|
starting_indexes: &Indexes,
|
||||||
market: &market::Vecs,
|
|
||||||
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
||||||
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
||||||
|
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||||
|
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||||
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
@@ -170,9 +171,10 @@ impl CohortVecs for Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
market,
|
|
||||||
height_to_supply,
|
height_to_supply,
|
||||||
dateindex_to_supply,
|
dateindex_to_supply,
|
||||||
|
height_to_market_cap,
|
||||||
|
dateindex_to_market_cap,
|
||||||
height_to_realized_cap,
|
height_to_realized_cap,
|
||||||
dateindex_to_realized_cap,
|
dateindex_to_realized_cap,
|
||||||
exit,
|
exit,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use derive_deref::{Deref, DerefMut};
|
|||||||
use vecdb::{AnyIterableVec, Database, Exit, Format, StoredIndex};
|
use vecdb::{AnyIterableVec, Database, Exit, Format, StoredIndex};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Indexes, indexes, market, price,
|
Indexes, indexes, price,
|
||||||
stateful::r#trait::DynCohortVecs,
|
stateful::r#trait::DynCohortVecs,
|
||||||
states::{BlockState, Transacted},
|
states::{BlockState, Transacted},
|
||||||
};
|
};
|
||||||
@@ -38,18 +38,18 @@ impl Vecs {
|
|||||||
db,
|
db,
|
||||||
None,
|
None,
|
||||||
format,
|
format,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ONE,
|
||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
false,
|
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
true,
|
true,
|
||||||
)?,
|
)?,
|
||||||
term: ByTerm {
|
term: ByTerm {
|
||||||
short: utxo_cohort::Vecs::forced_import(
|
short: utxo_cohort::Vecs::forced_import(
|
||||||
db,
|
db,
|
||||||
Some("short_term_holders"),
|
Some("sth"),
|
||||||
format,
|
format,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -61,7 +61,7 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
long: utxo_cohort::Vecs::forced_import(
|
long: utxo_cohort::Vecs::forced_import(
|
||||||
db,
|
db,
|
||||||
Some("long_term_holders"),
|
Some("lth"),
|
||||||
format,
|
format,
|
||||||
version + VERSION + Version::ZERO,
|
version + VERSION + Version::ZERO,
|
||||||
indexes,
|
indexes,
|
||||||
@@ -143,8 +143,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
p2pk33: utxo_cohort::Vecs::forced_import(
|
p2pk33: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -155,8 +155,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
p2pkh: utxo_cohort::Vecs::forced_import(
|
p2pkh: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -167,8 +167,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
p2sh: utxo_cohort::Vecs::forced_import(
|
p2sh: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -179,8 +179,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
p2wpkh: utxo_cohort::Vecs::forced_import(
|
p2wpkh: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -191,8 +191,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
p2wsh: utxo_cohort::Vecs::forced_import(
|
p2wsh: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -203,8 +203,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
p2tr: utxo_cohort::Vecs::forced_import(
|
p2tr: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -215,8 +215,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
p2a: utxo_cohort::Vecs::forced_import(
|
p2a: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -227,8 +227,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
p2ms: utxo_cohort::Vecs::forced_import(
|
p2ms: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -239,8 +239,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
empty: utxo_cohort::Vecs::forced_import(
|
empty: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -251,8 +251,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
unknown: utxo_cohort::Vecs::forced_import(
|
unknown: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -263,8 +263,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
@@ -955,8 +955,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1sat_to_10sats: utxo_cohort::Vecs::forced_import(
|
_1sat_to_10sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -967,8 +967,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10sats_to_100sats: utxo_cohort::Vecs::forced_import(
|
_10sats_to_100sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -979,8 +979,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_100sats_to_1k_sats: utxo_cohort::Vecs::forced_import(
|
_100sats_to_1k_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -991,8 +991,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1k_sats_to_10k_sats: utxo_cohort::Vecs::forced_import(
|
_1k_sats_to_10k_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1003,8 +1003,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10k_sats_to_100k_sats: utxo_cohort::Vecs::forced_import(
|
_10k_sats_to_100k_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1015,8 +1015,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_100k_sats_to_1m_sats: utxo_cohort::Vecs::forced_import(
|
_100k_sats_to_1m_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1027,8 +1027,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1m_sats_to_10m_sats: utxo_cohort::Vecs::forced_import(
|
_1m_sats_to_10m_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1039,8 +1039,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10m_sats_to_1btc: utxo_cohort::Vecs::forced_import(
|
_10m_sats_to_1btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1051,8 +1051,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1btc_to_10btc: utxo_cohort::Vecs::forced_import(
|
_1btc_to_10btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1063,8 +1063,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10btc_to_100btc: utxo_cohort::Vecs::forced_import(
|
_10btc_to_100btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1075,8 +1075,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_100btc_to_1k_btc: utxo_cohort::Vecs::forced_import(
|
_100btc_to_1k_btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1087,8 +1087,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1k_btc_to_10k_btc: utxo_cohort::Vecs::forced_import(
|
_1k_btc_to_10k_btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1099,8 +1099,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10k_btc_to_100k_btc: utxo_cohort::Vecs::forced_import(
|
_10k_btc_to_100k_btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1111,8 +1111,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_100k_btc_or_more: utxo_cohort::Vecs::forced_import(
|
_100k_btc_or_more: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1123,8 +1123,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
Some(states_path),
|
Some(states_path),
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
@@ -1137,8 +1137,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_100sats: utxo_cohort::Vecs::forced_import(
|
_100sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1149,8 +1149,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1k_sats: utxo_cohort::Vecs::forced_import(
|
_1k_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1161,8 +1161,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10k_sats: utxo_cohort::Vecs::forced_import(
|
_10k_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1173,8 +1173,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_100k_sats: utxo_cohort::Vecs::forced_import(
|
_100k_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1185,8 +1185,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1m_sats: utxo_cohort::Vecs::forced_import(
|
_1m_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1197,8 +1197,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10m_sats: utxo_cohort::Vecs::forced_import(
|
_10m_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1209,8 +1209,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1btc: utxo_cohort::Vecs::forced_import(
|
_1btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1221,8 +1221,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10btc: utxo_cohort::Vecs::forced_import(
|
_10btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1233,8 +1233,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_100btc: utxo_cohort::Vecs::forced_import(
|
_100btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1245,8 +1245,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1k_btc: utxo_cohort::Vecs::forced_import(
|
_1k_btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1257,8 +1257,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10k_btc: utxo_cohort::Vecs::forced_import(
|
_10k_btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1269,8 +1269,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_100k_btc: utxo_cohort::Vecs::forced_import(
|
_100k_btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1281,8 +1281,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
@@ -1295,8 +1295,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10sats: utxo_cohort::Vecs::forced_import(
|
_10sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1307,8 +1307,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_100sats: utxo_cohort::Vecs::forced_import(
|
_100sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1319,8 +1319,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1k_sats: utxo_cohort::Vecs::forced_import(
|
_1k_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1331,8 +1331,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10k_sats: utxo_cohort::Vecs::forced_import(
|
_10k_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1343,8 +1343,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_100k_sats: utxo_cohort::Vecs::forced_import(
|
_100k_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1355,8 +1355,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1m_sats: utxo_cohort::Vecs::forced_import(
|
_1m_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1367,8 +1367,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10m_sats: utxo_cohort::Vecs::forced_import(
|
_10m_sats: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1379,8 +1379,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1btc: utxo_cohort::Vecs::forced_import(
|
_1btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1391,8 +1391,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10btc: utxo_cohort::Vecs::forced_import(
|
_10btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1403,8 +1403,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_100btc: utxo_cohort::Vecs::forced_import(
|
_100btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1415,8 +1415,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_1k_btc: utxo_cohort::Vecs::forced_import(
|
_1k_btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1427,8 +1427,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
_10k_btc: utxo_cohort::Vecs::forced_import(
|
_10k_btc: utxo_cohort::Vecs::forced_import(
|
||||||
@@ -1439,8 +1439,8 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
None,
|
None,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
@@ -1644,7 +1644,13 @@ impl Vecs {
|
|||||||
let by_size_range = self.0.amount_range.as_vec();
|
let by_size_range = self.0.amount_range.as_vec();
|
||||||
|
|
||||||
[
|
[
|
||||||
vec![(&mut self.0.all.1, self.0.epoch.vecs().to_vec())],
|
vec![(
|
||||||
|
&mut self.0.all.1,
|
||||||
|
by_date_range
|
||||||
|
.into_iter()
|
||||||
|
.map(|(_, v)| v)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)],
|
||||||
self.0
|
self.0
|
||||||
.min_age
|
.min_age
|
||||||
.as_mut_vec()
|
.as_mut_vec()
|
||||||
@@ -1748,9 +1754,10 @@ impl Vecs {
|
|||||||
indexes: &indexes::Vecs,
|
indexes: &indexes::Vecs,
|
||||||
price: Option<&price::Vecs>,
|
price: Option<&price::Vecs>,
|
||||||
starting_indexes: &Indexes,
|
starting_indexes: &Indexes,
|
||||||
market: &market::Vecs,
|
|
||||||
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
||||||
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
||||||
|
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||||
|
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||||
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
@@ -1762,9 +1769,10 @@ impl Vecs {
|
|||||||
indexes,
|
indexes,
|
||||||
price,
|
price,
|
||||||
starting_indexes,
|
starting_indexes,
|
||||||
market,
|
|
||||||
height_to_supply,
|
height_to_supply,
|
||||||
dateindex_to_supply,
|
dateindex_to_supply,
|
||||||
|
height_to_market_cap,
|
||||||
|
dateindex_to_market_cap,
|
||||||
height_to_realized_cap,
|
height_to_realized_cap,
|
||||||
dateindex_to_realized_cap,
|
dateindex_to_realized_cap,
|
||||||
exit,
|
exit,
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ use super::CohortState;
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AddressCohortState {
|
pub struct AddressCohortState {
|
||||||
pub address_count: u64,
|
pub addr_count: u64,
|
||||||
pub inner: CohortState,
|
pub inner: CohortState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddressCohortState {
|
impl AddressCohortState {
|
||||||
pub fn new(path: &Path, name: &str, compute_dollars: bool) -> Self {
|
pub fn new(path: &Path, name: &str, compute_dollars: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
address_count: 0,
|
addr_count: 0,
|
||||||
inner: CohortState::new(path, name, compute_dollars),
|
inner: CohortState::new(path, name, compute_dollars),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,14 +44,14 @@ impl AddressCohortState {
|
|||||||
|
|
||||||
let prev_realized_price = compute_price.then(|| addressdata.realized_price());
|
let prev_realized_price = compute_price.then(|| addressdata.realized_price());
|
||||||
let prev_supply_state = SupplyState {
|
let prev_supply_state = SupplyState {
|
||||||
utxos: addressdata.outputs_len as u64,
|
utxos: addressdata.utxos as u64,
|
||||||
value: addressdata.amount(),
|
value: addressdata.amount(),
|
||||||
};
|
};
|
||||||
|
|
||||||
addressdata.send(value, prev_price)?;
|
addressdata.send(value, prev_price)?;
|
||||||
|
|
||||||
let supply_state = SupplyState {
|
let supply_state = SupplyState {
|
||||||
utxos: addressdata.outputs_len as u64,
|
utxos: addressdata.utxos as u64,
|
||||||
value: addressdata.amount(),
|
value: addressdata.amount(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,14 +79,14 @@ impl AddressCohortState {
|
|||||||
|
|
||||||
let prev_realized_price = compute_price.then(|| address_data.realized_price());
|
let prev_realized_price = compute_price.then(|| address_data.realized_price());
|
||||||
let prev_supply_state = SupplyState {
|
let prev_supply_state = SupplyState {
|
||||||
utxos: address_data.outputs_len as u64,
|
utxos: address_data.utxos as u64,
|
||||||
value: address_data.amount(),
|
value: address_data.amount(),
|
||||||
};
|
};
|
||||||
|
|
||||||
address_data.receive(value, price);
|
address_data.receive(value, price);
|
||||||
|
|
||||||
let supply_state = SupplyState {
|
let supply_state = SupplyState {
|
||||||
utxos: address_data.outputs_len as u64,
|
utxos: address_data.utxos as u64,
|
||||||
value: address_data.amount(),
|
value: address_data.amount(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ impl AddressCohortState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(&mut self, addressdata: &LoadedAddressData) {
|
pub fn add(&mut self, addressdata: &LoadedAddressData) {
|
||||||
self.address_count += 1;
|
self.addr_count += 1;
|
||||||
self.inner.increment_(
|
self.inner.increment_(
|
||||||
&addressdata.into(),
|
&addressdata.into(),
|
||||||
addressdata.realized_cap,
|
addressdata.realized_cap,
|
||||||
@@ -108,7 +108,7 @@ impl AddressCohortState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn subtract(&mut self, addressdata: &LoadedAddressData) {
|
pub fn subtract(&mut self, addressdata: &LoadedAddressData) {
|
||||||
self.address_count = self.address_count.checked_sub(1).unwrap();
|
self.addr_count = self.addr_count.checked_sub(1).unwrap();
|
||||||
self.inner.decrement_(
|
self.inner.decrement_(
|
||||||
&addressdata.into(),
|
&addressdata.into(),
|
||||||
addressdata.realized_cap,
|
addressdata.realized_cap,
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ impl CohortState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
state.supply_even += sats;
|
state.supply_breakeven += sats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ impl SubAssign<&SupplyState> for SupplyState {
|
|||||||
impl From<&LoadedAddressData> for SupplyState {
|
impl From<&LoadedAddressData> for SupplyState {
|
||||||
fn from(value: &LoadedAddressData) -> Self {
|
fn from(value: &LoadedAddressData) -> Self {
|
||||||
Self {
|
Self {
|
||||||
utxos: value.outputs_len as u64,
|
utxos: value.utxos as u64,
|
||||||
value: value.amount(),
|
value: value.amount(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use brk_structs::{Dollars, Sats};
|
|||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct UnrealizedState {
|
pub struct UnrealizedState {
|
||||||
pub supply_in_profit: Sats,
|
pub supply_in_profit: Sats,
|
||||||
pub supply_even: Sats,
|
pub supply_breakeven: Sats,
|
||||||
pub supply_in_loss: Sats,
|
pub supply_in_loss: Sats,
|
||||||
pub unrealized_profit: Dollars,
|
pub unrealized_profit: Dollars,
|
||||||
pub unrealized_loss: Dollars,
|
pub unrealized_loss: Dollars,
|
||||||
@@ -12,7 +12,7 @@ pub struct UnrealizedState {
|
|||||||
impl UnrealizedState {
|
impl UnrealizedState {
|
||||||
pub const NAN: Self = Self {
|
pub const NAN: Self = Self {
|
||||||
supply_in_profit: Sats::ZERO,
|
supply_in_profit: Sats::ZERO,
|
||||||
supply_even: Sats::ZERO,
|
supply_breakeven: Sats::ZERO,
|
||||||
supply_in_loss: Sats::ZERO,
|
supply_in_loss: Sats::ZERO,
|
||||||
unrealized_profit: Dollars::NAN,
|
unrealized_profit: Dollars::NAN,
|
||||||
unrealized_loss: Dollars::NAN,
|
unrealized_loss: Dollars::NAN,
|
||||||
@@ -20,7 +20,7 @@ impl UnrealizedState {
|
|||||||
|
|
||||||
pub const ZERO: Self = Self {
|
pub const ZERO: Self = Self {
|
||||||
supply_in_profit: Sats::ZERO,
|
supply_in_profit: Sats::ZERO,
|
||||||
supply_even: Sats::ZERO,
|
supply_breakeven: Sats::ZERO,
|
||||||
supply_in_loss: Sats::ZERO,
|
supply_in_loss: Sats::ZERO,
|
||||||
unrealized_profit: Dollars::ZERO,
|
unrealized_profit: Dollars::ZERO,
|
||||||
unrealized_loss: Dollars::ZERO,
|
unrealized_loss: Dollars::ZERO,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ pub struct BRK {
|
|||||||
dateindex_to_ohlc: BTreeMap<DateIndex, Vec<OHLCCents>>,
|
dateindex_to_ohlc: BTreeMap<DateIndex, Vec<OHLCCents>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const API_URL: &str = "https://bitcoinresearchkit.org/api/vecs";
|
const API_URL: &str = "https://bitview.space/api/vecs";
|
||||||
const CHUNK_SIZE: usize = 10_000;
|
const CHUNK_SIZE: usize = 10_000;
|
||||||
|
|
||||||
impl BRK {
|
impl BRK {
|
||||||
@@ -46,7 +46,7 @@ impl BRK {
|
|||||||
|
|
||||||
default_retry(|_| {
|
default_retry(|_| {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{API_URL}/height-to-ohlc?from={}&to={}",
|
"{API_URL}/height-to-price-ohlc?from={}&to={}",
|
||||||
height,
|
height,
|
||||||
height + CHUNK_SIZE
|
height + CHUNK_SIZE
|
||||||
);
|
);
|
||||||
@@ -91,7 +91,7 @@ impl BRK {
|
|||||||
|
|
||||||
default_retry(|_| {
|
default_retry(|_| {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{API_URL}/dateindex-to-ohlc?from={}&to={}",
|
"{API_URL}/dateindex-to-price-ohlc?from={}&to={}",
|
||||||
dateindex,
|
dateindex,
|
||||||
dateindex + CHUNK_SIZE
|
dateindex + CHUNK_SIZE
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
**Key-Value Storage (lookups):**
|
**Key-Value Storage (lookups):**
|
||||||
- Block hash prefixes → heights
|
- Block hash prefixes → heights
|
||||||
- Transaction ID prefixes → transaction indices
|
- Transaction ID prefixes → transaction indices
|
||||||
- Address byte hashes → type indices
|
- Address byte hashes → type indices
|
||||||
- Fast point queries by hash or address
|
- Fast point queries by hash or address
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ let rpc = Box::leak(Box::new(Client::new(
|
|||||||
// Create parser for Bitcoin Core block files
|
// Create parser for Bitcoin Core block files
|
||||||
let parser = Parser::new(
|
let parser = Parser::new(
|
||||||
Path::new("~/.bitcoin/blocks").to_path_buf(),
|
Path::new("~/.bitcoin/blocks").to_path_buf(),
|
||||||
Path::new("./brk_data").to_path_buf(),
|
Some(Path::new("./brk_data").to_path_buf()),
|
||||||
rpc
|
rpc
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -85,19 +85,19 @@ use std::thread::sleep;
|
|||||||
// Continuous indexing loop for real-time updates
|
// Continuous indexing loop for real-time updates
|
||||||
loop {
|
loop {
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
|
|
||||||
// Index new blocks
|
// Index new blocks
|
||||||
let indexes = indexer.index(&parser, rpc, &exit, true)?;
|
let indexes = indexer.index(&parser, rpc, &exit, true)?;
|
||||||
|
|
||||||
println!("Indexed to height {} in {:?}",
|
println!("Indexed to height {} in {:?}",
|
||||||
indexes.height, start_time.elapsed());
|
indexes.height, start_time.elapsed());
|
||||||
|
|
||||||
// Check for exit signal
|
// Check for exit signal
|
||||||
if exit.is_signaled() {
|
if exit.is_signaled() {
|
||||||
println!("Graceful shutdown requested");
|
println!("Graceful shutdown requested");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait before next update cycle
|
// Wait before next update cycle
|
||||||
sleep(Duration::from_secs(5 * 60));
|
sleep(Duration::from_secs(5 * 60));
|
||||||
}
|
}
|
||||||
@@ -187,4 +187,4 @@ pub struct Indexes {
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*This README was generated by Claude Code*
|
*This README was generated by Claude Code*
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
let blocks_dir = bitcoin_dir.join("blocks");
|
let blocks_dir = bitcoin_dir.join("blocks");
|
||||||
|
|
||||||
let outputs_dir = Path::new("../../_outputs");
|
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
|
||||||
fs::create_dir_all(outputs_dir)?;
|
fs::create_dir_all(&outputs_dir)?;
|
||||||
// let outputs_dir = Path::new("/Volumes/WD_BLACK1/brk");
|
// let outputs_dir = Path::new("/Volumes/WD_BLACK1/brk");
|
||||||
|
|
||||||
let rpc = Box::leak(Box::new(bitcoincore_rpc::Client::new(
|
let rpc = Box::leak(Box::new(bitcoincore_rpc::Client::new(
|
||||||
@@ -33,11 +33,11 @@ fn main() -> Result<()> {
|
|||||||
let exit = Exit::new();
|
let exit = Exit::new();
|
||||||
exit.set_ctrlc_handler();
|
exit.set_ctrlc_handler();
|
||||||
|
|
||||||
let parser = Parser::new(blocks_dir, outputs_dir.to_path_buf(), rpc);
|
let parser = Parser::new(blocks_dir, Some(outputs_dir.to_path_buf()), rpc);
|
||||||
|
|
||||||
fs::create_dir_all(outputs_dir)?;
|
fs::create_dir_all(&outputs_dir)?;
|
||||||
|
|
||||||
let mut indexer = Indexer::forced_import(outputs_dir)?;
|
let mut indexer = Indexer::forced_import(&outputs_dir)?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let i = Instant::now();
|
let i = Instant::now();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::{collections::BTreeMap, path::Path, str::FromStr, thread, time::Instant
|
|||||||
use bitcoin::{Transaction, TxIn, TxOut};
|
use bitcoin::{Transaction, TxIn, TxOut};
|
||||||
use brk_error::{Error, Result};
|
use brk_error::{Error, Result};
|
||||||
|
|
||||||
use brk_parser::Parser;
|
use brk_parser::{BlockExtended, Parser};
|
||||||
use brk_store::AnyStore;
|
use brk_store::AnyStore;
|
||||||
use brk_structs::{
|
use brk_structs::{
|
||||||
AddressBytes, AddressBytesHash, BlockHash, BlockHashPrefix, Height, InputIndex, OutputIndex,
|
AddressBytes, AddressBytesHash, BlockHash, BlockHashPrefix, Height, InputIndex, OutputIndex,
|
||||||
@@ -14,7 +14,7 @@ use brk_structs::{
|
|||||||
};
|
};
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use vecdb::{AnyVec, Database, Exit, GenericStoredVec, PAGE_SIZE, Reader, VecIterator};
|
use vecdb::{AnyVec, Exit, GenericStoredVec, Reader, VecIterator};
|
||||||
mod indexes;
|
mod indexes;
|
||||||
mod stores;
|
mod stores;
|
||||||
mod vecs;
|
mod vecs;
|
||||||
@@ -23,33 +23,32 @@ pub use indexes::*;
|
|||||||
pub use stores::*;
|
pub use stores::*;
|
||||||
pub use vecs::*;
|
pub use vecs::*;
|
||||||
|
|
||||||
|
// One version for all data sources
|
||||||
|
// Increment on change OR addition
|
||||||
|
const VERSION: Version = Version::new(21);
|
||||||
|
|
||||||
const SNAPSHOT_BLOCK_RANGE: usize = 1_000;
|
const SNAPSHOT_BLOCK_RANGE: usize = 1_000;
|
||||||
const COLLISIONS_CHECKED_UP_TO: Height = Height::new(909_150);
|
const COLLISIONS_CHECKED_UP_TO: Height = Height::new(909_150);
|
||||||
const VERSION: Version = Version::ONE;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Indexer {
|
pub struct Indexer {
|
||||||
pub db: Database,
|
|
||||||
pub vecs: Vecs,
|
pub vecs: Vecs,
|
||||||
pub stores: Stores,
|
pub stores: Stores,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Indexer {
|
impl Indexer {
|
||||||
pub fn forced_import(outputs_dir: &Path) -> Result<Self> {
|
pub fn forced_import(outputs_dir: &Path) -> Result<Self> {
|
||||||
let db = Database::open(&outputs_dir.join("indexed/vecs"))?;
|
info!("Importing indexer...");
|
||||||
|
|
||||||
let vecs = Vecs::forced_import(&db, VERSION + Version::ZERO)?;
|
let path = outputs_dir.join("indexed");
|
||||||
|
|
||||||
db.set_min_len(PAGE_SIZE * 50_000_000)?;
|
let vecs = Vecs::forced_import(&path, VERSION)?;
|
||||||
|
info!("Imported vecs");
|
||||||
|
|
||||||
Ok(Self {
|
let stores = Stores::forced_import(&path, VERSION)?;
|
||||||
vecs,
|
info!("Imported stores");
|
||||||
stores: Stores::forced_import(
|
|
||||||
&outputs_dir.join("indexed/stores"),
|
Ok(Self { vecs, stores })
|
||||||
VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
db,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn index(
|
pub fn index(
|
||||||
@@ -59,16 +58,9 @@ impl Indexer {
|
|||||||
exit: &Exit,
|
exit: &Exit,
|
||||||
check_collisions: bool,
|
check_collisions: bool,
|
||||||
) -> Result<Indexes> {
|
) -> Result<Indexes> {
|
||||||
let db = self.db.clone();
|
|
||||||
|
|
||||||
// dbg!(self.db.regions().id_to_index());
|
|
||||||
// dbg!(self.db.layout());
|
|
||||||
|
|
||||||
let starting_indexes = Indexes::try_from((&mut self.vecs, &self.stores, rpc))
|
let starting_indexes = Indexes::try_from((&mut self.vecs, &self.stores, rpc))
|
||||||
.unwrap_or_else(|_report| Indexes::default());
|
.unwrap_or_else(|_report| Indexes::default());
|
||||||
|
|
||||||
// dbg!(&starting_indexes);
|
|
||||||
|
|
||||||
let lock = exit.lock();
|
let lock = exit.lock();
|
||||||
self.stores
|
self.stores
|
||||||
.rollback_if_needed(&mut self.vecs, &starting_indexes)?;
|
.rollback_if_needed(&mut self.vecs, &starting_indexes)?;
|
||||||
@@ -108,7 +100,6 @@ impl Indexer {
|
|||||||
vecs.flush(height)?;
|
vecs.flush(height)?;
|
||||||
info!("Flushed vecs in {}s", i.elapsed().as_secs());
|
info!("Flushed vecs in {}s", i.elapsed().as_secs());
|
||||||
let i = Instant::now();
|
let i = Instant::now();
|
||||||
db.flush()?;
|
|
||||||
info!("Flushed db in {}s", i.elapsed().as_secs());
|
info!("Flushed db in {}s", i.elapsed().as_secs());
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
@@ -210,6 +201,10 @@ impl Indexer {
|
|||||||
.blockhashprefix_to_height
|
.blockhashprefix_to_height
|
||||||
.insert_if_needed(blockhash_prefix, height, height);
|
.insert_if_needed(blockhash_prefix, height, height);
|
||||||
|
|
||||||
|
stores
|
||||||
|
.height_to_coinbase_tag
|
||||||
|
.insert_if_needed( height, block.coinbase_tag().into(), height);
|
||||||
|
|
||||||
vecs.height_to_blockhash.push_if_needed(height, blockhash)?;
|
vecs.height_to_blockhash.push_if_needed(height, blockhash)?;
|
||||||
vecs.height_to_difficulty
|
vecs.height_to_difficulty
|
||||||
.push_if_needed(height, block.header.difficulty_float().into())?;
|
.push_if_needed(height, block.header.difficulty_float().into())?;
|
||||||
@@ -797,7 +792,7 @@ impl Indexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let i = Instant::now();
|
let i = Instant::now();
|
||||||
db.punch_holes()?;
|
self.vecs.punch_holes()?;
|
||||||
info!("Punched holes in db in {}s", i.elapsed().as_secs());
|
info!("Punched holes in db in {}s", i.elapsed().as_secs());
|
||||||
|
|
||||||
Ok(starting_indexes)
|
Ok(starting_indexes)
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ use brk_error::Result;
|
|||||||
use brk_store::{AnyStore, Store};
|
use brk_store::{AnyStore, Store};
|
||||||
use brk_structs::{
|
use brk_structs::{
|
||||||
AddressBytes, AddressBytesHash, BlockHashPrefix, ByAddressType, Height, OutputIndex,
|
AddressBytes, AddressBytesHash, BlockHashPrefix, ByAddressType, Height, OutputIndex,
|
||||||
OutputType, TxIndex, TxidPrefix, TypeIndex, TypeIndexWithOutputindex, Unit, Version,
|
OutputType, StoredString, TxIndex, TxidPrefix, TypeIndex, TypeIndexWithOutputindex, Unit,
|
||||||
|
Version,
|
||||||
};
|
};
|
||||||
use fjall::{PersistMode, TransactionalKeyspace};
|
use fjall::{PersistMode, TransactionalKeyspace};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use vecdb::VecIterator;
|
use vecdb::{AnyVec, StoredIndex, VecIterator};
|
||||||
|
|
||||||
use crate::Indexes;
|
use crate::Indexes;
|
||||||
|
|
||||||
@@ -20,22 +21,23 @@ pub struct Stores {
|
|||||||
|
|
||||||
pub addressbyteshash_to_typeindex: Store<AddressBytesHash, TypeIndex>,
|
pub addressbyteshash_to_typeindex: Store<AddressBytesHash, TypeIndex>,
|
||||||
pub blockhashprefix_to_height: Store<BlockHashPrefix, Height>,
|
pub blockhashprefix_to_height: Store<BlockHashPrefix, Height>,
|
||||||
|
pub height_to_coinbase_tag: Store<Height, StoredString>,
|
||||||
pub txidprefix_to_txindex: Store<TxidPrefix, TxIndex>,
|
pub txidprefix_to_txindex: Store<TxidPrefix, TxIndex>,
|
||||||
pub addresstype_to_typeindex_with_outputindex:
|
pub addresstype_to_typeindex_with_outputindex:
|
||||||
ByAddressType<Store<TypeIndexWithOutputindex, Unit>>,
|
ByAddressType<Store<TypeIndexWithOutputindex, Unit>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const VERSION: Version = Version::ZERO;
|
|
||||||
|
|
||||||
impl Stores {
|
impl Stores {
|
||||||
pub fn forced_import(path: &Path, version: Version) -> Result<Self> {
|
pub fn forced_import(parent: &Path, version: Version) -> Result<Self> {
|
||||||
fs::create_dir_all(path)?;
|
let path = parent.join("stores");
|
||||||
|
|
||||||
let keyspace = match brk_store::open_keyspace(path) {
|
fs::create_dir_all(&path)?;
|
||||||
|
|
||||||
|
let keyspace = match brk_store::open_keyspace(&path) {
|
||||||
Ok(keyspace) => keyspace,
|
Ok(keyspace) => keyspace,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
fs::remove_dir_all(path)?;
|
fs::remove_dir_all(&path)?;
|
||||||
return Self::forced_import(path, version);
|
return Self::forced_import(&path, version);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,106 +45,97 @@ impl Stores {
|
|||||||
let addressbyteshash_to_typeindex = scope.spawn(|| {
|
let addressbyteshash_to_typeindex = scope.spawn(|| {
|
||||||
Store::import(
|
Store::import(
|
||||||
&keyspace,
|
&keyspace,
|
||||||
path,
|
&path,
|
||||||
"addressbyteshash_to_typeindex",
|
"addressbyteshash_to_typeindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let blockhashprefix_to_height = scope.spawn(|| {
|
let blockhashprefix_to_height = scope.spawn(|| {
|
||||||
Store::import(
|
Store::import(&keyspace, &path, "blockhashprefix_to_height", version, None)
|
||||||
&keyspace,
|
|
||||||
path,
|
|
||||||
"blockhashprefix_to_height",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
let txidprefix_to_txindex = scope.spawn(|| {
|
|
||||||
Store::import(
|
|
||||||
&keyspace,
|
|
||||||
path,
|
|
||||||
"txidprefix_to_txindex",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
|
let txidprefix_to_txindex = scope
|
||||||
|
.spawn(|| Store::import(&keyspace, &path, "txidprefix_to_txindex", version, None));
|
||||||
let p2aaddressindex_with_outputindex = scope.spawn(|| {
|
let p2aaddressindex_with_outputindex = scope.spawn(|| {
|
||||||
Store::import(
|
Store::import(
|
||||||
&keyspace,
|
&keyspace,
|
||||||
path,
|
&path,
|
||||||
"p2aaddressindex_with_outputindex",
|
"p2aaddressindex_with_outputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
Some(false),
|
Some(false),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let p2pk33addressindex_with_outputindex = scope.spawn(|| {
|
let p2pk33addressindex_with_outputindex = scope.spawn(|| {
|
||||||
Store::import(
|
Store::import(
|
||||||
&keyspace,
|
&keyspace,
|
||||||
path,
|
&path,
|
||||||
"p2pk33addressindex_with_outputindex",
|
"p2pk33addressindex_with_outputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
Some(false),
|
Some(false),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let p2pk65addressindex_with_outputindex = scope.spawn(|| {
|
let p2pk65addressindex_with_outputindex = scope.spawn(|| {
|
||||||
Store::import(
|
Store::import(
|
||||||
&keyspace,
|
&keyspace,
|
||||||
path,
|
&path,
|
||||||
"p2pk65addressindex_with_outputindex",
|
"p2pk65addressindex_with_outputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
Some(false),
|
Some(false),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let p2pkhaddressindex_with_outputindex = scope.spawn(|| {
|
let p2pkhaddressindex_with_outputindex = scope.spawn(|| {
|
||||||
Store::import(
|
Store::import(
|
||||||
&keyspace,
|
&keyspace,
|
||||||
path,
|
&path,
|
||||||
"p2pkhaddressindex_with_outputindex",
|
"p2pkhaddressindex_with_outputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
Some(false),
|
Some(false),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let p2shaddressindex_with_outputindex = scope.spawn(|| {
|
let p2shaddressindex_with_outputindex = scope.spawn(|| {
|
||||||
Store::import(
|
Store::import(
|
||||||
&keyspace,
|
&keyspace,
|
||||||
path,
|
&path,
|
||||||
"p2shaddressindex_with_outputindex",
|
"p2shaddressindex_with_outputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
Some(false),
|
Some(false),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let p2traddressindex_with_outputindex = scope.spawn(|| {
|
let p2traddressindex_with_outputindex = scope.spawn(|| {
|
||||||
Store::import(
|
Store::import(
|
||||||
&keyspace,
|
&keyspace,
|
||||||
path,
|
&path,
|
||||||
"p2traddressindex_with_outputindex",
|
"p2traddressindex_with_outputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
Some(false),
|
Some(false),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let p2wpkhaddressindex_with_outputindex = scope.spawn(|| {
|
let p2wpkhaddressindex_with_outputindex = scope.spawn(|| {
|
||||||
Store::import(
|
Store::import(
|
||||||
&keyspace,
|
&keyspace,
|
||||||
path,
|
&path,
|
||||||
"p2wpkhaddressindex_with_outputindex",
|
"p2wpkhaddressindex_with_outputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
Some(false),
|
Some(false),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let p2wshaddressindex_with_outputindex = scope.spawn(|| {
|
let p2wshaddressindex_with_outputindex = scope.spawn(|| {
|
||||||
Store::import(
|
Store::import(
|
||||||
&keyspace,
|
&keyspace,
|
||||||
path,
|
&path,
|
||||||
"p2wshaddressindex_with_outputindex",
|
"p2wshaddressindex_with_outputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
Some(false),
|
Some(false),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let height_to_coinbase_tag =
|
||||||
|
Store::import(&keyspace, &path, "height_to_coinbase_tag", version, None)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
keyspace: keyspace.clone(),
|
keyspace: keyspace.clone(),
|
||||||
|
|
||||||
|
height_to_coinbase_tag,
|
||||||
addressbyteshash_to_typeindex: addressbyteshash_to_typeindex.join().unwrap()?,
|
addressbyteshash_to_typeindex: addressbyteshash_to_typeindex.join().unwrap()?,
|
||||||
blockhashprefix_to_height: blockhashprefix_to_height.join().unwrap()?,
|
blockhashprefix_to_height: blockhashprefix_to_height.join().unwrap()?,
|
||||||
txidprefix_to_txindex: txidprefix_to_txindex.join().unwrap()?,
|
txidprefix_to_txindex: txidprefix_to_txindex.join().unwrap()?,
|
||||||
@@ -182,11 +175,9 @@ impl Stores {
|
|||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_slice(&self) -> [&(dyn AnyStore + Send + Sync); 11] {
|
fn as_slice(&self) -> [&(dyn AnyStore + Send + Sync); 12] {
|
||||||
[
|
[
|
||||||
&self.addressbyteshash_to_typeindex,
|
&self.addressbyteshash_to_typeindex,
|
||||||
&self.blockhashprefix_to_height,
|
|
||||||
&self.txidprefix_to_txindex,
|
|
||||||
&self.addresstype_to_typeindex_with_outputindex.p2a,
|
&self.addresstype_to_typeindex_with_outputindex.p2a,
|
||||||
&self.addresstype_to_typeindex_with_outputindex.p2pk33,
|
&self.addresstype_to_typeindex_with_outputindex.p2pk33,
|
||||||
&self.addresstype_to_typeindex_with_outputindex.p2pk65,
|
&self.addresstype_to_typeindex_with_outputindex.p2pk65,
|
||||||
@@ -195,14 +186,15 @@ impl Stores {
|
|||||||
&self.addresstype_to_typeindex_with_outputindex.p2tr,
|
&self.addresstype_to_typeindex_with_outputindex.p2tr,
|
||||||
&self.addresstype_to_typeindex_with_outputindex.p2wpkh,
|
&self.addresstype_to_typeindex_with_outputindex.p2wpkh,
|
||||||
&self.addresstype_to_typeindex_with_outputindex.p2wsh,
|
&self.addresstype_to_typeindex_with_outputindex.p2wsh,
|
||||||
|
&self.blockhashprefix_to_height,
|
||||||
|
&self.height_to_coinbase_tag,
|
||||||
|
&self.txidprefix_to_txindex,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_mut_slice(&mut self) -> [&mut (dyn AnyStore + Send + Sync); 11] {
|
fn as_mut_slice(&mut self) -> [&mut (dyn AnyStore + Send + Sync); 12] {
|
||||||
[
|
[
|
||||||
&mut self.addressbyteshash_to_typeindex,
|
&mut self.addressbyteshash_to_typeindex,
|
||||||
&mut self.blockhashprefix_to_height,
|
|
||||||
&mut self.txidprefix_to_txindex,
|
|
||||||
&mut self.addresstype_to_typeindex_with_outputindex.p2a,
|
&mut self.addresstype_to_typeindex_with_outputindex.p2a,
|
||||||
&mut self.addresstype_to_typeindex_with_outputindex.p2pk33,
|
&mut self.addresstype_to_typeindex_with_outputindex.p2pk33,
|
||||||
&mut self.addresstype_to_typeindex_with_outputindex.p2pk65,
|
&mut self.addresstype_to_typeindex_with_outputindex.p2pk65,
|
||||||
@@ -211,6 +203,9 @@ impl Stores {
|
|||||||
&mut self.addresstype_to_typeindex_with_outputindex.p2tr,
|
&mut self.addresstype_to_typeindex_with_outputindex.p2tr,
|
||||||
&mut self.addresstype_to_typeindex_with_outputindex.p2wpkh,
|
&mut self.addresstype_to_typeindex_with_outputindex.p2wpkh,
|
||||||
&mut self.addresstype_to_typeindex_with_outputindex.p2wsh,
|
&mut self.addresstype_to_typeindex_with_outputindex.p2wsh,
|
||||||
|
&mut self.blockhashprefix_to_height,
|
||||||
|
&mut self.height_to_coinbase_tag,
|
||||||
|
&mut self.txidprefix_to_txindex,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +217,7 @@ impl Stores {
|
|||||||
if self.addressbyteshash_to_typeindex.is_empty()?
|
if self.addressbyteshash_to_typeindex.is_empty()?
|
||||||
&& self.blockhashprefix_to_height.is_empty()?
|
&& self.blockhashprefix_to_height.is_empty()?
|
||||||
&& self.txidprefix_to_txindex.is_empty()?
|
&& self.txidprefix_to_txindex.is_empty()?
|
||||||
|
&& self.height_to_coinbase_tag.is_empty()?
|
||||||
&& self
|
&& self
|
||||||
.addresstype_to_typeindex_with_outputindex
|
.addresstype_to_typeindex_with_outputindex
|
||||||
.p2a
|
.p2a
|
||||||
@@ -266,6 +262,12 @@ impl Stores {
|
|||||||
self.blockhashprefix_to_height.remove(blockhashprefix);
|
self.blockhashprefix_to_height.remove(blockhashprefix);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
(starting_indexes.height.unwrap_to_usize()..vecs.height_to_blockhash.len())
|
||||||
|
.map(Height::from)
|
||||||
|
.for_each(|h| {
|
||||||
|
self.height_to_coinbase_tag.remove(h);
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(mut index) = vecs
|
if let Some(mut index) = vecs
|
||||||
.height_to_first_p2pk65addressindex
|
.height_to_first_p2pk65addressindex
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
+91
-171
@@ -1,3 +1,5 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use brk_error::Result;
|
use brk_error::Result;
|
||||||
use brk_structs::{
|
use brk_structs::{
|
||||||
AddressBytes, BlockHash, EmptyOutputIndex, Height, InputIndex, OpReturnIndex, OutputIndex,
|
AddressBytes, BlockHash, EmptyOutputIndex, Height, InputIndex, OpReturnIndex, OutputIndex,
|
||||||
@@ -9,15 +11,16 @@ use brk_structs::{
|
|||||||
};
|
};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use vecdb::{
|
use vecdb::{
|
||||||
AnyCollectableVec, AnyStoredVec, CompressedVec, Database, GenericStoredVec, RawVec, Stamp,
|
AnyCollectableVec, AnyStoredVec, CompressedVec, Database, GenericStoredVec, PAGE_SIZE, RawVec,
|
||||||
|
Stamp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Indexes;
|
use crate::Indexes;
|
||||||
|
|
||||||
const VERSION: Version = Version::ZERO;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Vecs {
|
pub struct Vecs {
|
||||||
|
db: Database,
|
||||||
|
|
||||||
pub emptyoutputindex_to_txindex: CompressedVec<EmptyOutputIndex, TxIndex>,
|
pub emptyoutputindex_to_txindex: CompressedVec<EmptyOutputIndex, TxIndex>,
|
||||||
pub height_to_blockhash: RawVec<Height, BlockHash>,
|
pub height_to_blockhash: RawVec<Height, BlockHash>,
|
||||||
pub height_to_difficulty: CompressedVec<Height, StoredF64>,
|
pub height_to_difficulty: CompressedVec<Height, StoredF64>,
|
||||||
@@ -67,225 +70,136 @@ pub struct Vecs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Vecs {
|
impl Vecs {
|
||||||
pub fn forced_import(db: &Database, version: Version) -> Result<Self> {
|
pub fn forced_import(parent: &Path, version: Version) -> Result<Self> {
|
||||||
Ok(Self {
|
let db = Database::open(&parent.join("vecs"))?;
|
||||||
emptyoutputindex_to_txindex: CompressedVec::forced_import(
|
|
||||||
db,
|
db.set_min_len(PAGE_SIZE * 50_000_000)?;
|
||||||
"txindex",
|
|
||||||
version + VERSION + Version::ZERO,
|
let this = Self {
|
||||||
)?,
|
emptyoutputindex_to_txindex: CompressedVec::forced_import(&db, "txindex", version)?,
|
||||||
height_to_blockhash: RawVec::forced_import(
|
height_to_blockhash: RawVec::forced_import(&db, "blockhash", version)?,
|
||||||
db,
|
height_to_difficulty: CompressedVec::forced_import(&db, "difficulty", version)?,
|
||||||
"blockhash",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
height_to_difficulty: CompressedVec::forced_import(
|
|
||||||
db,
|
|
||||||
"difficulty",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
height_to_first_emptyoutputindex: CompressedVec::forced_import(
|
height_to_first_emptyoutputindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_emptyoutputindex",
|
"first_emptyoutputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
height_to_first_inputindex: CompressedVec::forced_import(
|
height_to_first_inputindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_inputindex",
|
"first_inputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
height_to_first_opreturnindex: CompressedVec::forced_import(
|
height_to_first_opreturnindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_opreturnindex",
|
"first_opreturnindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
height_to_first_outputindex: CompressedVec::forced_import(
|
height_to_first_outputindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_outputindex",
|
"first_outputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
height_to_first_p2aaddressindex: CompressedVec::forced_import(
|
height_to_first_p2aaddressindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_p2aaddressindex",
|
"first_p2aaddressindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
height_to_first_p2msoutputindex: CompressedVec::forced_import(
|
height_to_first_p2msoutputindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_p2msoutputindex",
|
"first_p2msoutputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
height_to_first_p2pk33addressindex: CompressedVec::forced_import(
|
height_to_first_p2pk33addressindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_p2pk33addressindex",
|
"first_p2pk33addressindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
height_to_first_p2pk65addressindex: CompressedVec::forced_import(
|
height_to_first_p2pk65addressindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_p2pk65addressindex",
|
"first_p2pk65addressindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
height_to_first_p2pkhaddressindex: CompressedVec::forced_import(
|
height_to_first_p2pkhaddressindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_p2pkhaddressindex",
|
"first_p2pkhaddressindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
height_to_first_p2shaddressindex: CompressedVec::forced_import(
|
height_to_first_p2shaddressindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_p2shaddressindex",
|
"first_p2shaddressindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
height_to_first_p2traddressindex: CompressedVec::forced_import(
|
height_to_first_p2traddressindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_p2traddressindex",
|
"first_p2traddressindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
height_to_first_p2wpkhaddressindex: CompressedVec::forced_import(
|
height_to_first_p2wpkhaddressindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_p2wpkhaddressindex",
|
"first_p2wpkhaddressindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
height_to_first_p2wshaddressindex: CompressedVec::forced_import(
|
height_to_first_p2wshaddressindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_p2wshaddressindex",
|
"first_p2wshaddressindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
|
||||||
height_to_first_txindex: CompressedVec::forced_import(
|
|
||||||
db,
|
|
||||||
"first_txindex",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
)?,
|
||||||
|
height_to_first_txindex: CompressedVec::forced_import(&db, "first_txindex", version)?,
|
||||||
height_to_first_unknownoutputindex: CompressedVec::forced_import(
|
height_to_first_unknownoutputindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_unknownoutputindex",
|
"first_unknownoutputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
|
||||||
height_to_timestamp: CompressedVec::forced_import(
|
|
||||||
db,
|
|
||||||
"timestamp",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
height_to_total_size: CompressedVec::forced_import(
|
|
||||||
db,
|
|
||||||
"total_size",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
height_to_weight: CompressedVec::forced_import(
|
|
||||||
db,
|
|
||||||
"weight",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
inputindex_to_outputindex: RawVec::forced_import(
|
|
||||||
db,
|
|
||||||
"outputindex",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
opreturnindex_to_txindex: CompressedVec::forced_import(
|
|
||||||
db,
|
|
||||||
"txindex",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
outputindex_to_outputtype: RawVec::forced_import(
|
|
||||||
db,
|
|
||||||
"outputtype",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
outputindex_to_typeindex: RawVec::forced_import(
|
|
||||||
db,
|
|
||||||
"typeindex",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
outputindex_to_value: RawVec::forced_import(
|
|
||||||
db,
|
|
||||||
"value",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
p2aaddressindex_to_p2abytes: RawVec::forced_import(
|
|
||||||
db,
|
|
||||||
"p2abytes",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
p2msoutputindex_to_txindex: CompressedVec::forced_import(
|
|
||||||
db,
|
|
||||||
"txindex",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
p2pk33addressindex_to_p2pk33bytes: RawVec::forced_import(
|
|
||||||
db,
|
|
||||||
"p2pk33bytes",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
p2pk65addressindex_to_p2pk65bytes: RawVec::forced_import(
|
|
||||||
db,
|
|
||||||
"p2pk65bytes",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
p2pkhaddressindex_to_p2pkhbytes: RawVec::forced_import(
|
|
||||||
db,
|
|
||||||
"p2pkhbytes",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
p2shaddressindex_to_p2shbytes: RawVec::forced_import(
|
|
||||||
db,
|
|
||||||
"p2shbytes",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
p2traddressindex_to_p2trbytes: RawVec::forced_import(
|
|
||||||
db,
|
|
||||||
"p2trbytes",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
p2wpkhaddressindex_to_p2wpkhbytes: RawVec::forced_import(
|
|
||||||
db,
|
|
||||||
"p2wpkhbytes",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
p2wshaddressindex_to_p2wshbytes: RawVec::forced_import(
|
|
||||||
db,
|
|
||||||
"p2wshbytes",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
txindex_to_base_size: CompressedVec::forced_import(
|
|
||||||
db,
|
|
||||||
"base_size",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
)?,
|
||||||
|
height_to_timestamp: CompressedVec::forced_import(&db, "timestamp", version)?,
|
||||||
|
height_to_total_size: CompressedVec::forced_import(&db, "total_size", version)?,
|
||||||
|
height_to_weight: CompressedVec::forced_import(&db, "weight", version)?,
|
||||||
|
inputindex_to_outputindex: RawVec::forced_import(&db, "outputindex", version)?,
|
||||||
|
opreturnindex_to_txindex: CompressedVec::forced_import(&db, "txindex", version)?,
|
||||||
|
outputindex_to_outputtype: RawVec::forced_import(&db, "outputtype", version)?,
|
||||||
|
outputindex_to_typeindex: RawVec::forced_import(&db, "typeindex", version)?,
|
||||||
|
outputindex_to_value: RawVec::forced_import(&db, "value", version)?,
|
||||||
|
p2aaddressindex_to_p2abytes: RawVec::forced_import(&db, "p2abytes", version)?,
|
||||||
|
p2msoutputindex_to_txindex: CompressedVec::forced_import(&db, "txindex", version)?,
|
||||||
|
p2pk33addressindex_to_p2pk33bytes: RawVec::forced_import(&db, "p2pk33bytes", version)?,
|
||||||
|
p2pk65addressindex_to_p2pk65bytes: RawVec::forced_import(&db, "p2pk65bytes", version)?,
|
||||||
|
p2pkhaddressindex_to_p2pkhbytes: RawVec::forced_import(&db, "p2pkhbytes", version)?,
|
||||||
|
p2shaddressindex_to_p2shbytes: RawVec::forced_import(&db, "p2shbytes", version)?,
|
||||||
|
p2traddressindex_to_p2trbytes: RawVec::forced_import(&db, "p2trbytes", version)?,
|
||||||
|
p2wpkhaddressindex_to_p2wpkhbytes: RawVec::forced_import(&db, "p2wpkhbytes", version)?,
|
||||||
|
p2wshaddressindex_to_p2wshbytes: RawVec::forced_import(&db, "p2wshbytes", version)?,
|
||||||
|
txindex_to_base_size: CompressedVec::forced_import(&db, "base_size", version)?,
|
||||||
txindex_to_first_inputindex: CompressedVec::forced_import(
|
txindex_to_first_inputindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_inputindex",
|
"first_inputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
txindex_to_first_outputindex: CompressedVec::forced_import(
|
txindex_to_first_outputindex: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"first_outputindex",
|
"first_outputindex",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
txindex_to_is_explicitly_rbf: CompressedVec::forced_import(
|
txindex_to_is_explicitly_rbf: CompressedVec::forced_import(
|
||||||
db,
|
&db,
|
||||||
"is_explicitly_rbf",
|
"is_explicitly_rbf",
|
||||||
version + VERSION + Version::ZERO,
|
version,
|
||||||
)?,
|
)?,
|
||||||
txindex_to_rawlocktime: CompressedVec::forced_import(
|
txindex_to_rawlocktime: CompressedVec::forced_import(&db, "rawlocktime", version)?,
|
||||||
db,
|
txindex_to_total_size: CompressedVec::forced_import(&db, "total_size", version)?,
|
||||||
"rawlocktime",
|
txindex_to_txid: RawVec::forced_import(&db, "txid", version)?,
|
||||||
version + VERSION + Version::ZERO,
|
txindex_to_txversion: CompressedVec::forced_import(&db, "txversion", version)?,
|
||||||
)?,
|
unknownoutputindex_to_txindex: CompressedVec::forced_import(&db, "txindex", version)?,
|
||||||
txindex_to_total_size: CompressedVec::forced_import(
|
|
||||||
db,
|
db,
|
||||||
"total_size",
|
};
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
// self.db.retain_regions(
|
||||||
txindex_to_txid: RawVec::forced_import(db, "txid", version + VERSION + Version::ZERO)?,
|
// this.vecs()
|
||||||
txindex_to_txversion: CompressedVec::forced_import(
|
// .into_iter()
|
||||||
db,
|
// .flat_map(|v| v.region_names())
|
||||||
"txversion",
|
// .collect(),
|
||||||
version + VERSION + Version::ZERO,
|
// )?;
|
||||||
)?,
|
|
||||||
unknownoutputindex_to_txindex: CompressedVec::forced_import(
|
Ok(this)
|
||||||
db,
|
|
||||||
"txindex",
|
|
||||||
version + VERSION + Version::ZERO,
|
|
||||||
)?,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rollback_if_needed(&mut self, starting_indexes: &Indexes) -> Result<()> {
|
pub fn rollback_if_needed(&mut self, starting_indexes: &Indexes) -> Result<()> {
|
||||||
@@ -438,6 +352,7 @@ impl Vecs {
|
|||||||
self.mut_vecs()
|
self.mut_vecs()
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.try_for_each(|vec| vec.stamped_flush(Stamp::from(height)))?;
|
.try_for_each(|vec| vec.stamped_flush(Stamp::from(height)))?;
|
||||||
|
self.db.flush()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,6 +367,11 @@ impl Vecs {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn punch_holes(&self) -> Result<()> {
|
||||||
|
self.db.punch_holes()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||||
vec![
|
vec![
|
||||||
&self.emptyoutputindex_to_txindex,
|
&self.emptyoutputindex_to_txindex,
|
||||||
|
|||||||
@@ -16,8 +16,10 @@ brk_indexer = { workspace = true }
|
|||||||
brk_structs = { workspace = true }
|
brk_structs = { workspace = true }
|
||||||
vecdb = { workspace = true }
|
vecdb = { workspace = true }
|
||||||
derive_deref = { workspace = true }
|
derive_deref = { workspace = true }
|
||||||
|
quick_cache = { workspace = true }
|
||||||
schemars = "1.0.4"
|
schemars = "1.0.4"
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
serde_with = "3.14.0"
|
serde_with = "3.14.0"
|
||||||
tabled = "0.20.0"
|
tabled = "0.20.0"
|
||||||
|
nucleo-matcher = "0.3.1"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use serde::Deserialize;
|
|||||||
|
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, JsonSchema)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum Format {
|
pub enum Format {
|
||||||
#[serde(alias = "json")]
|
#[serde(alias = "json")]
|
||||||
JSON,
|
JSON,
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use derive_deref::Deref;
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Deref, JsonSchema)]
|
||||||
|
pub struct MaybeIds(Vec<String>);
|
||||||
|
|
||||||
|
const MAX_STRING_SIZE: usize = 10_000;
|
||||||
|
const MAX_VECS: usize = 64;
|
||||||
|
|
||||||
|
impl From<String> for MaybeIds {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
Self(vec![value])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<Vec<&'a str>> for MaybeIds {
|
||||||
|
fn from(value: Vec<&'a str>) -> Self {
|
||||||
|
Self(value.iter().map(|s| s.to_string()).collect::<Vec<_>>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for MaybeIds {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
match serde_json::Value::deserialize(deserializer)? {
|
||||||
|
serde_json::Value::String(str) => {
|
||||||
|
if str.len() <= MAX_STRING_SIZE {
|
||||||
|
Ok(MaybeIds(sanitize_ids(
|
||||||
|
str.split(",").map(|s| s.to_string()),
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
dbg!(str.len(), MAX_STRING_SIZE);
|
||||||
|
Err(serde::de::Error::custom("Given parameter is too long"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
serde_json::Value::Array(vec) => {
|
||||||
|
if vec.len() <= MAX_VECS {
|
||||||
|
Ok(MaybeIds(sanitize_ids(
|
||||||
|
vec.into_iter().map(|s| s.as_str().unwrap().to_string()),
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
dbg!(vec.len(), MAX_VECS);
|
||||||
|
Err(serde::de::Error::custom("Given parameter is too long"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(serde::de::Error::custom("Bad ids format")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MaybeIds {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let s = self.0.join(",");
|
||||||
|
write!(f, "{s}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sanitize_ids(raw_ids: impl Iterator<Item = String>) -> Vec<String> {
|
||||||
|
let mut results = Vec::new();
|
||||||
|
raw_ids.for_each(|s| {
|
||||||
|
let mut current = String::new();
|
||||||
|
for c in s.to_lowercase().chars() {
|
||||||
|
match c {
|
||||||
|
' ' | ',' | '+' => {
|
||||||
|
if !current.is_empty() {
|
||||||
|
results.push(std::mem::take(&mut current));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'-' => current.push('_'),
|
||||||
|
c if c.is_alphanumeric() || c == '_' => current.push(c),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !current.is_empty() {
|
||||||
|
results.push(current);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
results
|
||||||
|
}
|
||||||
@@ -2,16 +2,17 @@ use std::fmt::{self, Debug};
|
|||||||
|
|
||||||
use brk_error::Error;
|
use brk_error::Error;
|
||||||
use brk_structs::{
|
use brk_structs::{
|
||||||
DateIndex, DecadeIndex, DifficultyEpoch, EmptyOutputIndex, HalvingEpoch, Height, InputIndex,
|
DateIndex, DecadeIndex, DifficultyEpoch, EmptyAddressIndex, EmptyOutputIndex, HalvingEpoch,
|
||||||
MonthIndex, OpReturnIndex, OutputIndex, P2AAddressIndex, P2MSOutputIndex, P2PK33AddressIndex,
|
Height, InputIndex, LoadedAddressIndex, MonthIndex, OpReturnIndex, OutputIndex,
|
||||||
P2PK65AddressIndex, P2PKHAddressIndex, P2SHAddressIndex, P2TRAddressIndex, P2WPKHAddressIndex,
|
P2AAddressIndex, P2MSOutputIndex, P2PK33AddressIndex, P2PK65AddressIndex, P2PKHAddressIndex,
|
||||||
P2WSHAddressIndex, Printable, QuarterIndex, SemesterIndex, TxIndex, UnknownOutputIndex,
|
P2SHAddressIndex, P2TRAddressIndex, P2WPKHAddressIndex, P2WSHAddressIndex, Printable,
|
||||||
WeekIndex, YearIndex,
|
QuarterIndex, SemesterIndex, TxIndex, UnknownOutputIndex, WeekIndex, YearIndex,
|
||||||
};
|
};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum Index {
|
pub enum Index {
|
||||||
#[schemars(description = "Date/day index")]
|
#[schemars(description = "Date/day index")]
|
||||||
DateIndex,
|
DateIndex,
|
||||||
@@ -63,10 +64,14 @@ pub enum Index {
|
|||||||
WeekIndex,
|
WeekIndex,
|
||||||
#[schemars(description = "Year index")]
|
#[schemars(description = "Year index")]
|
||||||
YearIndex,
|
YearIndex,
|
||||||
|
#[schemars(description = "Loaded Address Index")]
|
||||||
|
LoadedAddressIndex,
|
||||||
|
#[schemars(description = "Empty Address Index")]
|
||||||
|
EmptyAddressIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index {
|
impl Index {
|
||||||
pub fn all() -> [Self; 25] {
|
pub fn all() -> [Self; 27] {
|
||||||
[
|
[
|
||||||
Self::DateIndex,
|
Self::DateIndex,
|
||||||
Self::DecadeIndex,
|
Self::DecadeIndex,
|
||||||
@@ -93,6 +98,8 @@ impl Index {
|
|||||||
Self::UnknownOutputIndex,
|
Self::UnknownOutputIndex,
|
||||||
Self::WeekIndex,
|
Self::WeekIndex,
|
||||||
Self::YearIndex,
|
Self::YearIndex,
|
||||||
|
Self::LoadedAddressIndex,
|
||||||
|
Self::EmptyAddressIndex,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +130,8 @@ impl Index {
|
|||||||
Self::UnknownOutputIndex => UnknownOutputIndex::to_possible_strings(),
|
Self::UnknownOutputIndex => UnknownOutputIndex::to_possible_strings(),
|
||||||
Self::WeekIndex => WeekIndex::to_possible_strings(),
|
Self::WeekIndex => WeekIndex::to_possible_strings(),
|
||||||
Self::YearIndex => YearIndex::to_possible_strings(),
|
Self::YearIndex => YearIndex::to_possible_strings(),
|
||||||
|
Self::LoadedAddressIndex => LoadedAddressIndex::to_possible_strings(),
|
||||||
|
Self::EmptyAddressIndex => EmptyAddressIndex::to_possible_strings(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,6 +195,12 @@ impl TryFrom<&str> for Index {
|
|||||||
v if (Self::UnknownOutputIndex).possible_values().contains(&v) => {
|
v if (Self::UnknownOutputIndex).possible_values().contains(&v) => {
|
||||||
Self::UnknownOutputIndex
|
Self::UnknownOutputIndex
|
||||||
}
|
}
|
||||||
|
v if (Self::LoadedAddressIndex).possible_values().contains(&v) => {
|
||||||
|
Self::LoadedAddressIndex
|
||||||
|
}
|
||||||
|
v if (Self::EmptyAddressIndex).possible_values().contains(&v) => {
|
||||||
|
Self::EmptyAddressIndex
|
||||||
|
}
|
||||||
_ => return Err(Error::Str("Bad index")),
|
_ => return Err(Error::Str("Bad index")),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,23 @@
|
|||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::{collections::BTreeMap, sync::OnceLock};
|
||||||
|
|
||||||
use brk_computer::Computer;
|
use brk_computer::Computer;
|
||||||
use brk_error::Result;
|
use brk_error::{Error, Result};
|
||||||
use brk_indexer::Indexer;
|
use brk_indexer::Indexer;
|
||||||
use brk_structs::Height;
|
use brk_structs::Height;
|
||||||
|
use nucleo_matcher::{
|
||||||
|
Config, Matcher,
|
||||||
|
pattern::{AtomKind, CaseMatching, Normalization, Pattern},
|
||||||
|
};
|
||||||
|
use quick_cache::sync::Cache;
|
||||||
use tabled::settings::Style;
|
use tabled::settings::Style;
|
||||||
use vecdb::{AnyCollectableVec, AnyStoredVec};
|
use vecdb::{AnyCollectableVec, AnyStoredVec};
|
||||||
|
|
||||||
mod deser;
|
mod deser;
|
||||||
mod format;
|
mod format;
|
||||||
|
mod ids;
|
||||||
mod index;
|
mod index;
|
||||||
mod maybe_ids;
|
|
||||||
mod output;
|
mod output;
|
||||||
mod pagination;
|
mod pagination;
|
||||||
mod params;
|
mod params;
|
||||||
@@ -29,6 +34,11 @@ use vecs::Vecs;
|
|||||||
|
|
||||||
use crate::vecs::{IdToVec, IndexToVec};
|
use crate::vecs::{IdToVec, IndexToVec};
|
||||||
|
|
||||||
|
pub fn cached_errors() -> &'static Cache<String, String> {
|
||||||
|
static CACHE: OnceLock<Cache<String, String>> = OnceLock::new();
|
||||||
|
CACHE.get_or_init(|| Cache::new(1000))
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct Interface<'a> {
|
pub struct Interface<'a> {
|
||||||
vecs: Vecs<'a>,
|
vecs: Vecs<'a>,
|
||||||
@@ -53,38 +63,64 @@ impl<'a> Interface<'a> {
|
|||||||
Height::from(self.indexer.vecs.height_to_blockhash.stamp())
|
Height::from(self.indexer.vecs.height_to_blockhash.stamp())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search(&self, params: &Params) -> Vec<(String, &&dyn AnyCollectableVec)> {
|
pub fn search(&self, params: &Params) -> Result<Vec<(String, &&dyn AnyCollectableVec)>> {
|
||||||
let tuples = params
|
let ids = ¶ms.ids;
|
||||||
.ids
|
let index = params.index;
|
||||||
.iter()
|
|
||||||
.flat_map(|s| {
|
|
||||||
s.to_lowercase()
|
|
||||||
.replace("-", "_")
|
|
||||||
.split_whitespace()
|
|
||||||
.flat_map(|s| {
|
|
||||||
s.split(',')
|
|
||||||
.flat_map(|s| s.split('+').map(|s| s.to_string()))
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
})
|
|
||||||
.map(|mut id| {
|
|
||||||
let mut res = self.vecs.id_to_index_to_vec.get(id.as_str());
|
|
||||||
if res.is_none()
|
|
||||||
&& let Ok(index) = Index::try_from(id.as_str())
|
|
||||||
{
|
|
||||||
id = index.possible_values().last().unwrap().to_string();
|
|
||||||
res = self.vecs.id_to_index_to_vec.get(id.as_str())
|
|
||||||
}
|
|
||||||
(id, res)
|
|
||||||
})
|
|
||||||
.filter(|(_, opt)| opt.is_some())
|
|
||||||
.map(|(id, vec)| (id, vec.unwrap()))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
tuples
|
let ids_to_vec = self
|
||||||
.iter()
|
.vecs
|
||||||
.flat_map(|(str, i_to_v)| i_to_v.get(¶ms.index).map(|vec| (str.to_owned(), vec)))
|
.index_to_id_to_vec
|
||||||
.collect::<Vec<_>>()
|
.get(&index)
|
||||||
|
.ok_or(Error::String(format!(
|
||||||
|
"Index \"{}\" isn't a valid index",
|
||||||
|
index
|
||||||
|
)))?;
|
||||||
|
|
||||||
|
ids.iter()
|
||||||
|
.map(|id| {
|
||||||
|
let vec = ids_to_vec.get(id.as_str()).ok_or_else(|| {
|
||||||
|
let cached_errors = cached_errors();
|
||||||
|
|
||||||
|
if let Some(message) = cached_errors.get(id) {
|
||||||
|
return Error::String(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut message = format!(
|
||||||
|
"No vec named \"{}\" indexed by \"{}\" found.\n",
|
||||||
|
id,
|
||||||
|
index
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut matcher = Matcher::new(Config::DEFAULT);
|
||||||
|
|
||||||
|
let matches = Pattern::new(
|
||||||
|
id.as_str(),
|
||||||
|
CaseMatching::Ignore,
|
||||||
|
Normalization::Smart,
|
||||||
|
AtomKind::Fuzzy,
|
||||||
|
)
|
||||||
|
.match_list(ids_to_vec.keys(), &mut matcher)
|
||||||
|
.into_iter()
|
||||||
|
.take(10)
|
||||||
|
.map(|(s, _)| s)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if !matches.is_empty() {
|
||||||
|
message +=
|
||||||
|
&format!("\nMaybe you meant one of the following: {matches:#?} ?\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(index_to_vec) = self.id_to_index_to_vec().get(id.as_str()) {
|
||||||
|
message += &format!("\nBut there is a vec named {id} which supports the following indexes: {:#?}\n", index_to_vec.keys());
|
||||||
|
}
|
||||||
|
|
||||||
|
cached_errors.insert(id.clone(), message.clone());
|
||||||
|
|
||||||
|
Error::String(message)
|
||||||
|
});
|
||||||
|
vec.map(|vec| (id.clone(), vec))
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(
|
||||||
@@ -183,7 +219,7 @@ impl<'a> Interface<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn search_and_format(&self, params: Params) -> Result<Output> {
|
pub fn search_and_format(&self, params: Params) -> Result<Output> {
|
||||||
self.format(self.search(¶ms), ¶ms.rest)
|
self.format(self.search(¶ms)?, ¶ms.rest)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id_to_index_to_vec(&self) -> &BTreeMap<&str, IndexToVec<'_>> {
|
pub fn id_to_index_to_vec(&self) -> &BTreeMap<&str, IndexToVec<'_>> {
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
use derive_deref::Deref;
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
#[derive(Debug, Deref, JsonSchema)]
|
|
||||||
pub struct MaybeIds(Vec<String>);
|
|
||||||
|
|
||||||
impl From<String> for MaybeIds {
|
|
||||||
fn from(value: String) -> Self {
|
|
||||||
Self(vec![value])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<Vec<&'a str>> for MaybeIds {
|
|
||||||
fn from(value: Vec<&'a str>) -> Self {
|
|
||||||
Self(value.iter().map(|s| s.to_string()).collect::<Vec<_>>())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for MaybeIds {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let maybe_ids = match serde_json::Value::deserialize(deserializer)? {
|
|
||||||
serde_json::Value::String(str) => {
|
|
||||||
str.split(",").map(|s| s.to_string()).collect::<Vec<_>>()
|
|
||||||
}
|
|
||||||
serde_json::Value::Array(vec) => vec
|
|
||||||
.into_iter()
|
|
||||||
.map(|s| s.as_str().unwrap().to_string())
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
_ => return Err(serde::de::Error::custom("Bad ids format")),
|
|
||||||
};
|
|
||||||
// dbg!(&maybe_ids);
|
|
||||||
Ok(MaybeIds(maybe_ids))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,7 @@ use tabled::Tabled as TabledTabled;
|
|||||||
use crate::Format;
|
use crate::Format;
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged, rename_all = "lowercase")]
|
||||||
pub enum Output {
|
pub enum Output {
|
||||||
Json(Value),
|
Json(Value),
|
||||||
CSV(String),
|
CSV(String),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use serde::Deserialize;
|
|||||||
use crate::{
|
use crate::{
|
||||||
Format, Index,
|
Format, Index,
|
||||||
deser::{de_unquote_i64, de_unquote_usize},
|
deser::{de_unquote_i64, de_unquote_usize},
|
||||||
maybe_ids::MaybeIds,
|
ids::MaybeIds,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, JsonSchema)]
|
#[derive(Debug, Deserialize, JsonSchema)]
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
`brk_mcp` provides a Model Context Protocol server that enables Large Language Models (LLMs) to access Bitcoin blockchain data through BRK's interface layer. It implements the MCP specification to expose BRK's analytics capabilities as tools that LLMs can call.
|
`brk_mcp` provides a Model Context Protocol server that enables Large Language Models (LLMs) to access Bitcoin blockchain data through BRK's interface layer. It implements the MCP specification to expose BRK's analytics capabilities as tools that LLMs can call.
|
||||||
|
|
||||||
|
Try it out: [https://bitview.space/mcp](https://bitview.space/mcp)
|
||||||
|
|
||||||
## What it provides
|
## What it provides
|
||||||
|
|
||||||
- **MCP Server Implementation**: Standards-compliant Model Context Protocol server
|
- **MCP Server Implementation**: Standards-compliant Model Context Protocol server
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
- **Sequential block access**: Blocks delivered in height order (0, 1, 2, ...) regardless of physical file storage
|
- **Sequential block access**: Blocks delivered in height order (0, 1, 2, ...) regardless of physical file storage
|
||||||
- **Fork filtering**: Automatically excludes orphaned blocks using Bitcoin Core RPC verification
|
- **Fork filtering**: Automatically excludes orphaned blocks using Bitcoin Core RPC verification
|
||||||
- **XOR encryption support**: Transparently handles XOR-encrypted block files
|
- **XOR encryption support**: Transparently handles XOR-encrypted block files
|
||||||
- **High performance**: Multi-threaded parsing with ~500MB peak memory usage
|
- **High performance**: Multi-threaded parsing with ~500MB peak memory usage
|
||||||
- **State persistence**: Caches parsing state for fast restarts
|
- **State persistence**: Caches parsing state for fast restarts
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ let rpc = Box::leak(Box::new(Client::new(
|
|||||||
// Create parser
|
// Create parser
|
||||||
let parser = Parser::new(
|
let parser = Parser::new(
|
||||||
Path::new("~/.bitcoin/blocks").to_path_buf(),
|
Path::new("~/.bitcoin/blocks").to_path_buf(),
|
||||||
Path::new("./output").to_path_buf(),
|
Some(Path::new("./output").to_path_buf()),
|
||||||
rpc,
|
rpc,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ use bitcoin::Block;
|
|||||||
fn analyze_blockchain(parser: &Parser) {
|
fn analyze_blockchain(parser: &Parser) {
|
||||||
let mut total_transactions = 0;
|
let mut total_transactions = 0;
|
||||||
let mut total_outputs = 0;
|
let mut total_outputs = 0;
|
||||||
|
|
||||||
parser.parse(None, None)
|
parser.parse(None, None)
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|(height, block, _hash)| {
|
.for_each(|(height, block, _hash)| {
|
||||||
@@ -98,12 +98,12 @@ fn analyze_blockchain(parser: &Parser) {
|
|||||||
total_outputs += block.txdata.iter()
|
total_outputs += block.txdata.iter()
|
||||||
.map(|tx| tx.output.len())
|
.map(|tx| tx.output.len())
|
||||||
.sum::<usize>();
|
.sum::<usize>();
|
||||||
|
|
||||||
if height.0 % 10000 == 0 {
|
if height.0 % 10000 == 0 {
|
||||||
println!("Processed {} blocks", height);
|
println!("Processed {} blocks", height);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("Total transactions: {}", total_transactions);
|
println!("Total transactions: {}", total_transactions);
|
||||||
println!("Total outputs: {}", total_outputs);
|
println!("Total outputs: {}", total_outputs);
|
||||||
}
|
}
|
||||||
@@ -150,4 +150,4 @@ The parser saves parsing state in `{output_dir}/blk_index_to_blk_recap.json` con
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*This README was generated by Claude Code*
|
*This README was generated by Claude Code*
|
||||||
|
|||||||
@@ -1,60 +1,46 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use bitcoincore_rpc::{Auth, Client, Result};
|
use bitcoincore_rpc::{Auth, Client, Result};
|
||||||
use brk_parser::Parser;
|
use brk_parser::{BlockExtended, Parser};
|
||||||
use brk_structs::Height;
|
use brk_structs::Height;
|
||||||
|
|
||||||
#[allow(clippy::needless_doctest_main)]
|
#[allow(clippy::needless_doctest_main)]
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let i = std::time::Instant::now();
|
let i = std::time::Instant::now();
|
||||||
|
|
||||||
let bitcoin_dir = Path::new("").join("");
|
let bitcoin_dir = Path::new(&std::env::var("HOME").unwrap())
|
||||||
let brk_dir = Path::new("").join("");
|
.join("Library")
|
||||||
|
.join("Application Support")
|
||||||
|
.join("Bitcoin");
|
||||||
|
let brk_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
|
||||||
|
|
||||||
let rpc = Box::leak(Box::new(Client::new(
|
let rpc = Box::leak(Box::new(Client::new(
|
||||||
"http://localhost:8332",
|
"http://localhost:8332",
|
||||||
Auth::CookieFile(bitcoin_dir.join(".cookie")),
|
Auth::CookieFile(bitcoin_dir.join(".cookie")),
|
||||||
)?));
|
)?));
|
||||||
|
|
||||||
let start = None;
|
let parser = Parser::new(bitcoin_dir.join("blocks"), Some(brk_dir), rpc);
|
||||||
let end = None;
|
|
||||||
|
|
||||||
let parser = Parser::new(bitcoin_dir.join("blocks"), brk_dir, rpc);
|
// let start = None;
|
||||||
|
// let end = None;
|
||||||
parser
|
// parser
|
||||||
.parse(start, end)
|
// .parse(start, end)
|
||||||
.iter()
|
// .iter()
|
||||||
.for_each(|(height, _block, hash)| {
|
// .for_each(|(height, _block, hash)| {
|
||||||
println!("{height}: {hash}");
|
// println!("{height}: {}", hash);
|
||||||
});
|
// });
|
||||||
|
|
||||||
let block_0 = parser.get(Height::new(0));
|
let block_0 = parser.get(Height::new(0));
|
||||||
|
dbg!("{}", block_0.coinbase_tag());
|
||||||
|
|
||||||
println!(
|
let block_158251 = parser.get(Height::new(158251));
|
||||||
"{}",
|
dbg!("{}", block_158251.coinbase_tag());
|
||||||
block_0
|
|
||||||
.txdata
|
|
||||||
.first()
|
|
||||||
.unwrap()
|
|
||||||
.output
|
|
||||||
.first()
|
|
||||||
.unwrap()
|
|
||||||
.script_pubkey
|
|
||||||
);
|
|
||||||
|
|
||||||
let block_840_000 = parser.get(Height::new(840_000));
|
let block_173195 = parser.get(Height::new(173195));
|
||||||
|
dbg!("{}", block_173195.coinbase_tag());
|
||||||
|
|
||||||
println!(
|
let block_840_000 = parser.get(Height::new(840_004));
|
||||||
"{}",
|
dbg!("{}", block_840_000.coinbase_tag());
|
||||||
block_840_000
|
|
||||||
.txdata
|
|
||||||
.first()
|
|
||||||
.unwrap()
|
|
||||||
.output
|
|
||||||
.first()
|
|
||||||
.unwrap()
|
|
||||||
.value
|
|
||||||
);
|
|
||||||
|
|
||||||
dbg!(i.elapsed());
|
dbg!(i.elapsed());
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ fn main() {
|
|||||||
// let start = None;
|
// let start = None;
|
||||||
// let end = None;
|
// let end = None;
|
||||||
|
|
||||||
let parser = Parser::new(bitcoin_dir.join("blocks"), brk_dir, rpc);
|
let parser = Parser::new(bitcoin_dir.join("blocks"), Some(brk_dir), rpc);
|
||||||
|
|
||||||
// parser
|
// parser
|
||||||
// .parse(start, end)
|
// .parse(start, end)
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use bitcoin::Block;
|
||||||
|
|
||||||
|
pub trait BlockExtended {
|
||||||
|
fn coinbase_tag(&self) -> Cow<'_, str>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockExtended for Block {
|
||||||
|
fn coinbase_tag(&self) -> Cow<'_, str> {
|
||||||
|
String::from_utf8_lossy(
|
||||||
|
self.txdata
|
||||||
|
.first()
|
||||||
|
.and_then(|tx| tx.input.first())
|
||||||
|
.unwrap()
|
||||||
|
.script_sig
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ mod blk_index_to_blk_path;
|
|||||||
mod blk_index_to_blk_recap;
|
mod blk_index_to_blk_recap;
|
||||||
mod blk_metadata;
|
mod blk_metadata;
|
||||||
mod blk_recap;
|
mod blk_recap;
|
||||||
|
mod block;
|
||||||
mod block_state;
|
mod block_state;
|
||||||
mod error;
|
mod error;
|
||||||
mod utils;
|
mod utils;
|
||||||
@@ -22,6 +23,7 @@ mod xor_index;
|
|||||||
|
|
||||||
use blk_index_to_blk_recap::*;
|
use blk_index_to_blk_recap::*;
|
||||||
use blk_metadata::*;
|
use blk_metadata::*;
|
||||||
|
pub use block::*;
|
||||||
use block_state::*;
|
use block_state::*;
|
||||||
pub use error::*;
|
pub use error::*;
|
||||||
use utils::*;
|
use utils::*;
|
||||||
@@ -35,14 +37,14 @@ const BOUND_CAP: usize = 50;
|
|||||||
|
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
blocks_dir: PathBuf,
|
blocks_dir: PathBuf,
|
||||||
outputs_dir: PathBuf,
|
outputs_dir: Option<PathBuf>,
|
||||||
rpc: &'static bitcoincore_rpc::Client,
|
rpc: &'static bitcoincore_rpc::Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parser {
|
impl Parser {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
blocks_dir: PathBuf,
|
blocks_dir: PathBuf,
|
||||||
outputs_dir: PathBuf,
|
outputs_dir: Option<PathBuf>,
|
||||||
rpc: &'static bitcoincore_rpc::Client,
|
rpc: &'static bitcoincore_rpc::Client,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -79,8 +81,11 @@ impl Parser {
|
|||||||
|
|
||||||
let blk_index_to_blk_path = BlkIndexToBlkPath::scan(blocks_dir);
|
let blk_index_to_blk_path = BlkIndexToBlkPath::scan(blocks_dir);
|
||||||
|
|
||||||
let (mut blk_index_to_blk_recap, blk_index) =
|
let (mut blk_index_to_blk_recap, blk_index) = BlkIndexToBlkRecap::import(
|
||||||
BlkIndexToBlkRecap::import(&self.outputs_dir, &blk_index_to_blk_path, start);
|
self.outputs_dir.as_ref().unwrap(),
|
||||||
|
&blk_index_to_blk_path,
|
||||||
|
start,
|
||||||
|
);
|
||||||
|
|
||||||
let xor_bytes = XORBytes::from(blocks_dir);
|
let xor_bytes = XORBytes::from(blocks_dir);
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ brk_parser = { workspace = true }
|
|||||||
vecdb = { workspace = true }
|
vecdb = { workspace = true }
|
||||||
jiff = { workspace = true }
|
jiff = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
quick_cache = "0.6.16"
|
quick_cache = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
tower-http = { version = "0.6.6", features = ["compression-full", "trace"] }
|
tower-http = { version = "0.6.6", features = ["compression-full", "trace"] }
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
`brk_server` provides a high-performance HTTP server that exposes BRK's indexed blockchain data and computed analytics through a comprehensive REST API. It offers multiple output formats, intelligent caching, compression, and optional web interface serving.
|
`brk_server` provides a high-performance HTTP server that exposes BRK's indexed blockchain data and computed analytics through a comprehensive REST API. It offers multiple output formats, intelligent caching, compression, and optional web interface serving.
|
||||||
|
|
||||||
|
URL: [`https://bitview.space/api`](https://bitview.space/api)
|
||||||
|
|
||||||
## What it provides
|
## What it provides
|
||||||
|
|
||||||
- **REST API**: Vector-based data access with flexible querying and pagination
|
- **REST API**: Vector-based data access with flexible querying and pagination
|
||||||
@@ -60,26 +62,26 @@ server.serve(true).await?;
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Latest 100 price values
|
# Latest 100 price values
|
||||||
curl "http://brekit.org/api/vecs/date-to-close?from=-100"
|
curl "https://bitview.space/api/vecs/date-to-close?from=-100"
|
||||||
|
|
||||||
# First 50 difficulty values as CSV
|
# First 50 difficulty values as CSV
|
||||||
curl "http://brekit.org/api/vecs/height-to-difficulty?count=50&format=csv"
|
curl "https://bitview.space/api/vecs/height-to-difficulty?count=50&format=csv"
|
||||||
|
|
||||||
# Range from block 800,000 to 800,100
|
# Range from block 800,000 to 800,100
|
||||||
curl "https://brekit.org/api/vecs/height-to-timestamp?from=800000&to=800100"
|
curl "https://bitview.space/api/vecs/height-to-timestamp?from=800000&to=800100"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Multi-Vector Queries
|
#### Multi-Vector Queries
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Multiple price metrics for last 30 days
|
# Multiple price metrics for last 30 days
|
||||||
curl "http://brekit.org/api/vecs/query?index=date&ids=open,high,low,close&from=-30&format=csv"
|
curl "https://bitview.space/api/vecs/query?index=date&ids=open,high,low,close&from=-30&format=csv"
|
||||||
|
|
||||||
# Block statistics for specific range
|
# Block statistics for specific range
|
||||||
curl "https://brekit.org/api/vecs/query?index=height&ids=size,weight,tx_count,fee_sum&from=800000&count=100"
|
curl "https://bitview.space/api/vecs/query?index=height&ids=size,weight,tx_count,fee_sum&from=800000&count=100"
|
||||||
|
|
||||||
# Weekly analytics as JSON matrix
|
# Weekly analytics as JSON matrix
|
||||||
curl "https://brekit.org/api/vecs/query?index=week&ids=close,difficulty&from=-52"
|
curl "https://bitview.space/api/vecs/query?index=week&ids=close,difficulty&from=-52"
|
||||||
```
|
```
|
||||||
|
|
||||||
## API Reference
|
## API Reference
|
||||||
@@ -145,7 +147,7 @@ curl "/api/vecs/month-to-supply"
|
|||||||
|
|
||||||
**CSV Format**:
|
**CSV Format**:
|
||||||
```csv
|
```csv
|
||||||
index,close,supply,feerate
|
index,close,supply,fee_rate
|
||||||
0,42.5,1500,0.05
|
0,42.5,1500,0.05
|
||||||
1,43.1,1520,0.052
|
1,43.1,1520,0.052
|
||||||
2,44.2,1480,0.048
|
2,44.2,1480,0.048
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ pub fn main() -> Result<()> {
|
|||||||
let exit = Exit::new();
|
let exit = Exit::new();
|
||||||
exit.set_ctrlc_handler();
|
exit.set_ctrlc_handler();
|
||||||
|
|
||||||
let parser = Parser::new(bitcoin_dir.join("blocks"), brk_dir.to_path_buf(), rpc);
|
let parser = Parser::new(bitcoin_dir.join("blocks"), Some(brk_dir.to_path_buf()), rpc);
|
||||||
|
|
||||||
let outputs_dir = Path::new("../../_outputs");
|
let outputs_dir = Path::new("../../_outputs");
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use crate::{HeaderMapExtended, ResponseExtended};
|
|||||||
|
|
||||||
use super::AppState;
|
use super::AppState;
|
||||||
|
|
||||||
const MAX_WEIGHT: usize = 320_000;
|
const MAX_WEIGHT: usize = 65 * 10_000;
|
||||||
|
|
||||||
pub async fn handler(
|
pub async fn handler(
|
||||||
uri: Uri,
|
uri: Uri,
|
||||||
@@ -43,7 +43,7 @@ fn req_to_response_res(
|
|||||||
interface, cache, ..
|
interface, cache, ..
|
||||||
}: AppState,
|
}: AppState,
|
||||||
) -> Result<Response> {
|
) -> Result<Response> {
|
||||||
let vecs = interface.search(¶ms);
|
let vecs = interface.search(¶ms)?;
|
||||||
|
|
||||||
if vecs.is_empty() {
|
if vecs.is_empty() {
|
||||||
return Ok(Json(vec![] as Vec<usize>).into_response());
|
return Ok(Json(vec![] as Vec<usize>).into_response());
|
||||||
@@ -61,9 +61,9 @@ fn req_to_response_res(
|
|||||||
.sum::<usize>();
|
.sum::<usize>();
|
||||||
|
|
||||||
if weight > MAX_WEIGHT {
|
if weight > MAX_WEIGHT {
|
||||||
return Err(Error::Str(
|
return Err(Error::String(format!(
|
||||||
"Request is too heavy, max weight is {MAX_WEIGHT} bytes",
|
"Request is too heavy, max weight is {MAX_WEIGHT} bytes"
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: height should be from vec, but good enough for now
|
// TODO: height should be from vec, but good enough for now
|
||||||
|
|||||||
@@ -106,16 +106,6 @@ impl ApiRoutes for Router<AppState> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.route(
|
|
||||||
"/health",
|
|
||||||
get(|| async {
|
|
||||||
Json(serde_json::json!({
|
|
||||||
"status": "healthy",
|
|
||||||
"service": "brk-server",
|
|
||||||
"timestamp": jiff::Timestamp::now().to_string()
|
|
||||||
}))
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.route(
|
.route(
|
||||||
"/api",
|
"/api",
|
||||||
get(|| async {
|
get(|| async {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use axum::{
|
|||||||
body::{Body, Bytes},
|
body::{Body, Bytes},
|
||||||
http::{Request, Response, StatusCode, Uri},
|
http::{Request, Response, StatusCode, Uri},
|
||||||
middleware::Next,
|
middleware::Next,
|
||||||
|
response::Redirect,
|
||||||
routing::get,
|
routing::get,
|
||||||
serve,
|
serve,
|
||||||
};
|
};
|
||||||
@@ -47,7 +48,7 @@ impl Server {
|
|||||||
Self(AppState {
|
Self(AppState {
|
||||||
interface: Box::leak(Box::new(interface)),
|
interface: Box::leak(Box::new(interface)),
|
||||||
path: files_path,
|
path: files_path,
|
||||||
cache: Arc::new(Cache::new(10_000)),
|
cache: Arc::new(Cache::new(5_000)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +99,33 @@ impl Server {
|
|||||||
.add_files_routes(state.path.as_ref())
|
.add_files_routes(state.path.as_ref())
|
||||||
.add_mcp_routes(state.interface, mcp)
|
.add_mcp_routes(state.interface, mcp)
|
||||||
.route("/version", get(Json(VERSION)))
|
.route("/version", get(Json(VERSION)))
|
||||||
|
.route(
|
||||||
|
"/health",
|
||||||
|
get(Json(serde_json::json!({
|
||||||
|
"status": "healthy",
|
||||||
|
"service": "brk-server",
|
||||||
|
"timestamp": jiff::Timestamp::now().to_string()
|
||||||
|
}))),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/discord",
|
||||||
|
get(Redirect::temporary("https://discord.gg/WACpShCB7M")),
|
||||||
|
)
|
||||||
|
.route("/crates", get(Redirect::temporary("https://crates.io/crates/brk")))
|
||||||
|
.route(
|
||||||
|
"/status",
|
||||||
|
get(Redirect::temporary("https://status.bitview.space")),
|
||||||
|
)
|
||||||
|
.route("/github", get(Redirect::temporary("https://github.com/bitcoinresearchkit/brk")))
|
||||||
|
.route(
|
||||||
|
"/cli",
|
||||||
|
get(Redirect::temporary("https://crates.io/crates/brk_cli")),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/hosting",
|
||||||
|
get(Redirect::temporary("https://github.com/bitcoinresearchkit/brk?tab=readme-ov-file#hosting-as-a-service")),
|
||||||
|
)
|
||||||
|
.route("/nostr", get(Redirect::temporary("https://primal.net/p/npub1jagmm3x39lmwfnrtvxcs9ac7g300y3dusv9lgzhk2e4x5frpxlrqa73v44")))
|
||||||
.with_state(state)
|
.with_state(state)
|
||||||
.layer(compression_layer)
|
.layer(compression_layer)
|
||||||
.layer(response_uri_layer)
|
.layer(response_uri_layer)
|
||||||
|
|||||||
@@ -3,18 +3,11 @@ use brk_structs::{Height, Version};
|
|||||||
|
|
||||||
pub trait AnyStore {
|
pub trait AnyStore {
|
||||||
fn commit(&mut self, height: Height) -> Result<()>;
|
fn commit(&mut self, height: Height) -> Result<()>;
|
||||||
|
|
||||||
fn persist(&self) -> Result<()>;
|
fn persist(&self) -> Result<()>;
|
||||||
|
|
||||||
fn reset(&mut self) -> Result<()>;
|
fn reset(&mut self) -> Result<()>;
|
||||||
|
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
|
||||||
fn height(&self) -> Option<Height>;
|
fn height(&self) -> Option<Height>;
|
||||||
|
|
||||||
fn has(&self, height: Height) -> bool;
|
fn has(&self, height: Height) -> bool;
|
||||||
|
|
||||||
fn needs(&self, height: Height) -> bool;
|
fn needs(&self, height: Height) -> bool;
|
||||||
|
|
||||||
fn version(&self) -> Version;
|
fn version(&self) -> Version;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,12 +126,12 @@ where
|
|||||||
// .map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v)))))
|
// .map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v)))))
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// pub fn tx_iter(&self) -> impl Iterator<Item = (K, V)> {
|
pub fn iter(&self) -> impl Iterator<Item = (K, V)> {
|
||||||
// self.rtx
|
self.rtx
|
||||||
// .iter(&self.partition.load())
|
.iter(self.partition.as_ref().unwrap())
|
||||||
// .map(|res| res.unwrap())
|
.map(|res| res.unwrap())
|
||||||
// .map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v))))
|
.map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v))))
|
||||||
// }
|
}
|
||||||
|
|
||||||
pub fn insert_if_needed(&mut self, key: K, value: V, height: Height) {
|
pub fn insert_if_needed(&mut self, key: K, value: V, height: Height) {
|
||||||
if self.needs(height) {
|
if self.needs(height) {
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ rust-version.workspace = true
|
|||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
allocative = { workspace = true }
|
||||||
|
allocative_derive = { workspace = true }
|
||||||
bitcoin = { workspace = true }
|
bitcoin = { workspace = true }
|
||||||
bitcoincore-rpc = { workspace = true }
|
bitcoincore-rpc = { workspace = true }
|
||||||
brk_error = {workspace = true}
|
brk_error = {workspace = true}
|
||||||
@@ -17,7 +19,7 @@ vecdb = {workspace = true}
|
|||||||
byteview = { workspace = true }
|
byteview = { workspace = true }
|
||||||
derive_deref = { workspace = true }
|
derive_deref = { workspace = true }
|
||||||
jiff = { workspace = true }
|
jiff = { workspace = true }
|
||||||
rapidhash = "3.1.0"
|
rapidhash = "4.0.0"
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_bytes = { workspace = true }
|
serde_bytes = { workspace = true }
|
||||||
zerocopy = { workspace = true }
|
zerocopy = { workspace = true }
|
||||||
|
|||||||
@@ -25,6 +25,25 @@ pub enum AddressBytes {
|
|||||||
P2A(P2ABytes),
|
P2A(P2ABytes),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for AddressBytes {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match self {
|
||||||
|
AddressBytes::P2PK65(bytes) => bytes.to_string(),
|
||||||
|
AddressBytes::P2PK33(bytes) => bytes.to_string(),
|
||||||
|
AddressBytes::P2PKH(bytes) => bytes.to_string(),
|
||||||
|
AddressBytes::P2SH(bytes) => bytes.to_string(),
|
||||||
|
AddressBytes::P2WPKH(bytes) => bytes.to_string(),
|
||||||
|
AddressBytes::P2WSH(bytes) => bytes.to_string(),
|
||||||
|
AddressBytes::P2TR(bytes) => bytes.to_string(),
|
||||||
|
AddressBytes::P2A(bytes) => bytes.to_string(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AddressBytes {
|
impl AddressBytes {
|
||||||
pub fn as_slice(&self) -> &[u8] {
|
pub fn as_slice(&self) -> &[u8] {
|
||||||
match self {
|
match self {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ impl Serialize for AnyAddressIndex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum AnyAddressDataIndexEnum {
|
pub enum AnyAddressDataIndexEnum {
|
||||||
Loaded(LoadedAddressIndex),
|
Loaded(LoadedAddressIndex),
|
||||||
Empty(EmptyAddressIndex),
|
Empty(EmptyAddressIndex),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use std::{
|
|||||||
ops::{Add, AddAssign, Div, Mul},
|
ops::{Add, AddAssign, Div, Mul},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use allocative::Allocative;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use vecdb::{CheckedSub, StoredCompressed};
|
use vecdb::{CheckedSub, StoredCompressed};
|
||||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||||
@@ -20,6 +21,7 @@ use super::{Sats, StoredF64};
|
|||||||
KnownLayout,
|
KnownLayout,
|
||||||
Serialize,
|
Serialize,
|
||||||
StoredCompressed,
|
StoredCompressed,
|
||||||
|
Allocative,
|
||||||
)]
|
)]
|
||||||
pub struct Bitcoin(f64);
|
pub struct Bitcoin(f64);
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ impl Date {
|
|||||||
pub fn into_jiff(self) -> Date_ {
|
pub fn into_jiff(self) -> Date_ {
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn today() -> Self {
|
||||||
|
Self::from(Timestamp::now())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Date {
|
impl Default for Date {
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ use std::{
|
|||||||
ops::{Add, Rem},
|
ops::{Add, Rem},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use allocative::Allocative;
|
||||||
use brk_error::Error;
|
use brk_error::Error;
|
||||||
use vecdb::{CheckedSub, FromCoarserIndex, Printable, StoredCompressed};
|
|
||||||
use jiff::Span;
|
use jiff::Span;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use vecdb::{CheckedSub, FromCoarserIndex, Printable, StoredCompressed};
|
||||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||||
|
|
||||||
use crate::{DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, WeekIndex, YearIndex};
|
use crate::{DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, WeekIndex, YearIndex};
|
||||||
@@ -28,6 +29,7 @@ use super::Date;
|
|||||||
KnownLayout,
|
KnownLayout,
|
||||||
Serialize,
|
Serialize,
|
||||||
StoredCompressed,
|
StoredCompressed,
|
||||||
|
Allocative,
|
||||||
)]
|
)]
|
||||||
pub struct DateIndex(u16);
|
pub struct DateIndex(u16);
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ use std::{
|
|||||||
ops::{Add, AddAssign, Div},
|
ops::{Add, AddAssign, Div},
|
||||||
};
|
};
|
||||||
|
|
||||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
use allocative::Allocative;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||||
|
|
||||||
use super::{Date, DateIndex, YearIndex};
|
use super::{Date, DateIndex, YearIndex};
|
||||||
@@ -25,6 +26,7 @@ use super::{Date, DateIndex, YearIndex};
|
|||||||
IntoBytes,
|
IntoBytes,
|
||||||
KnownLayout,
|
KnownLayout,
|
||||||
StoredCompressed,
|
StoredCompressed,
|
||||||
|
Allocative,
|
||||||
)]
|
)]
|
||||||
pub struct DecadeIndex(u16);
|
pub struct DecadeIndex(u16);
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use std::{
|
|||||||
ops::{Add, AddAssign, Div},
|
ops::{Add, AddAssign, Div},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use allocative::Allocative;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||||
@@ -25,6 +26,7 @@ use super::Height;
|
|||||||
IntoBytes,
|
IntoBytes,
|
||||||
KnownLayout,
|
KnownLayout,
|
||||||
StoredCompressed,
|
StoredCompressed,
|
||||||
|
Allocative,
|
||||||
)]
|
)]
|
||||||
pub struct DifficultyEpoch(u16);
|
pub struct DifficultyEpoch(u16);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use std::{
|
|||||||
ops::{Add, AddAssign, Div, Mul},
|
ops::{Add, AddAssign, Div, Mul},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use allocative::Allocative;
|
||||||
use derive_deref::Deref;
|
use derive_deref::Deref;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use vecdb::{CheckedSub, StoredCompressed};
|
use vecdb::{CheckedSub, StoredCompressed};
|
||||||
@@ -24,6 +25,7 @@ use super::{Bitcoin, Cents, Close, High, Sats, StoredF32, StoredF64};
|
|||||||
Serialize,
|
Serialize,
|
||||||
Deserialize,
|
Deserialize,
|
||||||
StoredCompressed,
|
StoredCompressed,
|
||||||
|
Allocative,
|
||||||
)]
|
)]
|
||||||
pub struct Dollars(f64);
|
pub struct Dollars(f64);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
|
||||||
use vecdb::{CheckedSub, Printable};
|
|
||||||
use derive_deref::Deref;
|
use derive_deref::Deref;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||||
|
|
||||||
use crate::TypeIndex;
|
use crate::TypeIndex;
|
||||||
@@ -22,6 +22,7 @@ use crate::TypeIndex;
|
|||||||
IntoBytes,
|
IntoBytes,
|
||||||
KnownLayout,
|
KnownLayout,
|
||||||
Serialize,
|
Serialize,
|
||||||
|
StoredCompressed,
|
||||||
)]
|
)]
|
||||||
pub struct EmptyAddressIndex(TypeIndex);
|
pub struct EmptyAddressIndex(TypeIndex);
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use std::{
|
|||||||
ops::{Add, AddAssign, Div},
|
ops::{Add, AddAssign, Div},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use allocative::Allocative;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use vecdb::StoredCompressed;
|
use vecdb::StoredCompressed;
|
||||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||||
@@ -10,11 +11,20 @@ use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
|||||||
use super::{Sats, StoredU64};
|
use super::{Sats, StoredU64};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug, Clone, Copy, Serialize, FromBytes, Immutable, IntoBytes, KnownLayout, StoredCompressed,
|
Debug,
|
||||||
|
Clone,
|
||||||
|
Copy,
|
||||||
|
Serialize,
|
||||||
|
FromBytes,
|
||||||
|
Immutable,
|
||||||
|
IntoBytes,
|
||||||
|
KnownLayout,
|
||||||
|
StoredCompressed,
|
||||||
|
Allocative,
|
||||||
)]
|
)]
|
||||||
pub struct Feerate(f64);
|
pub struct FeeRate(f64);
|
||||||
|
|
||||||
impl From<(Sats, StoredU64)> for Feerate {
|
impl From<(Sats, StoredU64)> for FeeRate {
|
||||||
fn from((sats, vsize): (Sats, StoredU64)) -> Self {
|
fn from((sats, vsize): (Sats, StoredU64)) -> Self {
|
||||||
let sats = u64::from(sats);
|
let sats = u64::from(sats);
|
||||||
let vsize = u64::from(vsize);
|
let vsize = u64::from(vsize);
|
||||||
@@ -22,44 +32,44 @@ impl From<(Sats, StoredU64)> for Feerate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<f64> for Feerate {
|
impl From<f64> for FeeRate {
|
||||||
fn from(value: f64) -> Self {
|
fn from(value: f64) -> Self {
|
||||||
Self(value)
|
Self(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<Feerate> for f64 {
|
impl From<FeeRate> for f64 {
|
||||||
fn from(value: Feerate) -> Self {
|
fn from(value: FeeRate) -> Self {
|
||||||
value.0
|
value.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add for Feerate {
|
impl Add for FeeRate {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn add(self, rhs: Self) -> Self::Output {
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
Self(self.0 + rhs.0)
|
Self(self.0 + rhs.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddAssign for Feerate {
|
impl AddAssign for FeeRate {
|
||||||
fn add_assign(&mut self, rhs: Self) {
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
*self = *self + rhs
|
*self = *self + rhs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Div<usize> for Feerate {
|
impl Div<usize> for FeeRate {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn div(self, rhs: usize) -> Self::Output {
|
fn div(self, rhs: usize) -> Self::Output {
|
||||||
Self(self.0 / rhs as f64)
|
Self(self.0 / rhs as f64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<usize> for Feerate {
|
impl From<usize> for FeeRate {
|
||||||
fn from(value: usize) -> Self {
|
fn from(value: usize) -> Self {
|
||||||
Self(value as f64)
|
Self(value as f64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Feerate {
|
impl PartialEq for FeeRate {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
match (self.0.is_nan(), other.0.is_nan()) {
|
match (self.0.is_nan(), other.0.is_nan()) {
|
||||||
(true, true) => true,
|
(true, true) => true,
|
||||||
@@ -70,17 +80,17 @@ impl PartialEq for Feerate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for Feerate {}
|
impl Eq for FeeRate {}
|
||||||
|
|
||||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||||
impl PartialOrd for Feerate {
|
impl PartialOrd for FeeRate {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
Some(self.cmp(other))
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||||
impl Ord for Feerate {
|
impl Ord for FeeRate {
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
match (self.0.is_nan(), other.0.is_nan()) {
|
match (self.0.is_nan(), other.0.is_nan()) {
|
||||||
(true, true) => Ordering::Equal,
|
(true, true) => Ordering::Equal,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use std::{
|
|||||||
ops::{Add, AddAssign, Div},
|
ops::{Add, AddAssign, Div},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use allocative::Allocative;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||||
@@ -25,6 +26,7 @@ use super::Height;
|
|||||||
IntoBytes,
|
IntoBytes,
|
||||||
KnownLayout,
|
KnownLayout,
|
||||||
StoredCompressed,
|
StoredCompressed,
|
||||||
|
Allocative,
|
||||||
)]
|
)]
|
||||||
pub struct HalvingEpoch(u16);
|
pub struct HalvingEpoch(u16);
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use std::{
|
|||||||
ops::{Add, AddAssign, Rem},
|
ops::{Add, AddAssign, Rem},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use allocative::Allocative;
|
||||||
use bitcoincore_rpc::{Client, RpcApi};
|
use bitcoincore_rpc::{Client, RpcApi};
|
||||||
use byteview::ByteView;
|
use byteview::ByteView;
|
||||||
use derive_deref::Deref;
|
use derive_deref::Deref;
|
||||||
@@ -32,6 +33,7 @@ use super::StoredU64;
|
|||||||
IntoBytes,
|
IntoBytes,
|
||||||
KnownLayout,
|
KnownLayout,
|
||||||
StoredCompressed,
|
StoredCompressed,
|
||||||
|
Allocative,
|
||||||
)]
|
)]
|
||||||
pub struct Height(u32);
|
pub struct Height(u32);
|
||||||
|
|
||||||
@@ -227,13 +229,19 @@ impl TryFrom<&std::path::Path> for Height {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<ByteView> for Height {
|
impl From<ByteView> for Height {
|
||||||
fn from(value: byteview::ByteView) -> Self {
|
fn from(value: ByteView) -> Self {
|
||||||
Self(u32::from_be_bytes(copy_first_4bytes(&value).unwrap()))
|
Self(u32::from_be_bytes(copy_first_4bytes(&value).unwrap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Height> for ByteView {
|
impl From<Height> for ByteView {
|
||||||
fn from(value: Height) -> Self {
|
fn from(value: Height) -> Self {
|
||||||
|
Self::from(&value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Height> for ByteView {
|
||||||
|
fn from(value: &Height) -> Self {
|
||||||
Self::new(&value.0.to_be_bytes())
|
Self::new(&value.0.to_be_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::ops::{Add, AddAssign};
|
use std::ops::{Add, AddAssign};
|
||||||
|
|
||||||
|
use allocative::Allocative;
|
||||||
use derive_deref::{Deref, DerefMut};
|
use derive_deref::{Deref, DerefMut};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||||
@@ -24,6 +25,7 @@ use super::Vin;
|
|||||||
KnownLayout,
|
KnownLayout,
|
||||||
Serialize,
|
Serialize,
|
||||||
StoredCompressed,
|
StoredCompressed,
|
||||||
|
Allocative,
|
||||||
)]
|
)]
|
||||||
pub struct InputIndex(u64);
|
pub struct InputIndex(u64);
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ pub struct LoadedAddressData {
|
|||||||
pub sent: Sats,
|
pub sent: Sats,
|
||||||
pub received: Sats,
|
pub received: Sats,
|
||||||
pub realized_cap: Dollars,
|
pub realized_cap: Dollars,
|
||||||
pub outputs_len: u32,
|
pub utxos: u32,
|
||||||
|
#[serde(skip)]
|
||||||
padding: u32,
|
padding: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,12 +42,12 @@ impl LoadedAddressData {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn has_0_utxos(&self) -> bool {
|
pub fn has_0_utxos(&self) -> bool {
|
||||||
self.outputs_len == 0
|
self.utxos == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn receive(&mut self, amount: Sats, price: Option<Dollars>) {
|
pub fn receive(&mut self, amount: Sats, price: Option<Dollars>) {
|
||||||
self.received += amount;
|
self.received += amount;
|
||||||
self.outputs_len += 1;
|
self.utxos += 1;
|
||||||
if let Some(price) = price {
|
if let Some(price) = price {
|
||||||
let added = price * amount;
|
let added = price * amount;
|
||||||
self.realized_cap += added;
|
self.realized_cap += added;
|
||||||
@@ -62,7 +63,7 @@ impl LoadedAddressData {
|
|||||||
return Err(Error::Str("Previous_amount smaller than sent amount"));
|
return Err(Error::Str("Previous_amount smaller than sent amount"));
|
||||||
}
|
}
|
||||||
self.sent += amount;
|
self.sent += amount;
|
||||||
self.outputs_len -= 1;
|
self.utxos -= 1;
|
||||||
if let Some(previous_price) = previous_price {
|
if let Some(previous_price) = previous_price {
|
||||||
let subtracted = previous_price * amount;
|
let subtracted = previous_price * amount;
|
||||||
let realized_cap = self.realized_cap.checked_sub(subtracted).unwrap();
|
let realized_cap = self.realized_cap.checked_sub(subtracted).unwrap();
|
||||||
@@ -94,7 +95,7 @@ impl From<&EmptyAddressData> for LoadedAddressData {
|
|||||||
sent: value.transfered,
|
sent: value.transfered,
|
||||||
received: value.transfered,
|
received: value.transfered,
|
||||||
realized_cap: Dollars::ZERO,
|
realized_cap: Dollars::ZERO,
|
||||||
outputs_len: 0,
|
utxos: 0,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::ops::Add;
|
|||||||
|
|
||||||
use derive_deref::Deref;
|
use derive_deref::Deref;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use vecdb::{CheckedSub, Printable};
|
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||||
|
|
||||||
use crate::TypeIndex;
|
use crate::TypeIndex;
|
||||||
@@ -22,6 +22,7 @@ use crate::TypeIndex;
|
|||||||
IntoBytes,
|
IntoBytes,
|
||||||
KnownLayout,
|
KnownLayout,
|
||||||
Serialize,
|
Serialize,
|
||||||
|
StoredCompressed,
|
||||||
)]
|
)]
|
||||||
pub struct LoadedAddressIndex(TypeIndex);
|
pub struct LoadedAddressIndex(TypeIndex);
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ mod stored_bool;
|
|||||||
mod stored_f32;
|
mod stored_f32;
|
||||||
mod stored_f64;
|
mod stored_f64;
|
||||||
mod stored_i16;
|
mod stored_i16;
|
||||||
|
mod stored_string;
|
||||||
mod stored_u16;
|
mod stored_u16;
|
||||||
mod stored_u32;
|
mod stored_u32;
|
||||||
mod stored_u64;
|
mod stored_u64;
|
||||||
@@ -105,6 +106,7 @@ pub use stored_bool::*;
|
|||||||
pub use stored_f32::*;
|
pub use stored_f32::*;
|
||||||
pub use stored_f64::*;
|
pub use stored_f64::*;
|
||||||
pub use stored_i16::*;
|
pub use stored_i16::*;
|
||||||
|
pub use stored_string::*;
|
||||||
pub use stored_u8::*;
|
pub use stored_u8::*;
|
||||||
pub use stored_u16::*;
|
pub use stored_u16::*;
|
||||||
pub use stored_u32::*;
|
pub use stored_u32::*;
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ use std::{
|
|||||||
ops::{Add, AddAssign, Div},
|
ops::{Add, AddAssign, Div},
|
||||||
};
|
};
|
||||||
|
|
||||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
use allocative::Allocative;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||||
|
|
||||||
use super::{Date, DateIndex, YearIndex};
|
use super::{Date, DateIndex, YearIndex};
|
||||||
@@ -25,6 +26,7 @@ use super::{Date, DateIndex, YearIndex};
|
|||||||
IntoBytes,
|
IntoBytes,
|
||||||
KnownLayout,
|
KnownLayout,
|
||||||
StoredCompressed,
|
StoredCompressed,
|
||||||
|
Allocative,
|
||||||
)]
|
)]
|
||||||
pub struct MonthIndex(u16);
|
pub struct MonthIndex(u16);
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user