Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1103e538a5 | |||
| c0cd4cba6f | |||
| b91120e8d4 | |||
| 005774a4c2 | |||
| 16bbfebfba | |||
| 15505cd82d | |||
| 016d80e002 | |||
| 0f3c267a48 | |||
| 589bb02411 | |||
| c0f4ece17b | |||
| c3ae3cb768 | |||
| c9e0f9d985 | |||
| e3431c2fa3 | |||
| 5979b9771e | |||
| aa61832fb2 | |||
| 2ac6e982b1 | |||
| 3204ddcf07 | |||
| c87b1c133c | |||
| 9b275ecdae | |||
| d6fd7de361 | |||
| 49d66a133e | |||
| c559f26d0e | |||
| bbe9f1bad2 | |||
| 7e1fb6472d | |||
| 0ff8d20573 | |||
| 9c1f9448dc | |||
| 43a6081dd6 | |||
| 985e961876 | |||
| 098f6de047 | |||
| 1b0f90fd68 | |||
| 12252f407b | |||
| 3b6e3f47ab | |||
| 6a9ac9b025 | |||
| ae6aa4088b | |||
| c08f431180 | |||
| 123c1f56e9 | |||
| 35ac65a864 | |||
| e9f362cc87 | |||
| 65685c23e1 | |||
| 2f74748cea | |||
| f477bd66f3 | |||
| d7d77ae8f0 | |||
| 31110a740d | |||
| b64d8b1d7f | |||
| c46006aacc | |||
| 92f81b1493 | |||
| 70213cfc8f | |||
| 8a82bf5c50 | |||
| 37405384a2 | |||
| 54ea6cc53b | |||
| 339c00d815 | |||
| ea6b4dcde2 | |||
| 2b84623d1e | |||
| c8b3afa56b | |||
| 1348f3c24c | |||
| 62208ce3e1 | |||
| 813b2481de | |||
| 27b924ba61 | |||
| b40170b8ce | |||
| 8bfa9d2734 | |||
| c7cf76d4a8 | |||
| dfd2969b3e |
@@ -3,6 +3,8 @@
|
||||
|
||||
# Builds
|
||||
target
|
||||
dist
|
||||
vecid-to-indexes.js
|
||||
|
||||
# Copies
|
||||
*\ copy*
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
<!--
|
||||
# v0.X.Y | WIP
|
||||

|
||||

|
||||
-->
|
||||
|
||||
# v0.X.0 | WIP | A new beginning
|
||||
|
||||

|
||||
|
||||
Full rewrite
|
||||
|
||||
# [kibo-v0.5.0](https://github.com/kibo-money/kibo/tree/eea56d394bf92c62c81da8b78b8c47ea730683f5) | [873199](https://mempool.space/block/0000000000000000000270925aa6a565be92e13164565a3f7994ca1966e48050) - 2024/12/04
|
||||
# [kibo-v0.5.0](https://github.com/bitcoinresearchkit/brk/tree/eea56d394bf92c62c81da8b78b8c47ea730683f5) | [873199](https://mempool.space/block/0000000000000000000270925aa6a565be92e13164565a3f7994ca1966e48050) - 2024/12/04
|
||||
|
||||

|
||||

|
||||
|
||||
## Datasets
|
||||
|
||||
@@ -74,9 +76,9 @@ Full rewrite
|
||||
|
||||
- Moved back to this repo
|
||||
|
||||
# [kibo-v0.4.0](https://github.com/kibo-money/kibo/tree/a64c544815d9ef785e2fc1323582f774f16b9200) | [861950](https://mempool.space/block/00000000000000000000530d0e30ccf7deeace122dcc99f2668a06c6dad83629) - 2024/09/19
|
||||
# [kibo-v0.4.0](https://github.com/bitcoinresearchkit/brk/tree/a64c544815d9ef785e2fc1323582f774f16b9200) | [861950](https://mempool.space/block/00000000000000000000530d0e30ccf7deeace122dcc99f2668a06c6dad83629) - 2024/09/19
|
||||
|
||||

|
||||

|
||||
|
||||
## Brand
|
||||
|
||||
@@ -111,9 +113,9 @@ Full rewrite
|
||||
- Added serving of the website
|
||||
- Improved `Cache-Control` behavior
|
||||
|
||||
# [kibo-v0.3.0](https://github.com/kibo-money/kibo/tree/b68b016091c45b071218fba01bac5b76e8eaf18c) | [853930](https://mempool.space/block/00000000000000000002eb5e9a7950ca2d5d98bd1ed28fc9098aa630d417985d) - 2024/07/26
|
||||
# [satonomics-v0.3.0](https://github.com/bitcoinresearchkit/brk/tree/b68b016091c45b071218fba01bac5b76e8eaf18c) | [853930](https://mempool.space/block/00000000000000000002eb5e9a7950ca2d5d98bd1ed28fc9098aa630d417985d) - 2024/07/26
|
||||
|
||||

|
||||

|
||||
|
||||
## Parser
|
||||
|
||||
@@ -190,9 +192,9 @@ Full rewrite
|
||||
- Only run with a watcher if `cargo watch` is available
|
||||
- Removed id_to_path file in favor for only `paths.d.ts` in `app/src/types`
|
||||
|
||||
# [kibo-v0.2.0](https://github.com/kibo-money/kibo/tree/248187889283597c5dbb806292297453c25e97b8) | [851286](https://mempool.space/block/0000000000000000000281ca7f1bf8c50702bfca168c7af1bdc67c977c1ac8ed) - 2024/07/08
|
||||
# [satonomics-v0.2.0](https://github.com/bitcoinresearchkit/brk/tree/248187889283597c5dbb806292297453c25e97b8) | [851286](https://mempool.space/block/0000000000000000000281ca7f1bf8c50702bfca168c7af1bdc67c977c1ac8ed) - 2024/07/08
|
||||
|
||||

|
||||

|
||||
|
||||
## App
|
||||
|
||||
@@ -226,9 +228,9 @@ Full rewrite
|
||||
|
||||
- Fixed ulimit only being run in Mac OS instead of whenever the program is detected
|
||||
|
||||
# [kibo-v0.1.1](https://github.com/kibo-money/kibo/tree/e55b5195a9de9aea306903c94ed63cb1720fda5f) | [849240](https://mempool.space/block/000000000000000000002b8653988655071c07bb5f7181c038f9326bc86db741) - 2024/06/24
|
||||
# [satonomics-v0.1.1](https://github.com/bitcoinresearchkit/brk/tree/e55b5195a9de9aea306903c94ed63cb1720fda5f) | [849240](https://mempool.space/block/000000000000000000002b8653988655071c07bb5f7181c038f9326bc86db741) - 2024/06/24
|
||||
|
||||

|
||||

|
||||
|
||||
## Parser
|
||||
|
||||
@@ -276,10 +278,10 @@ Full rewrite
|
||||
|
||||
- Deleted old price datasets and their backups
|
||||
|
||||
# [kibo-v0.1.0](https://github.com/kibo-money/kibo/tree/a1a576d088c8f83ed32d48753a7611f70a964574) | [848642](https://mempool.space/block/000000000000000000020be5761d70751252219a9557f55e91ecdfb86c4e026a) - 2024/06/19
|
||||
# [satonomics-v0.1.0](https://github.com/bitcoinresearchkit/brk/tree/a1a576d088c8f83ed32d48753a7611f70a964574) | [848642](https://mempool.space/block/000000000000000000020be5761d70751252219a9557f55e91ecdfb86c4e026a) - 2024/06/19
|
||||
|
||||

|
||||

|
||||
|
||||
# kibo-v0.0.1 | [835444](https://mempool.space/block/000000000000000000009f93907a0dd83c080d5585cc7ec82c076d45f6d7c872) - 2024/03/20
|
||||
# satonomics-v0.0.1 | [835444](https://mempool.space/block/000000000000000000009f93907a0dd83c080d5585cc7ec82c076d45f6d7c872) - 2024/03/20
|
||||
|
||||

|
||||

|
||||
|
||||
@@ -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.license = "MIT"
|
||||
package.edition = "2024"
|
||||
package.version = "0.0.48"
|
||||
package.version = "0.0.67"
|
||||
package.homepage = "https://bitcoinresearchkit.org"
|
||||
package.repository = "https://github.com/bitcoinresearchkit/brk"
|
||||
|
||||
@@ -22,37 +22,41 @@ axum = "0.8.4"
|
||||
bincode = { version = "2.0.1", features = ["serde"] }
|
||||
bitcoin = { version = "0.32.6", features = ["serde"] }
|
||||
bitcoincore-rpc = "0.19.0"
|
||||
brk_cli = { version = "0", path = "crates/brk_cli" }
|
||||
brk_computer = { version = "0", path = "crates/brk_computer" }
|
||||
brk_core = { version = "0", path = "crates/brk_core" }
|
||||
brk_exit = { version = "0", path = "crates/brk_exit" }
|
||||
brk_fetcher = { version = "0", path = "crates/brk_fetcher" }
|
||||
brk_indexer = { version = "0", path = "crates/brk_indexer" }
|
||||
brk_logger = { version = "0", path = "crates/brk_logger" }
|
||||
brk_parser = { version = "0", path = "crates/brk_parser" }
|
||||
brk_query = { version = "0", path = "crates/brk_query" }
|
||||
brk_server = { version = "0", path = "crates/brk_server" }
|
||||
brk_state = { version = "0", path = "crates/brk_state" }
|
||||
brk_store = { version = "0", path = "crates/brk_store" }
|
||||
brk_vec = { version = "0", path = "crates/brk_vec" }
|
||||
brk_bundler = { version = "0.0.67", path = "crates/brk_bundler" }
|
||||
brk_cli = { version = "0.0.67", path = "crates/brk_cli" }
|
||||
brk_computer = { version = "0.0.67", path = "crates/brk_computer" }
|
||||
brk_core = { version = "0.0.67", path = "crates/brk_core" }
|
||||
brk_exit = { version = "0.0.67", path = "crates/brk_exit" }
|
||||
brk_fetcher = { version = "0.0.67", path = "crates/brk_fetcher" }
|
||||
brk_indexer = { version = "0.0.67", path = "crates/brk_indexer" }
|
||||
brk_interface = { version = "0.0.67", path = "crates/brk_interface" }
|
||||
brk_logger = { version = "0.0.67", path = "crates/brk_logger" }
|
||||
brk_mcp = { version = "0.0.67", path = "crates/brk_mcp" }
|
||||
brk_parser = { version = "0.0.67", path = "crates/brk_parser" }
|
||||
brk_rmcp = { version = "0.1.7", features = ["transport-streamable-http-server", "transport-worker"]}
|
||||
brk_server = { version = "0.0.67", path = "crates/brk_server" }
|
||||
brk_state = { version = "0.0.67", path = "crates/brk_state" }
|
||||
brk_store = { version = "0.0.67", path = "crates/brk_store" }
|
||||
brk_vec = { version = "0.0.67", path = "crates/brk_vec" }
|
||||
byteview = "=0.6.1"
|
||||
clap = { version = "4.5.39", features = ["string"] }
|
||||
clap_derive = "4.5.32"
|
||||
clap = { version = "4.5.40", features = ["string"] }
|
||||
clap_derive = "4.5.40"
|
||||
color-eyre = "0.6.5"
|
||||
derive_deref = "1.1.1"
|
||||
fjall = "2.11.0"
|
||||
jiff = "0.2.14"
|
||||
fjall = "2.11.1"
|
||||
jiff = "0.2.15"
|
||||
log = { version = "0.4.27" }
|
||||
minreq = { version = "2.13.4", features = ["https", "serde_json"] }
|
||||
rayon = "1.10.0"
|
||||
schemars = "1.0.0"
|
||||
serde = { version = "1.0.219" }
|
||||
serde_bytes = "0.11.17"
|
||||
serde_derive = "1.0.219"
|
||||
serde_json = { version = "1.0.140", features = ["float_roundtrip"] }
|
||||
tabled = "0.20.0"
|
||||
tokio = { version = "1.45.1", features = ["rt-multi-thread"] }
|
||||
zerocopy = { version = "0.8.25" }
|
||||
zerocopy-derive = "0.8.25"
|
||||
zerocopy = { version = "0.8.26" }
|
||||
zerocopy-derive = "0.8.26"
|
||||
|
||||
[workspace.metadata.release]
|
||||
shared-version = true
|
||||
|
||||
@@ -41,9 +41,13 @@ The toolkit can be used in various ways to accommodate as many needs as possible
|
||||
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. \
|
||||
Also available at: [kibo.money](https://kibo.money) // [satonomics.xyz](https://satonomics.xyz)
|
||||
- **[API](https://github.com/bitcoinresearchkit/brk/tree/main/crates/brk_server#endpoints)** \
|
||||
Researchers and developers are free to use BRK's public API with  dataset variants at your disposal. \
|
||||
- **[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. \
|
||||
Just like the website, it's entirely free, with no authentication or rate-limiting.
|
||||
- **[AI](https://github.com/bitcoinresearchkit/brk/blob/main/crates/brk_mcp/README.md#brk-mcp)** \
|
||||
LLMs have to possibility to connect to BRK's backend through a [MCP](https://modelcontextprotocol.io/introduction). \
|
||||
It will give them access to the same tools as the API, with no restrictions, and allow you to have your very own data analysts. \
|
||||
One-shot output examples: [Document](https://claude.ai/public/artifacts/71194d29-f965-417c-ba09-fdf0e4ecb1d5) // [Dashboard](https://claude.ai/public/artifacts/beef143f-399a-4ed4-b8bf-c986b776de42) // [Dashboard 2](https://claude.ai/public/artifacts/5430ae49-bb3d-4fc1-ab24-f1e33deb40dc)
|
||||
- **[CLI](https://crates.io/crates/brk_cli)** \
|
||||
Node runners are strongly encouraged to try out and self-host their own instance using BRK's command line interface. \
|
||||
The CLI has multiple cogs available for users to tweak to adapt to all situations with even the possibility for web developers to create their own custom website which could later on be added as an alternative front-end.
|
||||
@@ -58,19 +62,21 @@ In contrast, existing alternatives tend to be either [very costly](https://studi
|
||||
## Crates
|
||||
|
||||
- [`brk`](https://crates.io/crates/brk): Wrapper around all other `brk-*` crates
|
||||
- [`brk_cli`](https://crates.io/crates/brk_cli): A standalone command line interface to interact with the Bitcoin Research Kit
|
||||
- [`brk_cli`](https://crates.io/crates/brk_cli): A command line interface to run a Bitcoin Research Kit instance
|
||||
- [`brk_computer`](https://crates.io/crates/brk_computer): A Bitcoin dataset computer, built on top of brk_indexer
|
||||
- [`brk_core`](https://crates.io/crates/brk_core): The Core (Structs and Errors) of the Bitcoin Research Kit
|
||||
- [`brk_exit`](https://crates.io/crates/brk_exit): An exit blocker built on top of ctrlc
|
||||
- [`brk_fetcher`](https://crates.io/crates/brk_fetcher): A Bitcoin price fetcher
|
||||
- [`brk_indexer`](https://crates.io/crates/brk_indexer): A Bitcoin Core indexer built on top of brk_parser
|
||||
- [`brk_logger`](https://crates.io/crates/brk_logger): A clean logger used in the Bitcoin Research Kit.
|
||||
- [`brk_logger`](https://crates.io/crates/brk_logger): A clean logger used in the Bitcoin Research Kit
|
||||
- [`brk_mcp`](https://crates.io/crates/brk_mcp): A Model Context Protocol (MCP) which gives LLMs access to all available tools in BRK
|
||||
- [`brk_parser`](https://crates.io/crates/brk_parser): A very fast Bitcoin Core block parser and iterator built on top of bitcoin-rust
|
||||
- [`brk_query`](https://crates.io/crates/brk_query): A library that finds requested datasets.
|
||||
- [`brk_interface`](https://crates.io/crates/brk_interface): An interface to BRK's engine
|
||||
- [`brk_server`](https://crates.io/crates/brk_server): A server that serves Bitcoin data and swappable front-ends, built on top of `brk_indexer`, `brk_fetcher` and `brk_computer`
|
||||
- [`brk_state`](https://crates.io/crates/brk_state): Various states used mainly by the computer
|
||||
- [`brk_store`](https://crates.io/crates/brk_store): A thin wrapper around [`fjall`](https://crates.io/crates/fjall)
|
||||
- [`brk_vec`](https://crates.io/crates/brk_vec): A push-only, truncable, compressable, saveable Vec
|
||||
- [`brk_bundler`](https://crates.io/crates/brk_bundler): A thin wrapper around [`rolldown`](https://rolldown.rs/)
|
||||
|
||||
## Hosting as a service
|
||||
|
||||
@@ -91,7 +97,7 @@ Pricing: `0.01 BTC / month` *or* `0.1 BTC / year`
|
||||
|
||||
Deepest gratitude to the [Open Sats](https://opensats.org/) public charity. Their grant — from December 2024 to the present — has been critical in sustaining this project.
|
||||
|
||||
Heartfelt thanks go out to every donor on [Nostr](https://primal.net/p/npub1jagmm3x39lmwfnrtvxcs9ac7g300y3dusv9lgzhk2e4x5frpxlrqa73v44) and [Geyser.fund](https://geyser.fund/project/brk) whose support has ensured the availability of the [kibo.money](https://kibo.money) public instance.
|
||||
Heartfelt thanks go out to every donor on [Nostr](https://primal.net/p/npub1jagmm3x39lmwfnrtvxcs9ac7g300y3dusv9lgzhk2e4x5frpxlrqa73v44) and [Geyser.fund](https://geyser.fund/project/brk) whose support has ensured the availability of the [bitcoinresearchkit.org](https://bitcoinresearchkit.org) public instance.
|
||||
|
||||
## Donate
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 340 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 253 KiB |
|
After Width: | Height: | Size: 208 KiB |
|
After Width: | Height: | Size: 386 KiB |
|
After Width: | Height: | Size: 496 KiB |
|
After Width: | Height: | Size: 564 KiB |
|
After Width: | Height: | Size: 592 KiB |
|
After Width: | Height: | Size: 453 KiB |
|
After Width: | Height: | Size: 526 KiB |
@@ -10,33 +10,38 @@ version.workspace = true
|
||||
|
||||
[features]
|
||||
full = [
|
||||
"bundler",
|
||||
"core",
|
||||
"computer",
|
||||
"exit",
|
||||
"fetcher",
|
||||
"indexer",
|
||||
"logger",
|
||||
"mcp",
|
||||
"parser",
|
||||
"query",
|
||||
"interface",
|
||||
"server",
|
||||
"state",
|
||||
"store",
|
||||
"vec",
|
||||
]
|
||||
bundler = ["brk_bundler"]
|
||||
core = ["brk_core"]
|
||||
computer = ["brk_computer"]
|
||||
exit = ["brk_exit"]
|
||||
fetcher = ["brk_fetcher"]
|
||||
indexer = ["brk_indexer"]
|
||||
logger = ["brk_logger"]
|
||||
mcp = ["brk_mcp"]
|
||||
parser = ["brk_parser"]
|
||||
query = ["brk_query"]
|
||||
interface = ["brk_interface"]
|
||||
server = ["brk_server"]
|
||||
state = ["brk_state"]
|
||||
store = ["brk_store"]
|
||||
vec = ["brk_vec"]
|
||||
|
||||
[dependencies]
|
||||
brk_bundler = { workspace = true, optional = true }
|
||||
brk_cli = { workspace = true }
|
||||
brk_core = { workspace = true, optional = true }
|
||||
brk_computer = { workspace = true, optional = true }
|
||||
@@ -44,8 +49,9 @@ brk_exit = { workspace = true, optional = true }
|
||||
brk_fetcher = { workspace = true, optional = true }
|
||||
brk_indexer = { workspace = true, optional = true }
|
||||
brk_logger = { workspace = true, optional = true }
|
||||
brk_mcp = { workspace = true, optional = true }
|
||||
brk_parser = { workspace = true, optional = true }
|
||||
brk_query = { workspace = true, optional = true }
|
||||
brk_interface = { workspace = true, optional = true }
|
||||
brk_server = { workspace = true, optional = true }
|
||||
brk_state = { workspace = true, optional = true }
|
||||
brk_store = { workspace = true, optional = true }
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
fn main() {}
|
||||
@@ -1,5 +1,12 @@
|
||||
#![doc = include_str!(concat!("../", env!("CARGO_PKG_README")))]
|
||||
|
||||
#[cfg(feature = "bundler")]
|
||||
#[doc(inline)]
|
||||
pub use brk_bundler as bundler;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use brk_cli as cli;
|
||||
|
||||
#[cfg(feature = "core")]
|
||||
#[doc(inline)]
|
||||
pub use brk_core as core;
|
||||
@@ -24,13 +31,17 @@ pub use brk_indexer as indexer;
|
||||
#[doc(inline)]
|
||||
pub use brk_logger as logger;
|
||||
|
||||
#[cfg(feature = "mcp")]
|
||||
#[doc(inline)]
|
||||
pub use brk_mcp as mcp;
|
||||
|
||||
#[cfg(feature = "parser")]
|
||||
#[doc(inline)]
|
||||
pub use brk_parser as parser;
|
||||
|
||||
#[cfg(feature = "query")]
|
||||
#[cfg(feature = "interface")]
|
||||
#[doc(inline)]
|
||||
pub use brk_query as query;
|
||||
pub use brk_interface as interface;
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
#[doc(inline)]
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "brk_bundler"
|
||||
description = "A thin wrapper around rolldown"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
log = { workspace = true }
|
||||
notify = "8.0.0"
|
||||
brk_rolldown = "0.0.1"
|
||||
sugar_path = "1.2.0"
|
||||
tokio = { workspace = true }
|
||||
@@ -0,0 +1,145 @@
|
||||
use std::{fs, io, path::Path, sync::Arc};
|
||||
|
||||
use brk_rolldown::{Bundler, BundlerOptions, RawMinifyOptions, SourceMapType};
|
||||
use log::error;
|
||||
use notify::{EventKind, RecursiveMode, Watcher};
|
||||
use sugar_path::SugarPath;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
pub async fn bundle(websites_path: &Path, source_folder: &str, watch: bool) -> io::Result<()> {
|
||||
let source_path = websites_path.join(source_folder);
|
||||
let dist_path = websites_path.join("dist");
|
||||
|
||||
let _ = fs::remove_dir_all(&dist_path);
|
||||
copy_dir_all(&source_path, &dist_path)?;
|
||||
|
||||
let source_scripts = format!("./{source_folder}/scripts");
|
||||
let source_entry = format!("{source_scripts}/entry.js");
|
||||
|
||||
let absolute_websites_path = websites_path.absolutize();
|
||||
|
||||
let mut bundler = Bundler::new(BundlerOptions {
|
||||
input: Some(vec![source_entry.into()]),
|
||||
dir: Some("./dist/scripts".to_string()),
|
||||
cwd: Some(absolute_websites_path),
|
||||
minify: Some(RawMinifyOptions::Bool(true)),
|
||||
sourcemap: Some(SourceMapType::File),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
bundler.write().await.unwrap();
|
||||
|
||||
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_path = source_path.absolutize();
|
||||
let absolute_source_path_clone = absolute_source_path.clone();
|
||||
let absolute_source_scripts_path = websites_path.join(source_scripts).absolutize();
|
||||
let absolute_source_sw_path = source_path.join("service-worker.js").absolutize();
|
||||
let absolute_source_sw_path_clone = absolute_source_sw_path.clone();
|
||||
|
||||
let absolute_dist_entry_path = dist_path.join("scripts/entry.js").absolutize();
|
||||
let absolute_dist_index_path = dist_path.join("index.html").absolutize();
|
||||
let absolute_dist_path = dist_path.absolutize();
|
||||
let absolute_dist_path_clone = absolute_dist_path.clone();
|
||||
let absolute_dist_sw_path = dist_path.join("service-worker.js").absolutize();
|
||||
|
||||
let write_index = move || {
|
||||
let mut contents = fs::read_to_string(&absolute_source_index_path).unwrap();
|
||||
|
||||
if let Ok(entry) = fs::read_to_string(absolute_dist_path_clone.join("scripts/entry.js")) {
|
||||
if let Some(start) = entry.find("main") {
|
||||
if let Some(end) = entry.find(".js") {
|
||||
let main_hashed = &entry[start..end];
|
||||
contents =
|
||||
contents.replace("/scripts/main.js", &format!("/scripts/{main_hashed}.js"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _ = fs::write(&absolute_dist_index_path, contents);
|
||||
};
|
||||
|
||||
let write_sw = move || {
|
||||
let contents = fs::read_to_string(&absolute_source_sw_path)
|
||||
.unwrap()
|
||||
.replace("__VERSION__", &format!("v{VERSION}"));
|
||||
let _ = fs::write(&absolute_dist_sw_path, contents);
|
||||
};
|
||||
|
||||
write_index();
|
||||
write_sw();
|
||||
|
||||
if !watch {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
tokio::spawn(async move {
|
||||
let write_index_clone = write_index.clone();
|
||||
|
||||
let mut entry_watcher = notify::recommended_watcher(
|
||||
move |res: Result<notify::Event, notify::Error>| match res {
|
||||
Ok(_) => write_index_clone(),
|
||||
Err(e) => error!("watch error: {:?}", e),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
entry_watcher
|
||||
.watch(&absolute_dist_entry_path, RecursiveMode::Recursive)
|
||||
.unwrap();
|
||||
|
||||
let mut source_watcher = notify::recommended_watcher(
|
||||
move |res: Result<notify::Event, notify::Error>| match res {
|
||||
Ok(event) => match event.kind {
|
||||
EventKind::Create(_) => event.paths,
|
||||
EventKind::Modify(_) => event.paths,
|
||||
_ => vec![],
|
||||
}
|
||||
.into_iter()
|
||||
.filter(|path| path.starts_with(&absolute_source_path))
|
||||
.filter(|path| !path.starts_with(&absolute_source_scripts_path))
|
||||
.for_each(|source_path| {
|
||||
let suffix = source_path.strip_prefix(&absolute_source_path).unwrap();
|
||||
let dist_path = absolute_dist_path.join(suffix);
|
||||
|
||||
if source_path == absolute_source_index_path_clone {
|
||||
write_index();
|
||||
} else if source_path == absolute_source_sw_path_clone {
|
||||
write_sw();
|
||||
} else {
|
||||
let _ = fs::copy(&source_path, &dist_path);
|
||||
}
|
||||
}),
|
||||
Err(e) => error!("watch error: {:?}", e),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
source_watcher
|
||||
.watch(&absolute_source_path_clone, RecursiveMode::Recursive)
|
||||
.unwrap();
|
||||
|
||||
let watcher =
|
||||
brk_rolldown::Watcher::new(vec![Arc::new(Mutex::new(bundler))], None).unwrap();
|
||||
|
||||
watcher.start().await;
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
|
||||
fs::create_dir_all(&dst)?;
|
||||
for entry in fs::read_dir(src)? {
|
||||
let entry = entry?;
|
||||
let ty = entry.file_type()?;
|
||||
if ty.is_dir() {
|
||||
copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?;
|
||||
} else {
|
||||
fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "brk_cli"
|
||||
description = "A command line interface to interact with the full Bitcoin Research Kit"
|
||||
description = "A command line interface to run a Bitcoin Research Kit instance"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
@@ -16,7 +16,6 @@ brk_fetcher = { workspace = true }
|
||||
brk_indexer = { workspace = true }
|
||||
brk_logger = { workspace = true }
|
||||
brk_parser = { workspace = true }
|
||||
brk_query = { workspace = true }
|
||||
brk_server = { workspace = true }
|
||||
brk_vec = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
@@ -24,7 +23,6 @@ clap_derive = { workspace = true }
|
||||
color-eyre = { workspace = true }
|
||||
log = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
tabled = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
toml = "0.8.23"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# BRK Cli
|
||||
# BRK CLI
|
||||
|
||||
<p align="left">
|
||||
<a href="https://github.com/bitcoinresearchkit/brk">
|
||||
@@ -31,9 +31,11 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
A command line interface to interact with the full Bitcoin Research Kit. It's built on top of every other create and gives the possility to use BRK using the terminal instead of Rust.
|
||||
A command line interface to run a Bitcoin Research Kit instance.
|
||||
|
||||
It has 2 commandes for now (other than `help` and `version`) which are `run` and `query`. The former is used to run the processing (indexer + computer) and/or the server. The latter uses `brk_query` as its backend just like to server to be able to get datasets via the terminal instead of the API. Both commands are very costumizable by having all the parameters of their Rust counterparts ([`run`](https://github.com/bitcoinresearchkit/brk/blob/main/crates/brk_cli/src/run.rs#L91-L147), [`query`](https://github.com/bitcoinresearchkit/brk/blob/main/crates/brk_query/src/params.rs)).
|
||||
It's very customizable with all parameters from the underlying tools (crates) used inside.
|
||||
|
||||
Run `brk -h` for more information.
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -54,13 +56,15 @@ To be determined
|
||||
- [Bitcoin](https://bitcoin.org/en/full-node)
|
||||
- [Rust](https://www.rust-lang.org/tools/install)
|
||||
- Unix based operating system (Mac OS or Linux)
|
||||
- Ubuntu users need to install `open-ssl` via `sudo apt install libssl-dev pkg-config`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Ubuntu users need to install `open-ssl` via `sudo apt install libssl-dev pkg-config`
|
||||
|
||||
## Download
|
||||
|
||||
### Binaries
|
||||
|
||||
You can find a pre-built binary for your operating system on the releases page ([link](https://github.com/bitcoinresearchkit/brk/releases/latest)).
|
||||
You can find a pre-built binary for your operating system in the [releases page](https://github.com/bitcoinresearchkit/brk/releases/latest).
|
||||
|
||||
### Cargo
|
||||
|
||||
@@ -82,10 +86,11 @@ cargo run -r
|
||||
|
||||
## Usage
|
||||
|
||||
Run `brk -h` to view each available command and their respective description.
|
||||
Run `brk -h` to view each available parameter and their respective description.
|
||||
|
||||
`-h` works also for commands, which mean that `brk run -h` will explain all the parameters of `brk run` for example.
|
||||
> [!TIP]
|
||||
> Every parameter set will be saved at `~/.brk/config.toml`, which allows you to simply run `brk` next time.
|
||||
|
||||
Every parameter set for `brk run` will be saved at `~/.brk/config.toml`, which will allow you to simply run `brk run` next time.
|
||||
## Tunnel
|
||||
|
||||
Then the easiest to let others access your server is to use `cloudflared` which will also cache requests. For more information go to: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/
|
||||
The easiest way to let others access your server is to use `cloudflared` which will also cache requests. For more information see [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) documentation.
|
||||
|
||||
@@ -0,0 +1,375 @@
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use bitcoincore_rpc::{self, Auth, Client};
|
||||
use brk_core::{default_bitcoin_path, default_brk_path, default_on_error, dot_brk_path};
|
||||
use brk_fetcher::Fetcher;
|
||||
use brk_server::Website;
|
||||
use brk_vec::{Computation, Format};
|
||||
use clap::Parser;
|
||||
use clap_derive::Parser;
|
||||
use color_eyre::eyre::eyre;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::services::Services;
|
||||
|
||||
#[derive(Parser, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
/// Bitcoin main directory path, defaults: ~/.bitcoin, ~/Library/Application\ Support/Bitcoin, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(long, value_name = "PATH")]
|
||||
bitcoindir: Option<String>,
|
||||
|
||||
/// Bitcoin blocks directory path, default: --bitcoindir/blocks, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(long, value_name = "PATH")]
|
||||
blocksdir: Option<String>,
|
||||
|
||||
/// Bitcoin Research Kit outputs directory path, default: ~/.brk, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(long, value_name = "PATH")]
|
||||
brkdir: Option<String>,
|
||||
|
||||
/// Activated services, default: all, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(short, long)]
|
||||
services: Option<Services>,
|
||||
|
||||
/// Computation of computed datasets, `lazy` computes data whenever requested without saving it, `eager` computes the data once and saves it to disk, default: `lazy`, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(short, long)]
|
||||
computation: Option<Computation>,
|
||||
|
||||
/// Format of computed datasets, `compressed` to save disk space (experimental), `raw` to prioritize speed, default: `raw`, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(short, long)]
|
||||
format: Option<Format>,
|
||||
|
||||
/// Activate fetching prices from exchanges APIs and the computation of all related datasets, default: true, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(short = 'F', long, value_name = "BOOL")]
|
||||
fetch: Option<bool>,
|
||||
|
||||
/// Website served by the server (if active), default: default, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(short, long)]
|
||||
website: Option<Website>,
|
||||
|
||||
/// Bitcoin RPC ip, default: localhost, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(long, value_name = "IP")]
|
||||
rpcconnect: Option<String>,
|
||||
|
||||
/// Bitcoin RPC port, default: 8332, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(long, value_name = "PORT")]
|
||||
rpcport: Option<u16>,
|
||||
|
||||
/// Bitcoin RPC cookie file, default: --bitcoindir/.cookie, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(long, value_name = "PATH")]
|
||||
rpccookiefile: Option<String>,
|
||||
|
||||
/// Bitcoin RPC username, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(long, value_name = "USERNAME")]
|
||||
rpcuser: Option<String>,
|
||||
|
||||
/// Bitcoin RPC password, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(long, value_name = "PASSWORD")]
|
||||
rpcpassword: Option<String>,
|
||||
|
||||
/// Delay between runs, default: 0, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(long, value_name = "SECONDS")]
|
||||
delay: Option<u64>,
|
||||
|
||||
/// Activate the Model Context Protocol (MCP) endpoint to give LLMs access to BRK (experimental), default: false, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(long, value_name = "BOOL")]
|
||||
mcp: Option<bool>,
|
||||
|
||||
/// DEV: Activate watching the selected website's folder for changes, default: false, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(long, value_name = "BOOL")]
|
||||
watch: Option<bool>,
|
||||
|
||||
/// DEV: Activate checking address hashes for collisions when indexing, default: false, saved
|
||||
#[serde(default, deserialize_with = "default_on_error")]
|
||||
#[arg(long, value_name = "BOOL")]
|
||||
check_collisions: Option<bool>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn import() -> color_eyre::Result<Self> {
|
||||
let config_args = Some(Config::parse());
|
||||
|
||||
let path = dot_brk_path();
|
||||
|
||||
let _ = fs::create_dir_all(&path);
|
||||
|
||||
let path = path.join("config.toml");
|
||||
|
||||
let mut config_saved = Self::read(&path);
|
||||
|
||||
if let Some(mut config_args) = config_args {
|
||||
if let Some(bitcoindir) = config_args.bitcoindir.take() {
|
||||
config_saved.bitcoindir = Some(bitcoindir);
|
||||
}
|
||||
|
||||
if let Some(blocksdir) = config_args.blocksdir.take() {
|
||||
config_saved.blocksdir = Some(blocksdir);
|
||||
}
|
||||
|
||||
if let Some(brkdir) = config_args.brkdir.take() {
|
||||
config_saved.brkdir = Some(brkdir);
|
||||
}
|
||||
|
||||
if let Some(services) = config_args.services.take() {
|
||||
config_saved.services = Some(services);
|
||||
}
|
||||
|
||||
if let Some(computation) = config_args.computation.take() {
|
||||
config_saved.computation = Some(computation);
|
||||
}
|
||||
|
||||
if let Some(fetch) = config_args.fetch.take() {
|
||||
config_saved.fetch = Some(fetch);
|
||||
}
|
||||
|
||||
if let Some(format) = config_args.format.take() {
|
||||
config_saved.format = Some(format);
|
||||
}
|
||||
|
||||
if let Some(website) = config_args.website.take() {
|
||||
config_saved.website = Some(website);
|
||||
}
|
||||
|
||||
if let Some(rpcconnect) = config_args.rpcconnect.take() {
|
||||
config_saved.rpcconnect = Some(rpcconnect);
|
||||
}
|
||||
|
||||
if let Some(rpcport) = config_args.rpcport.take() {
|
||||
config_saved.rpcport = Some(rpcport);
|
||||
}
|
||||
|
||||
if let Some(rpccookiefile) = config_args.rpccookiefile.take() {
|
||||
config_saved.rpccookiefile = Some(rpccookiefile);
|
||||
}
|
||||
|
||||
if let Some(rpcuser) = config_args.rpcuser.take() {
|
||||
config_saved.rpcuser = Some(rpcuser);
|
||||
}
|
||||
|
||||
if let Some(rpcpassword) = config_args.rpcpassword.take() {
|
||||
config_saved.rpcpassword = Some(rpcpassword);
|
||||
}
|
||||
|
||||
if let Some(delay) = config_args.delay.take() {
|
||||
config_saved.delay = Some(delay);
|
||||
}
|
||||
|
||||
if let Some(check_collisions) = config_args.check_collisions.take() {
|
||||
config_saved.check_collisions = Some(check_collisions);
|
||||
}
|
||||
|
||||
if let Some(mcp) = config_args.mcp.take() {
|
||||
config_saved.mcp = Some(mcp);
|
||||
}
|
||||
|
||||
if let Some(watch) = config_args.watch.take() {
|
||||
config_saved.watch = Some(watch);
|
||||
}
|
||||
|
||||
if config_args != Config::default() {
|
||||
dbg!(config_args);
|
||||
panic!("Didn't consume the full config")
|
||||
}
|
||||
}
|
||||
|
||||
let config = config_saved;
|
||||
|
||||
config.check();
|
||||
|
||||
config.write(&path)?;
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
fn check(&self) {
|
||||
if !self.bitcoindir().is_dir() {
|
||||
println!("{:?} isn't a valid directory", self.bitcoindir());
|
||||
println!("Please use the --bitcoindir parameter to set a valid path.");
|
||||
println!("Run the program with '-h' for help.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if !self.blocksdir().is_dir() {
|
||||
println!("{:?} isn't a valid directory", self.blocksdir());
|
||||
println!("Please use the --blocksdir parameter to set a valid path.");
|
||||
println!("Run the program with '-h' for help.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if !self.brkdir().is_dir() {
|
||||
println!("{:?} isn't a valid directory", self.brkdir());
|
||||
println!("Please use the --brkdir parameter to set a valid path.");
|
||||
println!("Run the program with '-h' for help.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if self.rpc_auth().is_err() {
|
||||
println!(
|
||||
"No way found to authenticate the RPC client, please either set --rpccookiefile or --rpcuser and --rpcpassword.\nRun the program with '-h' for help."
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn read(path: &Path) -> Self {
|
||||
fs::read_to_string(path).map_or_else(
|
||||
|_| Config::default(),
|
||||
|contents| toml::from_str(&contents).unwrap_or_default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn write(&self, path: &Path) -> std::io::Result<()> {
|
||||
fs::write(path, toml::to_string(self).unwrap())
|
||||
}
|
||||
|
||||
pub fn rpc(&self) -> color_eyre::Result<&'static Client> {
|
||||
Ok(Box::leak(Box::new(Client::new(
|
||||
&format!(
|
||||
"http://{}:{}",
|
||||
self.rpcconnect().unwrap_or(&"localhost".to_string()),
|
||||
self.rpcport().unwrap_or(8332)
|
||||
),
|
||||
self.rpc_auth().unwrap(),
|
||||
)?)))
|
||||
}
|
||||
|
||||
fn rpc_auth(&self) -> color_eyre::Result<Auth> {
|
||||
let cookie = self.path_cookiefile();
|
||||
|
||||
if cookie.is_file() {
|
||||
Ok(Auth::CookieFile(cookie))
|
||||
} else if self.rpcuser.is_some() && self.rpcpassword.is_some() {
|
||||
Ok(Auth::UserPass(
|
||||
self.rpcuser.clone().unwrap(),
|
||||
self.rpcpassword.clone().unwrap(),
|
||||
))
|
||||
} else {
|
||||
Err(eyre!("Failed to find correct auth"))
|
||||
}
|
||||
}
|
||||
|
||||
fn rpcconnect(&self) -> Option<&String> {
|
||||
self.rpcconnect.as_ref()
|
||||
}
|
||||
|
||||
fn rpcport(&self) -> Option<u16> {
|
||||
self.rpcport
|
||||
}
|
||||
|
||||
pub fn delay(&self) -> Option<u64> {
|
||||
self.delay
|
||||
}
|
||||
|
||||
pub fn bitcoindir(&self) -> PathBuf {
|
||||
self.bitcoindir
|
||||
.as_ref()
|
||||
.map_or_else(default_bitcoin_path, |s| Self::fix_user_path(s.as_ref()))
|
||||
}
|
||||
|
||||
pub fn blocksdir(&self) -> PathBuf {
|
||||
self.blocksdir.as_ref().map_or_else(
|
||||
|| self.bitcoindir().join("blocks"),
|
||||
|blocksdir| Self::fix_user_path(blocksdir.as_str()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn brkdir(&self) -> PathBuf {
|
||||
self.brkdir
|
||||
.as_ref()
|
||||
.map_or_else(default_brk_path, |s| Self::fix_user_path(s.as_ref()))
|
||||
}
|
||||
|
||||
pub fn outputsdir(&self) -> PathBuf {
|
||||
self.brkdir().join("outputs")
|
||||
}
|
||||
|
||||
pub fn harsdir(&self) -> PathBuf {
|
||||
self.outputsdir().join("hars")
|
||||
}
|
||||
|
||||
pub fn process(&self) -> bool {
|
||||
self.services
|
||||
.is_none_or(|m| m == Services::All || m == Services::Processor)
|
||||
}
|
||||
|
||||
pub fn serve(&self) -> bool {
|
||||
self.services
|
||||
.is_none_or(|m| m == Services::All || m == Services::Server)
|
||||
}
|
||||
|
||||
fn path_cookiefile(&self) -> PathBuf {
|
||||
self.rpccookiefile.as_ref().map_or_else(
|
||||
|| self.bitcoindir().join(".cookie"),
|
||||
|p| Self::fix_user_path(p.as_str()),
|
||||
)
|
||||
}
|
||||
|
||||
fn fix_user_path(path: &str) -> PathBuf {
|
||||
let fix = move |pattern: &str| {
|
||||
if path.starts_with(pattern) {
|
||||
let path = &path
|
||||
.replace(&format!("{pattern}/"), "")
|
||||
.replace(pattern, "");
|
||||
|
||||
let home = std::env::var("HOME").unwrap();
|
||||
|
||||
Some(Path::new(&home).join(path))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
fix("~").unwrap_or_else(|| fix("$HOME").unwrap_or_else(|| PathBuf::from(&path)))
|
||||
}
|
||||
|
||||
pub fn website(&self) -> Website {
|
||||
self.website.unwrap_or(Website::Default)
|
||||
}
|
||||
|
||||
pub fn fetch(&self) -> bool {
|
||||
self.fetch.is_none_or(|b| b)
|
||||
}
|
||||
|
||||
pub fn fetcher(&self) -> Option<Fetcher> {
|
||||
self.fetch()
|
||||
.then(|| Fetcher::import(Some(self.harsdir().as_path())).unwrap())
|
||||
}
|
||||
|
||||
pub fn computation(&self) -> Computation {
|
||||
self.computation.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn format(&self) -> Format {
|
||||
self.format.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn check_collisions(&self) -> bool {
|
||||
self.check_collisions.is_some_and(|b| b)
|
||||
}
|
||||
|
||||
pub fn mcp(&self) -> bool {
|
||||
self.mcp.is_some_and(|b| b)
|
||||
}
|
||||
|
||||
pub fn watch(&self) -> bool {
|
||||
self.watch.is_some_and(|b| b)
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,12 @@
|
||||
use std::{fs, thread};
|
||||
|
||||
use brk_core::{dot_brk_log_path, dot_brk_path};
|
||||
use brk_query::Params as QueryArgs;
|
||||
use clap::Parser;
|
||||
use clap_derive::{Parser, Subcommand};
|
||||
use query::query;
|
||||
use run::{RunConfig, run};
|
||||
|
||||
mod query;
|
||||
mod config;
|
||||
mod run;
|
||||
mod services;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(version, about)]
|
||||
#[command(propagate_version = true)]
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
enum Commands {
|
||||
/// Run the indexer, computer and server
|
||||
Run(RunConfig),
|
||||
/// Query generated datasets via the `run` command in a similar fashion as the server's API
|
||||
Query(QueryArgs),
|
||||
}
|
||||
use run::*;
|
||||
|
||||
pub fn main() -> color_eyre::Result<()> {
|
||||
color_eyre::install()?;
|
||||
@@ -33,14 +15,9 @@ pub fn main() -> color_eyre::Result<()> {
|
||||
|
||||
brk_logger::init(Some(&dot_brk_log_path()));
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
thread::Builder::new()
|
||||
.stack_size(128 * 1024 * 1024)
|
||||
.spawn(|| match cli.command {
|
||||
Commands::Run(args) => run(args),
|
||||
Commands::Query(args) => query(args),
|
||||
})?
|
||||
.stack_size(256 * 1024 * 1024)
|
||||
.spawn(run)?
|
||||
.join()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
use brk_computer::Computer;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_query::{Index, Output, Params as QueryParams, Query, Tabled, Value};
|
||||
use tabled::settings::Style;
|
||||
|
||||
use crate::run::RunConfig;
|
||||
|
||||
pub fn query(params: QueryParams) -> color_eyre::Result<()> {
|
||||
let config = RunConfig::import(None)?;
|
||||
|
||||
let format = config.format();
|
||||
|
||||
let mut indexer = Indexer::new(&config.outputsdir(), format, config.check_collisions())?;
|
||||
indexer.import_vecs()?;
|
||||
|
||||
let mut computer = Computer::new(&config.outputsdir(), config.fetcher(), format);
|
||||
computer.import_vecs(&indexer, config.computation())?;
|
||||
|
||||
let query = Query::build(&indexer, &computer);
|
||||
|
||||
let index = Index::try_from(params.index.as_str())?;
|
||||
let ids = params.values.iter().map(|s| s.as_str()).collect::<Vec<_>>();
|
||||
let from = params.from();
|
||||
let to = params.to();
|
||||
let format = params.format();
|
||||
|
||||
let res = query.search_and_format(index, &ids, from, to, format)?;
|
||||
|
||||
if format.is_some() {
|
||||
println!("{}", res);
|
||||
} else {
|
||||
println!(
|
||||
"{}",
|
||||
match res {
|
||||
Output::Json(v) => match v {
|
||||
Value::Single(v) => v.to_string().replace("\"", ""),
|
||||
v => {
|
||||
let v = match v {
|
||||
Value::Single(_) => unreachable!("Already processed"),
|
||||
Value::List(v) => vec![v],
|
||||
Value::Matrix(v) => v,
|
||||
};
|
||||
let mut table =
|
||||
v.to_table(ids.iter().map(|id| id.to_string()).collect::<Vec<_>>());
|
||||
table.with(Style::psql());
|
||||
table.to_string()
|
||||
}
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,25 +1,16 @@
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
thread::sleep,
|
||||
time::Duration,
|
||||
};
|
||||
use std::{thread::sleep, time::Duration};
|
||||
|
||||
use bitcoincore_rpc::{self, Auth, Client, RpcApi};
|
||||
use bitcoincore_rpc::{self, RpcApi};
|
||||
use brk_computer::Computer;
|
||||
use brk_core::{default_bitcoin_path, default_brk_path, dot_brk_path};
|
||||
use brk_exit::Exit;
|
||||
use brk_fetcher::Fetcher;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_server::{Server, Website};
|
||||
use brk_vec::{Computation, Format};
|
||||
use clap_derive::{Parser, ValueEnum};
|
||||
use color_eyre::eyre::eyre;
|
||||
use brk_server::Server;
|
||||
use log::info;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub fn run(config: RunConfig) -> color_eyre::Result<()> {
|
||||
let config = RunConfig::import(Some(config))?;
|
||||
use crate::config::Config;
|
||||
|
||||
pub fn run() -> color_eyre::Result<()> {
|
||||
let config = Config::import()?;
|
||||
|
||||
let rpc = config.rpc()?;
|
||||
|
||||
@@ -29,9 +20,7 @@ pub fn run(config: RunConfig) -> color_eyre::Result<()> {
|
||||
|
||||
let format = config.format();
|
||||
|
||||
let mut indexer = Indexer::new(&config.outputsdir(), format, config.check_collisions())?;
|
||||
indexer.import_stores()?;
|
||||
indexer.import_vecs()?;
|
||||
let mut indexer = Indexer::forced_import(&config.outputsdir())?;
|
||||
|
||||
let wait_for_synced_node = || -> color_eyre::Result<()> {
|
||||
let is_synced = || -> color_eyre::Result<bool> {
|
||||
@@ -49,9 +38,13 @@ pub fn run(config: RunConfig) -> color_eyre::Result<()> {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let mut computer = Computer::new(&config.outputsdir(), config.fetcher(), format);
|
||||
computer.import_stores(&indexer)?;
|
||||
computer.import_vecs(&indexer, config.computation())?;
|
||||
let mut computer = Computer::forced_import(
|
||||
&config.outputsdir(),
|
||||
&indexer,
|
||||
config.computation(),
|
||||
config.fetcher(),
|
||||
format,
|
||||
)?;
|
||||
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
@@ -63,8 +56,10 @@ pub fn run(config: RunConfig) -> color_eyre::Result<()> {
|
||||
|
||||
let server = Server::new(served_indexer, served_computer, config.website())?;
|
||||
|
||||
let watch = config.watch();
|
||||
let mcp = config.mcp();
|
||||
let opt = Some(tokio::spawn(async move {
|
||||
server.serve().await.unwrap();
|
||||
server.serve(watch, mcp).await.unwrap();
|
||||
}));
|
||||
|
||||
sleep(Duration::from_secs(1));
|
||||
@@ -82,7 +77,8 @@ pub fn run(config: RunConfig) -> color_eyre::Result<()> {
|
||||
|
||||
info!("{} blocks found.", block_count + 1);
|
||||
|
||||
let starting_indexes = indexer.index(&parser, rpc, &exit)?;
|
||||
let starting_indexes =
|
||||
indexer.index(&parser, rpc, &exit, config.check_collisions())?;
|
||||
|
||||
computer.compute(&mut indexer, starting_indexes, &exit)?;
|
||||
|
||||
@@ -105,353 +101,3 @@ pub fn run(config: RunConfig) -> color_eyre::Result<()> {
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
|
||||
pub struct RunConfig {
|
||||
/// Bitcoin main directory path, defaults: ~/.bitcoin, ~/Library/Application\ Support/Bitcoin, saved
|
||||
#[arg(long, value_name = "PATH")]
|
||||
bitcoindir: Option<String>,
|
||||
|
||||
/// Bitcoin blocks directory path, default: --bitcoindir/blocks, saved
|
||||
#[arg(long, value_name = "PATH")]
|
||||
blocksdir: Option<String>,
|
||||
|
||||
/// Bitcoin Research Kit outputs directory path, default: ~/.brk, saved
|
||||
#[arg(long, value_name = "PATH")]
|
||||
brkdir: Option<String>,
|
||||
|
||||
/// Executed by the runner, default: all, saved
|
||||
#[arg(short, long)]
|
||||
mode: Option<Mode>,
|
||||
|
||||
/// Computation mode for compatible datasets, `lazy` computes data whenever requested without saving it, `eager` computes the data once and saves it to disk, default: Lazy, saved
|
||||
#[arg(short, long)]
|
||||
computation: Option<Computation>,
|
||||
|
||||
/// Activate compression of datasets, set to true to save disk space or false if prioritize speed, default: true, saved
|
||||
#[arg(short, long, value_name = "FORMAT")]
|
||||
format: Option<Format>,
|
||||
|
||||
/// Activate fetching prices from exchanges APIs and the computation of all related datasets, default: true, saved
|
||||
#[arg(short = 'F', long, value_name = "BOOL")]
|
||||
fetch: Option<bool>,
|
||||
|
||||
/// Website served by the server (if active), default: default, saved
|
||||
#[arg(short, long)]
|
||||
website: Option<Website>,
|
||||
|
||||
/// Bitcoin RPC ip, default: localhost, saved
|
||||
#[arg(long, value_name = "IP")]
|
||||
rpcconnect: Option<String>,
|
||||
|
||||
/// Bitcoin RPC port, default: 8332, saved
|
||||
#[arg(long, value_name = "PORT")]
|
||||
rpcport: Option<u16>,
|
||||
|
||||
/// Bitcoin RPC cookie file, default: --bitcoindir/.cookie, saved
|
||||
#[arg(long, value_name = "PATH")]
|
||||
rpccookiefile: Option<String>,
|
||||
|
||||
/// Bitcoin RPC username, saved
|
||||
#[arg(long, value_name = "USERNAME")]
|
||||
rpcuser: Option<String>,
|
||||
|
||||
/// Bitcoin RPC password, saved
|
||||
#[arg(long, value_name = "PASSWORD")]
|
||||
rpcpassword: Option<String>,
|
||||
|
||||
/// Delay between runs, default: 0, saved
|
||||
#[arg(long, value_name = "SECONDS")]
|
||||
delay: Option<u64>,
|
||||
|
||||
/// DEV: Activate checking address hashes for collisions when indexing, default: false, saved
|
||||
#[arg(long, value_name = "BOOL")]
|
||||
check_collisions: Option<bool>,
|
||||
}
|
||||
|
||||
impl RunConfig {
|
||||
pub fn import(config_args: Option<RunConfig>) -> color_eyre::Result<Self> {
|
||||
let path = dot_brk_path();
|
||||
|
||||
let _ = fs::create_dir_all(&path);
|
||||
|
||||
let path = path.join("config.toml");
|
||||
|
||||
let mut config_saved = Self::read(&path);
|
||||
|
||||
if let Some(mut config_args) = config_args {
|
||||
if let Some(bitcoindir) = config_args.bitcoindir.take() {
|
||||
config_saved.bitcoindir = Some(bitcoindir);
|
||||
}
|
||||
|
||||
if let Some(blocksdir) = config_args.blocksdir.take() {
|
||||
config_saved.blocksdir = Some(blocksdir);
|
||||
}
|
||||
|
||||
if let Some(brkdir) = config_args.brkdir.take() {
|
||||
config_saved.brkdir = Some(brkdir);
|
||||
}
|
||||
|
||||
if let Some(mode) = config_args.mode.take() {
|
||||
config_saved.mode = Some(mode);
|
||||
}
|
||||
|
||||
if let Some(computation) = config_args.computation.take() {
|
||||
config_saved.computation = Some(computation);
|
||||
}
|
||||
|
||||
if let Some(fetch) = config_args.fetch.take() {
|
||||
config_saved.fetch = Some(fetch);
|
||||
}
|
||||
|
||||
if let Some(format) = config_args.format.take() {
|
||||
config_saved.format = Some(format);
|
||||
}
|
||||
|
||||
if let Some(website) = config_args.website.take() {
|
||||
config_saved.website = Some(website);
|
||||
}
|
||||
|
||||
if let Some(rpcconnect) = config_args.rpcconnect.take() {
|
||||
config_saved.rpcconnect = Some(rpcconnect);
|
||||
}
|
||||
|
||||
if let Some(rpcport) = config_args.rpcport.take() {
|
||||
config_saved.rpcport = Some(rpcport);
|
||||
}
|
||||
|
||||
if let Some(rpccookiefile) = config_args.rpccookiefile.take() {
|
||||
config_saved.rpccookiefile = Some(rpccookiefile);
|
||||
}
|
||||
|
||||
if let Some(rpcuser) = config_args.rpcuser.take() {
|
||||
config_saved.rpcuser = Some(rpcuser);
|
||||
}
|
||||
|
||||
if let Some(rpcpassword) = config_args.rpcpassword.take() {
|
||||
config_saved.rpcpassword = Some(rpcpassword);
|
||||
}
|
||||
|
||||
if let Some(delay) = config_args.delay.take() {
|
||||
config_saved.delay = Some(delay);
|
||||
}
|
||||
|
||||
if let Some(check_collisions) = config_args.check_collisions.take() {
|
||||
config_saved.check_collisions = Some(check_collisions);
|
||||
}
|
||||
|
||||
if config_args != RunConfig::default() {
|
||||
dbg!(config_args);
|
||||
panic!("Didn't consume the full config")
|
||||
}
|
||||
}
|
||||
|
||||
let config = config_saved;
|
||||
|
||||
config.check();
|
||||
|
||||
config.write(&path)?;
|
||||
|
||||
// info!("Configuration {{");
|
||||
// info!(" bitcoindir: {:?}", config.bitcoindir);
|
||||
// info!(" brkdir: {:?}", config.brkdir);
|
||||
// info!(" mode: {:?}", config.mode);
|
||||
// info!(" website: {:?}", config.website);
|
||||
// info!(" rpcconnect: {:?}", config.rpcconnect);
|
||||
// info!(" rpcport: {:?}", config.rpcport);
|
||||
// info!(" rpccookiefile: {:?}", config.rpccookiefile);
|
||||
// info!(" rpcuser: {:?}", config.rpcuser);
|
||||
// info!(" rpcpassword: {:?}", config.rpcpassword);
|
||||
// info!(" delay: {:?}", config.delay);
|
||||
// info!("}}");
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
fn check(&self) {
|
||||
if !self.bitcoindir().is_dir() {
|
||||
println!("{:?} isn't a valid directory", self.bitcoindir());
|
||||
println!("Please use the --bitcoindir parameter to set a valid path.");
|
||||
println!("Run the program with '-h' for help.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if !self.blocksdir().is_dir() {
|
||||
println!("{:?} isn't a valid directory", self.blocksdir());
|
||||
println!("Please use the --blocksdir parameter to set a valid path.");
|
||||
println!("Run the program with '-h' for help.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if !self.brkdir().is_dir() {
|
||||
println!("{:?} isn't a valid directory", self.brkdir());
|
||||
println!("Please use the --brkdir parameter to set a valid path.");
|
||||
println!("Run the program with '-h' for help.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if self.rpc_auth().is_err() {
|
||||
println!(
|
||||
"No way found to authenticate the RPC client, please either set --rpccookiefile or --rpcuser and --rpcpassword.\nRun the program with '-h' for help."
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn read(path: &Path) -> Self {
|
||||
fs::read_to_string(path).map_or_else(
|
||||
|_| RunConfig::default(),
|
||||
|contents| toml::from_str(&contents).unwrap_or_default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn write(&self, path: &Path) -> std::io::Result<()> {
|
||||
fs::write(path, toml::to_string(self).unwrap())
|
||||
}
|
||||
|
||||
pub fn rpc(&self) -> color_eyre::Result<&'static Client> {
|
||||
Ok(Box::leak(Box::new(Client::new(
|
||||
&format!(
|
||||
"http://{}:{}",
|
||||
self.rpcconnect().unwrap_or(&"localhost".to_string()),
|
||||
self.rpcport().unwrap_or(8332)
|
||||
),
|
||||
self.rpc_auth().unwrap(),
|
||||
)?)))
|
||||
}
|
||||
|
||||
fn rpc_auth(&self) -> color_eyre::Result<Auth> {
|
||||
let cookie = self.path_cookiefile();
|
||||
|
||||
if cookie.is_file() {
|
||||
Ok(Auth::CookieFile(cookie))
|
||||
} else if self.rpcuser.is_some() && self.rpcpassword.is_some() {
|
||||
Ok(Auth::UserPass(
|
||||
self.rpcuser.clone().unwrap(),
|
||||
self.rpcpassword.clone().unwrap(),
|
||||
))
|
||||
} else {
|
||||
Err(eyre!("Failed to find correct auth"))
|
||||
}
|
||||
}
|
||||
|
||||
fn rpcconnect(&self) -> Option<&String> {
|
||||
self.rpcconnect.as_ref()
|
||||
}
|
||||
|
||||
fn rpcport(&self) -> Option<u16> {
|
||||
self.rpcport
|
||||
}
|
||||
|
||||
pub fn delay(&self) -> Option<u64> {
|
||||
self.delay
|
||||
}
|
||||
|
||||
pub fn bitcoindir(&self) -> PathBuf {
|
||||
self.bitcoindir
|
||||
.as_ref()
|
||||
.map_or_else(default_bitcoin_path, |s| Self::fix_user_path(s.as_ref()))
|
||||
}
|
||||
|
||||
pub fn blocksdir(&self) -> PathBuf {
|
||||
self.blocksdir.as_ref().map_or_else(
|
||||
|| self.bitcoindir().join("blocks"),
|
||||
|blocksdir| Self::fix_user_path(blocksdir.as_str()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn brkdir(&self) -> PathBuf {
|
||||
self.brkdir
|
||||
.as_ref()
|
||||
.map_or_else(default_brk_path, |s| Self::fix_user_path(s.as_ref()))
|
||||
}
|
||||
|
||||
pub fn outputsdir(&self) -> PathBuf {
|
||||
self.brkdir().join("outputs")
|
||||
}
|
||||
|
||||
pub fn harsdir(&self) -> PathBuf {
|
||||
self.outputsdir().join("hars")
|
||||
}
|
||||
|
||||
pub fn process(&self) -> bool {
|
||||
self.mode
|
||||
.is_none_or(|m| m == Mode::All || m == Mode::Processor)
|
||||
}
|
||||
|
||||
pub fn serve(&self) -> bool {
|
||||
self.mode
|
||||
.is_none_or(|m| m == Mode::All || m == Mode::Server)
|
||||
}
|
||||
|
||||
fn path_cookiefile(&self) -> PathBuf {
|
||||
self.rpccookiefile.as_ref().map_or_else(
|
||||
|| self.bitcoindir().join(".cookie"),
|
||||
|p| Self::fix_user_path(p.as_str()),
|
||||
)
|
||||
}
|
||||
|
||||
fn fix_user_path(path: &str) -> PathBuf {
|
||||
let fix = move |pattern: &str| {
|
||||
if path.starts_with(pattern) {
|
||||
let path = &path
|
||||
.replace(&format!("{pattern}/"), "")
|
||||
.replace(pattern, "");
|
||||
|
||||
let home = std::env::var("HOME").unwrap();
|
||||
|
||||
Some(Path::new(&home).join(path))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
fix("~").unwrap_or_else(|| fix("$HOME").unwrap_or_else(|| PathBuf::from(&path)))
|
||||
}
|
||||
|
||||
pub fn website(&self) -> Website {
|
||||
self.website.unwrap_or(Website::Default)
|
||||
}
|
||||
|
||||
pub fn fetch(&self) -> bool {
|
||||
self.fetch.is_none_or(|b| b)
|
||||
}
|
||||
|
||||
pub fn fetcher(&self) -> Option<Fetcher> {
|
||||
self.fetch()
|
||||
.then(|| Fetcher::import(Some(self.harsdir().as_path())).unwrap())
|
||||
}
|
||||
|
||||
pub fn computation(&self) -> Computation {
|
||||
self.computation.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn format(&self) -> Format {
|
||||
self.format.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn check_collisions(&self) -> bool {
|
||||
self.check_collisions.is_some_and(|b| b)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Default,
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
Parser,
|
||||
ValueEnum,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
)]
|
||||
pub enum Mode {
|
||||
#[default]
|
||||
All,
|
||||
Processor,
|
||||
Server,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
use clap_derive::{Parser, ValueEnum};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(
|
||||
Default,
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
Parser,
|
||||
ValueEnum,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
)]
|
||||
pub enum Services {
|
||||
#[default]
|
||||
All,
|
||||
Processor,
|
||||
Server,
|
||||
}
|
||||
@@ -33,17 +33,19 @@ pub fn main() -> color_eyre::Result<()> {
|
||||
|
||||
let format = Format::Raw;
|
||||
|
||||
let mut indexer = Indexer::new(outputs_dir, format, true)?;
|
||||
indexer.import_stores()?;
|
||||
indexer.import_vecs()?;
|
||||
let mut indexer = Indexer::forced_import(outputs_dir)?;
|
||||
|
||||
let fetcher = Fetcher::import(None)?;
|
||||
|
||||
let mut computer = Computer::new(outputs_dir, Some(fetcher), format);
|
||||
computer.import_stores(&indexer)?;
|
||||
computer.import_vecs(&indexer, Computation::Lazy)?;
|
||||
let mut computer = Computer::forced_import(
|
||||
outputs_dir,
|
||||
&indexer,
|
||||
Computation::Lazy,
|
||||
Some(fetcher),
|
||||
format,
|
||||
)?;
|
||||
|
||||
let starting_indexes = indexer.index(&parser, rpc, &exit)?;
|
||||
let starting_indexes = indexer.index(&parser, rpc, &exit, true)?;
|
||||
|
||||
computer.compute(&mut indexer, starting_indexes, &exit)?;
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
#![doc = include_str!("../examples/main.rs")]
|
||||
#![doc = "```"]
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::Version;
|
||||
use brk_exit::Exit;
|
||||
use brk_fetcher::Fetcher;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyCollectableVec, Computation, Format};
|
||||
use brk_vec::{Computation, Format};
|
||||
|
||||
mod stores;
|
||||
mod utils;
|
||||
@@ -21,53 +21,40 @@ use vecs::Vecs;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Computer {
|
||||
path: PathBuf,
|
||||
fetcher: Option<Fetcher>,
|
||||
vecs: Option<Vecs>,
|
||||
stores: Option<Stores>,
|
||||
format: Format,
|
||||
pub vecs: Vecs,
|
||||
pub stores: Stores,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ONE;
|
||||
|
||||
impl Computer {
|
||||
pub fn new(outputs_dir: &Path, fetcher: Option<Fetcher>, format: Format) -> Self {
|
||||
Self {
|
||||
path: outputs_dir.to_owned(),
|
||||
fetcher,
|
||||
vecs: None,
|
||||
stores: None,
|
||||
format,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn import_vecs(
|
||||
&mut self,
|
||||
/// Do NOT import multiple times or things will break !!!
|
||||
pub fn forced_import(
|
||||
outputs_dir: &Path,
|
||||
indexer: &Indexer,
|
||||
computation: Computation,
|
||||
) -> color_eyre::Result<()> {
|
||||
self.vecs = Some(Vecs::import(
|
||||
// TODO: Give self.path, join inside import
|
||||
&self.path.join("vecs/computed"),
|
||||
VERSION + Version::ZERO,
|
||||
indexer,
|
||||
self.fetcher.is_some(),
|
||||
computation,
|
||||
self.format,
|
||||
)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Do NOT import multiple times or things will break !!!
|
||||
/// Clone struct instead
|
||||
pub fn import_stores(&mut self, indexer: &Indexer) -> color_eyre::Result<()> {
|
||||
self.stores = Some(Stores::import(
|
||||
// TODO: Give self.path, join inside import
|
||||
&self.path.join("stores"),
|
||||
VERSION + Version::ZERO,
|
||||
indexer.keyspace(),
|
||||
)?);
|
||||
Ok(())
|
||||
fetcher: Option<Fetcher>,
|
||||
format: Format,
|
||||
) -> color_eyre::Result<Self> {
|
||||
Ok(Self {
|
||||
vecs: Vecs::import(
|
||||
// TODO: Give self.path, join inside import
|
||||
&outputs_dir.join("vecs/computed"),
|
||||
VERSION + Version::ZERO,
|
||||
indexer,
|
||||
fetcher.is_some(),
|
||||
computation,
|
||||
format,
|
||||
)?,
|
||||
stores: Stores::import(
|
||||
// TODO: Give self.path, join inside import
|
||||
&outputs_dir.join("stores"),
|
||||
VERSION + Version::ZERO,
|
||||
&indexer.stores.keyspace,
|
||||
)?,
|
||||
fetcher,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,25 +67,6 @@ impl Computer {
|
||||
) -> color_eyre::Result<()> {
|
||||
info!("Computing...");
|
||||
self.vecs
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute(indexer, starting_indexes, self.fetcher.as_mut(), exit)
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
// pub fn vecs(&self) -> &Vecs {
|
||||
self.vecs.as_ref().unwrap().vecs()
|
||||
}
|
||||
|
||||
// pub fn mut_vecs(&mut self) -> &mut Vecs {
|
||||
// self.vecs.as_mut().unwrap()
|
||||
// }
|
||||
|
||||
pub fn stores(&self) -> &Stores {
|
||||
self.stores.as_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn mut_stores(&mut self) -> &mut Stores {
|
||||
self.stores.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{fs, path::Path};
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{
|
||||
CheckedSub, DifficultyEpoch, HalvingEpoch, Height, StoredU32, StoredU64, StoredUsize,
|
||||
@@ -37,8 +37,6 @@ impl Vecs {
|
||||
_computation: Computation,
|
||||
format: Format,
|
||||
) -> color_eyre::Result<Self> {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
Ok(Self {
|
||||
height_to_interval: EagerVec::forced_import(
|
||||
path,
|
||||
@@ -154,23 +152,19 @@ impl Vecs {
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
let indexer_vecs = indexer.vecs();
|
||||
|
||||
v.compute_range(
|
||||
starting_indexes.height,
|
||||
&indexer_vecs.height_to_weight,
|
||||
&indexer.vecs.height_to_weight,
|
||||
|h| (h, StoredU32::from(1_u32)),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
let indexer_vecs = indexer.vecs();
|
||||
|
||||
let mut height_to_timestamp_iter = indexer_vecs.height_to_timestamp.iter();
|
||||
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,
|
||||
&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);
|
||||
@@ -194,19 +188,19 @@ impl Vecs {
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&indexer_vecs.height_to_weight),
|
||||
Some(&indexer.vecs.height_to_weight),
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_size.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&indexer_vecs.height_to_total_size),
|
||||
Some(&indexer.vecs.height_to_total_size),
|
||||
)?;
|
||||
|
||||
self.height_to_vbytes.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer_vecs.height_to_weight,
|
||||
&indexer.vecs.height_to_weight,
|
||||
|(h, w, ..)| {
|
||||
(
|
||||
h,
|
||||
@@ -223,7 +217,7 @@ impl Vecs {
|
||||
Some(&self.height_to_vbytes),
|
||||
)?;
|
||||
|
||||
let mut height_to_timestamp_iter = indexer_vecs.height_to_timestamp.iter();
|
||||
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
|
||||
|
||||
self.difficultyepoch_to_timestamp.compute_transform(
|
||||
starting_indexes.difficultyepoch,
|
||||
|
||||
@@ -0,0 +1,679 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{Bitcoin, CheckedSub, Dollars, StoredF64, Version};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyCollectableVec, Computation, Format, VecIterator};
|
||||
|
||||
use crate::vecs::{
|
||||
fetched,
|
||||
grouped::{ComputedRatioVecsFromDateIndex, ComputedValueVecsFromHeight},
|
||||
stateful, transactions,
|
||||
};
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
grouped::{ComputedVecsFromHeight, StorableVecGeneatorOptions},
|
||||
indexes,
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
pub indexes_to_coinblocks_created: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_coinblocks_stored: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_liveliness: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_vaultedness: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_activity_to_vaultedness_ratio: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_vaulted_supply: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_active_supply: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_thermo_cap: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_investor_cap: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_vaulted_cap: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_active_cap: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_vaulted_price: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_vaulted_price_ratio: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_active_price: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_active_price_ratio: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_true_market_mean: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_true_market_mean_ratio: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_cointime_value_destroyed: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_cointime_value_created: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_cointime_value_stored: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_cointime_price: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_cointime_cap: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_cointime_price_ratio: ComputedRatioVecsFromDateIndex,
|
||||
// pub indexes_to_thermo_cap_relative_to_investor_cap: ComputedValueVecsFromHeight,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
path: &Path,
|
||||
version: Version,
|
||||
_computation: Computation,
|
||||
format: Format,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
) -> color_eyre::Result<Self> {
|
||||
let compute_dollars = fetched.is_some();
|
||||
|
||||
Ok(Self {
|
||||
indexes_to_coinblocks_created: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"coinblocks_created",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
indexes_to_coinblocks_stored: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"coinblocks_stored",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
indexes_to_liveliness: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"liveliness",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_vaultedness: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"vaultedness",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_activity_to_vaultedness_ratio: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"activity_to_vaultedness_ratio",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_vaulted_supply: ComputedValueVecsFromHeight::forced_import(
|
||||
path,
|
||||
"vaulted_supply",
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
compute_dollars,
|
||||
)?,
|
||||
indexes_to_active_supply: ComputedValueVecsFromHeight::forced_import(
|
||||
path,
|
||||
"active_supply",
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
compute_dollars,
|
||||
)?,
|
||||
indexes_to_thermo_cap: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"thermo_cap",
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_investor_cap: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"investor_cap",
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_vaulted_cap: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"vaulted_cap",
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_active_cap: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"active_cap",
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_vaulted_price: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"vaulted_price",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_vaulted_price_ratio: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"vaulted_price",
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)?,
|
||||
indexes_to_active_price: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"active_price",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_active_price_ratio: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"active_price",
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)?,
|
||||
indexes_to_true_market_mean: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"true_market_mean",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_true_market_mean_ratio: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"true_market_mean",
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)?,
|
||||
indexes_to_cointime_value_destroyed: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"cointime_value_destroyed",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
indexes_to_cointime_value_created: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"cointime_value_created",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
indexes_to_cointime_value_stored: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"cointime_value_stored",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
indexes_to_cointime_price: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"cointime_price",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_cointime_cap: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"cointime_cap",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_cointime_price_ratio: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"cointime_price",
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
transactions: &transactions::Vecs,
|
||||
stateful: &stateful::Vecs,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
let circulating_supply = &stateful.utxos_vecs.all.1.height_to_supply;
|
||||
|
||||
self.indexes_to_coinblocks_created.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
circulating_supply,
|
||||
|(i, v, ..)| (i, StoredF64::from(Bitcoin::from(v))),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
let indexes_to_coinblocks_destroyed =
|
||||
&stateful.utxos_vecs.all.1.indexes_to_coinblocks_destroyed;
|
||||
|
||||
self.indexes_to_coinblocks_stored.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut coinblocks_destroyed_iter = indexes_to_coinblocks_destroyed
|
||||
.height
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
self.indexes_to_coinblocks_created.height.as_ref().unwrap(),
|
||||
|(i, created, ..)| {
|
||||
let destroyed = coinblocks_destroyed_iter.unwrap_get_inner(i);
|
||||
(i, created.checked_sub(destroyed).unwrap())
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_liveliness.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
indexes_to_coinblocks_destroyed
|
||||
.height_extra
|
||||
.unwrap_cumulative(),
|
||||
self.indexes_to_coinblocks_created
|
||||
.height_extra
|
||||
.unwrap_cumulative(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
let liveliness = &self.indexes_to_liveliness;
|
||||
|
||||
self.indexes_to_vaultedness.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
liveliness.height.as_ref().unwrap(),
|
||||
|(i, v, ..)| (i, StoredF64::from(1.0).checked_sub(v).unwrap()),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
let vaultedness = &self.indexes_to_vaultedness;
|
||||
|
||||
self.indexes_to_activity_to_vaultedness_ratio.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
liveliness.height.as_ref().unwrap(),
|
||||
vaultedness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_vaulted_supply.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
circulating_supply,
|
||||
vaultedness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_active_supply.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
circulating_supply,
|
||||
liveliness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
if let Some(fetched) = fetched {
|
||||
let realized_cap = stateful
|
||||
.utxos_vecs
|
||||
.all
|
||||
.1
|
||||
.height_to_realized_cap
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
|
||||
let realized_price = stateful
|
||||
.utxos_vecs
|
||||
.all
|
||||
.1
|
||||
.indexes_to_realized_price
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.height
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
|
||||
self.indexes_to_thermo_cap.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
transactions
|
||||
.indexes_to_subsidy
|
||||
.dollars
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.height_extra
|
||||
.unwrap_cumulative(),
|
||||
|(i, v, ..)| (i, v),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_investor_cap.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_subtract(
|
||||
starting_indexes.height,
|
||||
realized_cap,
|
||||
self.indexes_to_thermo_cap.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_vaulted_cap.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
realized_cap,
|
||||
self.indexes_to_vaultedness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_active_cap.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
realized_cap,
|
||||
self.indexes_to_liveliness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_vaulted_price.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
realized_price,
|
||||
self.indexes_to_vaultedness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_vaulted_price_ratio.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.indexes_to_vaulted_price.dateindex.unwrap_last()),
|
||||
)?;
|
||||
|
||||
self.indexes_to_active_price.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
realized_price,
|
||||
self.indexes_to_liveliness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_active_price_ratio.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.indexes_to_active_price.dateindex.unwrap_last()),
|
||||
)?;
|
||||
|
||||
self.indexes_to_true_market_mean.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
self.indexes_to_investor_cap.height.as_ref().unwrap(),
|
||||
self.indexes_to_active_supply
|
||||
.bitcoin
|
||||
.height
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_true_market_mean_ratio.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.indexes_to_true_market_mean.dateindex.unwrap_last()),
|
||||
)?;
|
||||
|
||||
self.indexes_to_cointime_value_destroyed.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
// TODO: Another example when the callback should be applied to each index, instead of to base then merging from more granular to less
|
||||
// The price taken won't be correct for time based indexes
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
&fetched.chainindexes_to_close.height,
|
||||
indexes_to_coinblocks_destroyed.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cointime_value_created.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
&fetched.chainindexes_to_close.height,
|
||||
self.indexes_to_coinblocks_created.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cointime_value_stored.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
&fetched.chainindexes_to_close.height,
|
||||
self.indexes_to_coinblocks_stored.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cointime_price.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
self.indexes_to_cointime_value_destroyed
|
||||
.height_extra
|
||||
.unwrap_cumulative(),
|
||||
self.indexes_to_coinblocks_stored
|
||||
.height_extra
|
||||
.unwrap_cumulative(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cointime_cap.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
self.indexes_to_cointime_price.height.as_ref().unwrap(),
|
||||
circulating_supply,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cointime_price_ratio.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.indexes_to_cointime_price.dateindex.unwrap_last()),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self.indexes_to_coinblocks_created.vecs(),
|
||||
self.indexes_to_coinblocks_stored.vecs(),
|
||||
self.indexes_to_liveliness.vecs(),
|
||||
self.indexes_to_vaultedness.vecs(),
|
||||
self.indexes_to_activity_to_vaultedness_ratio.vecs(),
|
||||
self.indexes_to_vaulted_supply.vecs(),
|
||||
self.indexes_to_active_supply.vecs(),
|
||||
self.indexes_to_thermo_cap.vecs(),
|
||||
self.indexes_to_investor_cap.vecs(),
|
||||
self.indexes_to_vaulted_cap.vecs(),
|
||||
self.indexes_to_active_cap.vecs(),
|
||||
self.indexes_to_vaulted_price.vecs(),
|
||||
self.indexes_to_vaulted_price_ratio.vecs(),
|
||||
self.indexes_to_active_price.vecs(),
|
||||
self.indexes_to_active_price_ratio.vecs(),
|
||||
self.indexes_to_true_market_mean.vecs(),
|
||||
self.indexes_to_true_market_mean_ratio.vecs(),
|
||||
self.indexes_to_cointime_price.vecs(),
|
||||
self.indexes_to_cointime_cap.vecs(),
|
||||
self.indexes_to_cointime_price_ratio.vecs(),
|
||||
self.indexes_to_cointime_value_destroyed.vecs(),
|
||||
self.indexes_to_cointime_value_created.vecs(),
|
||||
self.indexes_to_cointime_value_stored.vecs(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{fs, path::Path};
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{StoredU8, Version};
|
||||
use brk_exit::Exit;
|
||||
@@ -15,10 +15,10 @@ const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
pub _0: ComputedVecsFromHeight<StoredU8>,
|
||||
pub _1: ComputedVecsFromHeight<StoredU8>,
|
||||
pub _50: ComputedVecsFromHeight<StoredU8>,
|
||||
pub _100: ComputedVecsFromHeight<StoredU8>,
|
||||
pub constant_0: ComputedVecsFromHeight<StoredU8>,
|
||||
pub constant_1: ComputedVecsFromHeight<StoredU8>,
|
||||
pub constant_50: ComputedVecsFromHeight<StoredU8>,
|
||||
pub constant_100: ComputedVecsFromHeight<StoredU8>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -28,36 +28,34 @@ impl Vecs {
|
||||
_computation: Computation,
|
||||
format: Format,
|
||||
) -> color_eyre::Result<Self> {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
Ok(Self {
|
||||
_0: ComputedVecsFromHeight::forced_import(
|
||||
constant_0: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"0",
|
||||
"constant_0",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
_1: ComputedVecsFromHeight::forced_import(
|
||||
constant_1: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"1",
|
||||
"constant_1",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
_50: ComputedVecsFromHeight::forced_import(
|
||||
constant_50: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"50",
|
||||
"constant_50",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
_100: ComputedVecsFromHeight::forced_import(
|
||||
constant_100: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"100",
|
||||
"constant_100",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
@@ -73,7 +71,7 @@ impl Vecs {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
self._0.compute_all(
|
||||
self.constant_0.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
@@ -89,7 +87,7 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
self._1.compute_all(
|
||||
self.constant_1.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
@@ -105,7 +103,7 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
self._50.compute_all(
|
||||
self.constant_50.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
@@ -121,7 +119,7 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
self._100.compute_all(
|
||||
self.constant_100.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
@@ -142,10 +140,10 @@ impl Vecs {
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self._0.vecs(),
|
||||
self._1.vecs(),
|
||||
self._50.vecs(),
|
||||
self._100.vecs(),
|
||||
self.constant_0.vecs(),
|
||||
self.constant_1.vecs(),
|
||||
self.constant_50.vecs(),
|
||||
self.constant_100.vecs(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{fs, path::Path};
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{
|
||||
Cents, Close, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, Height, High, Low, MonthIndex,
|
||||
@@ -7,7 +7,7 @@ use brk_core::{
|
||||
use brk_exit::Exit;
|
||||
use brk_fetcher::Fetcher;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyCollectableVec, AnyIterableVec, Computation, EagerVec, Format};
|
||||
use brk_vec::{AnyCollectableVec, AnyIterableVec, Computation, EagerVec, Format, StoredIndex};
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
@@ -75,8 +75,6 @@ impl Vecs {
|
||||
_computation: Computation,
|
||||
format: Format,
|
||||
) -> color_eyre::Result<Self> {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
let mut fetched_path = path.to_owned();
|
||||
fetched_path.pop();
|
||||
fetched_path = fetched_path.join("fetched");
|
||||
@@ -371,12 +369,10 @@ impl Vecs {
|
||||
fetcher: &mut Fetcher,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
let indexer_vecs = indexer.vecs();
|
||||
|
||||
let mut height_to_timestamp_iter = indexer_vecs.height_to_timestamp.iter();
|
||||
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
|
||||
self.height_to_ohlc_in_cents.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer_vecs.height_to_timestamp,
|
||||
&indexer.vecs.height_to_timestamp,
|
||||
|(h, t, ..)| {
|
||||
let ohlc = fetcher
|
||||
.get_height(
|
||||
@@ -429,8 +425,18 @@ impl Vecs {
|
||||
self.dateindex_to_ohlc_in_cents.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&indexes.dateindex_to_date,
|
||||
|(di, d, ..)| {
|
||||
let ohlc = fetcher.get_date(d).unwrap();
|
||||
|(di, d, this)| {
|
||||
let mut ohlc = fetcher.get_date(d).unwrap();
|
||||
if let Some(prev) = di.decremented() {
|
||||
let prev_open = *this
|
||||
.get_or_read(prev, &this.mmap().load())
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.close;
|
||||
*ohlc.open = prev_open;
|
||||
*ohlc.high = (*ohlc.high).max(prev_open);
|
||||
*ohlc.low = (*ohlc.low).min(prev_open);
|
||||
}
|
||||
(di, ohlc)
|
||||
},
|
||||
exit,
|
||||
|
||||
@@ -130,7 +130,11 @@ where
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("sum"),
|
||||
&(if !options.last {
|
||||
name.to_string()
|
||||
} else {
|
||||
maybe_suffix("sum")
|
||||
}),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
|
||||
@@ -163,7 +163,7 @@ where
|
||||
self.height.compute(
|
||||
starting_indexes.height,
|
||||
txindex,
|
||||
&indexer.vecs().height_to_first_txindex,
|
||||
&indexer.vecs.height_to_first_txindex,
|
||||
&indexes.height_to_txindex_count,
|
||||
exit,
|
||||
)?;
|
||||
@@ -173,7 +173,7 @@ where
|
||||
self.height.compute(
|
||||
starting_indexes.height,
|
||||
txindex,
|
||||
&indexer.vecs().height_to_first_txindex,
|
||||
&indexer.vecs.height_to_first_txindex,
|
||||
&indexes.height_to_txindex_count,
|
||||
exit,
|
||||
)?;
|
||||
@@ -289,7 +289,7 @@ impl ComputedVecsFromTxindex<Bitcoin> {
|
||||
|
||||
let starting_index = self.height.starting_index(starting_indexes.height);
|
||||
|
||||
(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)
|
||||
.try_for_each(|height| -> Result<()> {
|
||||
if let Some(first) = self.height.first.as_mut() {
|
||||
@@ -470,7 +470,7 @@ impl ComputedVecsFromTxindex<Dollars> {
|
||||
|
||||
let mut close_iter = fetched.chainindexes_to_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)
|
||||
.try_for_each(|height| -> Result<()> {
|
||||
let price = *close_iter.unwrap_get_inner(height);
|
||||
|
||||
@@ -24,8 +24,11 @@ pub struct ComputedRatioVecsFromDateIndex {
|
||||
pub ratio_1w_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_1m_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_1y_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_4y_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_1y_sma_momentum_oscillator: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_standard_deviation: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_4y_sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_1y_sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p99_9: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p99_5: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p99: ComputedVecsFromDateIndex<StoredF32>,
|
||||
@@ -51,6 +54,8 @@ pub struct ComputedRatioVecsFromDateIndex {
|
||||
pub ratio_m2sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_m3sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_zscore: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_4y_zscore: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_1y_zscore: ComputedVecsFromDateIndex<StoredF32>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
@@ -62,8 +67,9 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
compute_source: bool,
|
||||
version: Version,
|
||||
format: Format,
|
||||
options: StorableVecGeneatorOptions,
|
||||
) -> color_eyre::Result<Self> {
|
||||
let options = StorableVecGeneatorOptions::default().add_last();
|
||||
|
||||
Ok(Self {
|
||||
price: compute_source.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
@@ -116,6 +122,14 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
ratio_4y_sma: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_4y_sma"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
ratio_1y_sma_momentum_oscillator: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_1y_sma_momentum_oscillator"),
|
||||
@@ -124,9 +138,25 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
ratio_standard_deviation: ComputedVecsFromDateIndex::forced_import(
|
||||
ratio_sd: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_standard_deviation"),
|
||||
&format!("{name}_ratio_sd"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
ratio_4y_sd: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_4y_sd"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
ratio_1y_sd: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_1y_sd"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
@@ -332,6 +362,22 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
ratio_4y_zscore: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_4y_zscore"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
ratio_1y_zscore: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_1y_zscore"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -476,6 +522,22 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_4y_sma.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sma_(
|
||||
starting_indexes.dateindex,
|
||||
self.ratio.dateindex.as_ref().unwrap(),
|
||||
4 * 365,
|
||||
exit,
|
||||
Some(min_ratio_date),
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_1y_sma_momentum_oscillator.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
@@ -527,6 +589,8 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
// }
|
||||
|
||||
let mut sma_iter = self.ratio_sma.dateindex.as_ref().unwrap().into_iter();
|
||||
let mut _4y_sma_iter = self.ratio_4y_sma.dateindex.as_ref().unwrap().into_iter();
|
||||
let mut _1y_sma_iter = self.ratio_1y_sma.dateindex.as_ref().unwrap().into_iter();
|
||||
|
||||
let nan = StoredF32::from(f32::NAN);
|
||||
self.ratio
|
||||
@@ -566,7 +630,17 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_standard_deviation
|
||||
self.ratio_sd
|
||||
.dateindex
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_4y_sd
|
||||
.dateindex
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_1y_sd
|
||||
.dateindex
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
@@ -645,12 +719,40 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
.sqrt(),
|
||||
);
|
||||
|
||||
self.ratio_standard_deviation
|
||||
self.ratio_sd
|
||||
.dateindex
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.forced_push_at(index, sd, exit)?;
|
||||
|
||||
let _4y_avg = _4y_sma_iter.unwrap_get_inner(index);
|
||||
|
||||
let _4y_sd = StoredF32::from(
|
||||
(sorted.iter().map(|v| (**v - *_4y_avg).powi(2)).sum::<f32>()
|
||||
/ (index.unwrap_to_usize() + 1) as f32)
|
||||
.sqrt(),
|
||||
);
|
||||
|
||||
self.ratio_4y_sd
|
||||
.dateindex
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.forced_push_at(index, _4y_sd, exit)?;
|
||||
|
||||
let _1y_avg = _1y_sma_iter.unwrap_get_inner(index);
|
||||
|
||||
let _1y_sd = StoredF32::from(
|
||||
(sorted.iter().map(|v| (**v - *_1y_avg).powi(2)).sum::<f32>()
|
||||
/ (index.unwrap_to_usize() + 1) as f32)
|
||||
.sqrt(),
|
||||
);
|
||||
|
||||
self.ratio_1y_sd
|
||||
.dateindex
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.forced_push_at(index, _1y_sd, exit)?;
|
||||
|
||||
self.ratio_p1sd.dateindex.as_mut().unwrap().forced_push_at(
|
||||
index,
|
||||
avg + sd,
|
||||
@@ -726,7 +828,19 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
exit,
|
||||
None as Option<&EagerVec<_, _>>,
|
||||
)?;
|
||||
self.ratio_standard_deviation.compute_rest(
|
||||
self.ratio_sd.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
None as Option<&EagerVec<_, _>>,
|
||||
)?;
|
||||
self.ratio_4y_sd.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
None as Option<&EagerVec<_, _>>,
|
||||
)?;
|
||||
self.ratio_1y_sd.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
@@ -1007,21 +1121,43 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut sma_iter = self.ratio_sma.dateindex.as_ref().unwrap().into_iter();
|
||||
let mut sd_iter = self
|
||||
.ratio_standard_deviation
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.into_iter();
|
||||
vec.compute_transform(
|
||||
vec.compute_zscore(
|
||||
starting_indexes.dateindex,
|
||||
self.ratio.dateindex.as_ref().unwrap(),
|
||||
|(i, ratio, ..)| {
|
||||
let sma = sma_iter.unwrap_get_inner(i);
|
||||
let sd = sd_iter.unwrap_get_inner(i);
|
||||
(i, (ratio - sma) / sd)
|
||||
},
|
||||
self.ratio_sma.dateindex.as_ref().unwrap(),
|
||||
self.ratio_sd.dateindex.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_4y_zscore.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_zscore(
|
||||
starting_indexes.dateindex,
|
||||
self.ratio.dateindex.as_ref().unwrap(),
|
||||
self.ratio_4y_sma.dateindex.as_ref().unwrap(),
|
||||
self.ratio_4y_sd.dateindex.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_1y_zscore.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_zscore(
|
||||
starting_indexes.dateindex,
|
||||
self.ratio.dateindex.as_ref().unwrap(),
|
||||
self.ratio_1y_sma.dateindex.as_ref().unwrap(),
|
||||
self.ratio_1y_sd.dateindex.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -1032,7 +1168,9 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
|
||||
fn mut_ratio_vecs(&mut self) -> Vec<&mut EagerVec<DateIndex, StoredF32>> {
|
||||
vec![
|
||||
self.ratio_standard_deviation.dateindex.as_mut().unwrap(),
|
||||
self.ratio_sd.dateindex.as_mut().unwrap(),
|
||||
self.ratio_4y_sd.dateindex.as_mut().unwrap(),
|
||||
self.ratio_1y_sd.dateindex.as_mut().unwrap(),
|
||||
self.ratio_p99_9.dateindex.as_mut().unwrap(),
|
||||
self.ratio_p99_5.dateindex.as_mut().unwrap(),
|
||||
self.ratio_p99.dateindex.as_mut().unwrap(),
|
||||
@@ -1056,8 +1194,11 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
self.ratio_1w_sma.vecs(),
|
||||
self.ratio_1m_sma.vecs(),
|
||||
self.ratio_1y_sma.vecs(),
|
||||
self.ratio_4y_sma.vecs(),
|
||||
self.ratio_1y_sma_momentum_oscillator.vecs(),
|
||||
self.ratio_standard_deviation.vecs(),
|
||||
self.ratio_sd.vecs(),
|
||||
self.ratio_1y_sd.vecs(),
|
||||
self.ratio_4y_sd.vecs(),
|
||||
self.ratio_p99_9.vecs(),
|
||||
self.ratio_p99_5.vecs(),
|
||||
self.ratio_p99.vecs(),
|
||||
@@ -1083,6 +1224,8 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
self.ratio_m2sd_as_price.vecs(),
|
||||
self.ratio_m3sd_as_price.vecs(),
|
||||
self.ratio_zscore.vecs(),
|
||||
self.ratio_1y_zscore.vecs(),
|
||||
self.ratio_4y_zscore.vecs(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
|
||||
@@ -205,7 +205,7 @@ impl ComputedValueVecsFromTxindex {
|
||||
|
||||
dollars_txindex.compute_if_necessary(
|
||||
starting_indexes.txindex,
|
||||
&indexer.vecs().txindex_to_txid,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -226,7 +226,11 @@ impl ComputedValueVecsFromTxindex {
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self.sats.vecs(),
|
||||
vec![&self.bitcoin_txindex as &dyn AnyCollectableVec],
|
||||
self.bitcoin.vecs(),
|
||||
self.dollars_txindex
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v as &dyn AnyCollectableVec]),
|
||||
self.dollars.as_ref().map_or(vec![], |v| v.vecs()),
|
||||
]
|
||||
.into_iter()
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use std::{fs, ops::Deref, path::Path};
|
||||
use std::{ops::Deref, path::Path};
|
||||
|
||||
use brk_core::{
|
||||
Date, DateIndex, DecadeIndex, DifficultyEpoch, EmptyOutputIndex, HalvingEpoch, Height,
|
||||
InputIndex, MonthIndex, OpReturnIndex, OutputIndex, P2ABytes, P2AIndex, P2MSIndex, P2PK33Bytes,
|
||||
P2PK33Index, P2PK65Bytes, P2PK65Index, P2PKHBytes, P2PKHIndex, P2SHBytes, P2SHIndex, P2TRBytes,
|
||||
P2TRIndex, P2WPKHBytes, P2WPKHIndex, P2WSHBytes, P2WSHIndex, QuarterIndex, Sats, StoredUsize,
|
||||
Timestamp, TxIndex, Txid, UnknownOutputIndex, Version, WeekIndex, YearIndex,
|
||||
InputIndex, MonthIndex, OpReturnIndex, OutputIndex, P2AAddressIndex, P2ABytes, P2MSOutputIndex,
|
||||
P2PK33AddressIndex, P2PK33Bytes, P2PK65AddressIndex, P2PK65Bytes, P2PKHAddressIndex,
|
||||
P2PKHBytes, P2SHAddressIndex, P2SHBytes, P2TRAddressIndex, P2TRBytes, P2WPKHAddressIndex,
|
||||
P2WPKHBytes, P2WSHAddressIndex, P2WSHBytes, QuarterIndex, Sats, StoredUsize, Timestamp,
|
||||
TxIndex, Txid, UnknownOutputIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
@@ -54,18 +55,24 @@ pub struct Vecs {
|
||||
ComputedVecFrom1<OpReturnIndex, OpReturnIndex, OpReturnIndex, TxIndex>,
|
||||
pub outputindex_to_outputindex: ComputedVecFrom1<OutputIndex, OutputIndex, OutputIndex, Sats>,
|
||||
pub outputindex_to_txindex: EagerVec<OutputIndex, TxIndex>,
|
||||
pub p2aindex_to_p2aindex: ComputedVecFrom1<P2AIndex, P2AIndex, P2AIndex, P2ABytes>,
|
||||
pub p2msindex_to_p2msindex: ComputedVecFrom1<P2MSIndex, P2MSIndex, P2MSIndex, TxIndex>,
|
||||
pub p2pk33index_to_p2pk33index:
|
||||
ComputedVecFrom1<P2PK33Index, P2PK33Index, P2PK33Index, P2PK33Bytes>,
|
||||
pub p2pk65index_to_p2pk65index:
|
||||
ComputedVecFrom1<P2PK65Index, P2PK65Index, P2PK65Index, P2PK65Bytes>,
|
||||
pub p2pkhindex_to_p2pkhindex: ComputedVecFrom1<P2PKHIndex, P2PKHIndex, P2PKHIndex, P2PKHBytes>,
|
||||
pub p2shindex_to_p2shindex: ComputedVecFrom1<P2SHIndex, P2SHIndex, P2SHIndex, P2SHBytes>,
|
||||
pub p2trindex_to_p2trindex: ComputedVecFrom1<P2TRIndex, P2TRIndex, P2TRIndex, P2TRBytes>,
|
||||
pub p2wpkhindex_to_p2wpkhindex:
|
||||
ComputedVecFrom1<P2WPKHIndex, P2WPKHIndex, P2WPKHIndex, P2WPKHBytes>,
|
||||
pub p2wshindex_to_p2wshindex: ComputedVecFrom1<P2WSHIndex, P2WSHIndex, P2WSHIndex, P2WSHBytes>,
|
||||
pub p2aaddressindex_to_p2aaddressindex:
|
||||
ComputedVecFrom1<P2AAddressIndex, P2AAddressIndex, P2AAddressIndex, P2ABytes>,
|
||||
pub p2msoutputindex_to_p2msoutputindex:
|
||||
ComputedVecFrom1<P2MSOutputIndex, P2MSOutputIndex, P2MSOutputIndex, TxIndex>,
|
||||
pub p2pk33addressindex_to_p2pk33addressindex:
|
||||
ComputedVecFrom1<P2PK33AddressIndex, P2PK33AddressIndex, P2PK33AddressIndex, P2PK33Bytes>,
|
||||
pub p2pk65addressindex_to_p2pk65addressindex:
|
||||
ComputedVecFrom1<P2PK65AddressIndex, P2PK65AddressIndex, P2PK65AddressIndex, P2PK65Bytes>,
|
||||
pub p2pkhaddressindex_to_p2pkhaddressindex:
|
||||
ComputedVecFrom1<P2PKHAddressIndex, P2PKHAddressIndex, P2PKHAddressIndex, P2PKHBytes>,
|
||||
pub p2shaddressindex_to_p2shaddressindex:
|
||||
ComputedVecFrom1<P2SHAddressIndex, P2SHAddressIndex, P2SHAddressIndex, P2SHBytes>,
|
||||
pub p2traddressindex_to_p2traddressindex:
|
||||
ComputedVecFrom1<P2TRAddressIndex, P2TRAddressIndex, P2TRAddressIndex, P2TRBytes>,
|
||||
pub p2wpkhaddressindex_to_p2wpkhaddressindex:
|
||||
ComputedVecFrom1<P2WPKHAddressIndex, P2WPKHAddressIndex, P2WPKHAddressIndex, P2WPKHBytes>,
|
||||
pub p2wshaddressindex_to_p2wshaddressindex:
|
||||
ComputedVecFrom1<P2WSHAddressIndex, P2WSHAddressIndex, P2WSHAddressIndex, P2WSHBytes>,
|
||||
pub quarterindex_to_first_monthindex: EagerVec<QuarterIndex, MonthIndex>,
|
||||
pub quarterindex_to_monthindex_count: EagerVec<QuarterIndex, StoredUsize>,
|
||||
pub quarterindex_to_quarterindex: EagerVec<QuarterIndex, QuarterIndex>,
|
||||
@@ -94,15 +101,13 @@ impl Vecs {
|
||||
computation: Computation,
|
||||
format: Format,
|
||||
) -> color_eyre::Result<Self> {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
let outputindex_to_outputindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().outputindex_to_value.boxed_clone(),
|
||||
indexer.vecs.outputindex_to_value.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
|
||||
@@ -112,7 +117,7 @@ impl Vecs {
|
||||
"inputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().inputindex_to_outputindex.boxed_clone(),
|
||||
indexer.vecs.inputindex_to_outputindex.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
|
||||
@@ -122,7 +127,7 @@ impl Vecs {
|
||||
"txindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().txindex_to_txid.boxed_clone(),
|
||||
indexer.vecs.txindex_to_txid.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
|
||||
@@ -132,8 +137,8 @@ impl Vecs {
|
||||
"input_count",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().txindex_to_first_inputindex.boxed_clone(),
|
||||
indexer.vecs().inputindex_to_outputindex.boxed_clone(),
|
||||
indexer.vecs.txindex_to_first_inputindex.boxed_clone(),
|
||||
indexer.vecs.inputindex_to_outputindex.boxed_clone(),
|
||||
|index: TxIndex, txindex_to_first_inputindex_iter, inputindex_to_outputindex_iter| {
|
||||
let txindex = index.unwrap_to_usize();
|
||||
txindex_to_first_inputindex_iter
|
||||
@@ -155,8 +160,8 @@ impl Vecs {
|
||||
"output_count",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().txindex_to_first_outputindex.boxed_clone(),
|
||||
indexer.vecs().outputindex_to_value.boxed_clone(),
|
||||
indexer.vecs.txindex_to_first_outputindex.boxed_clone(),
|
||||
indexer.vecs.outputindex_to_value.boxed_clone(),
|
||||
|index: TxIndex, txindex_to_first_outputindex_iter, outputindex_to_value_iter| {
|
||||
let txindex = index.unwrap_to_usize();
|
||||
txindex_to_first_outputindex_iter
|
||||
@@ -172,85 +177,85 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
let p2pk33index_to_p2pk33index = ComputedVec::forced_import_or_init_from_1(
|
||||
let p2pk33addressindex_to_p2pk33addressindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2pk33index",
|
||||
"p2pk33addressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().p2pk33index_to_p2pk33bytes.boxed_clone(),
|
||||
indexer.vecs.p2pk33addressindex_to_p2pk33bytes.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
let p2pk65index_to_p2pk65index = ComputedVec::forced_import_or_init_from_1(
|
||||
let p2pk65addressindex_to_p2pk65addressindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2pk65index",
|
||||
"p2pk65addressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().p2pk65index_to_p2pk65bytes.boxed_clone(),
|
||||
indexer.vecs.p2pk65addressindex_to_p2pk65bytes.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
let p2pkhindex_to_p2pkhindex = ComputedVec::forced_import_or_init_from_1(
|
||||
let p2pkhaddressindex_to_p2pkhaddressindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2pkhindex",
|
||||
"p2pkhaddressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().p2pkhindex_to_p2pkhbytes.boxed_clone(),
|
||||
indexer.vecs.p2pkhaddressindex_to_p2pkhbytes.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
let p2shindex_to_p2shindex = ComputedVec::forced_import_or_init_from_1(
|
||||
let p2shaddressindex_to_p2shaddressindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2shindex",
|
||||
"p2shaddressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().p2shindex_to_p2shbytes.boxed_clone(),
|
||||
indexer.vecs.p2shaddressindex_to_p2shbytes.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
let p2trindex_to_p2trindex = ComputedVec::forced_import_or_init_from_1(
|
||||
let p2traddressindex_to_p2traddressindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2trindex",
|
||||
"p2traddressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().p2trindex_to_p2trbytes.boxed_clone(),
|
||||
indexer.vecs.p2traddressindex_to_p2trbytes.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
let p2wpkhindex_to_p2wpkhindex = ComputedVec::forced_import_or_init_from_1(
|
||||
let p2wpkhaddressindex_to_p2wpkhaddressindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2wpkhindex",
|
||||
"p2wpkhaddressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().p2wpkhindex_to_p2wpkhbytes.boxed_clone(),
|
||||
indexer.vecs.p2wpkhaddressindex_to_p2wpkhbytes.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
let p2wshindex_to_p2wshindex = ComputedVec::forced_import_or_init_from_1(
|
||||
let p2wshaddressindex_to_p2wshaddressindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2wshindex",
|
||||
"p2wshaddressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().p2wshindex_to_p2wshbytes.boxed_clone(),
|
||||
indexer.vecs.p2wshaddressindex_to_p2wshbytes.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
let p2aindex_to_p2aindex = ComputedVec::forced_import_or_init_from_1(
|
||||
let p2aaddressindex_to_p2aaddressindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2aindex",
|
||||
"p2aaddressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().p2aindex_to_p2abytes.boxed_clone(),
|
||||
indexer.vecs.p2aaddressindex_to_p2abytes.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
let p2msindex_to_p2msindex = ComputedVec::forced_import_or_init_from_1(
|
||||
let p2msoutputindex_to_p2msoutputindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2msindex",
|
||||
"p2msoutputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().p2msindex_to_txindex.boxed_clone(),
|
||||
indexer.vecs.p2msoutputindex_to_txindex.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
let emptyoutputindex_to_emptyoutputindex = ComputedVec::forced_import_or_init_from_1(
|
||||
@@ -259,7 +264,7 @@ impl Vecs {
|
||||
"emptyoutputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().emptyoutputindex_to_txindex.boxed_clone(),
|
||||
indexer.vecs.emptyoutputindex_to_txindex.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
let unknownoutputindex_to_unknownoutputindex = ComputedVec::forced_import_or_init_from_1(
|
||||
@@ -268,7 +273,7 @@ impl Vecs {
|
||||
"unknownoutputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().unknownoutputindex_to_txindex.boxed_clone(),
|
||||
indexer.vecs.unknownoutputindex_to_txindex.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
let opreturnindex_to_opreturnindex = ComputedVec::forced_import_or_init_from_1(
|
||||
@@ -277,7 +282,7 @@ impl Vecs {
|
||||
"opreturnindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().opreturnindex_to_txindex.boxed_clone(),
|
||||
indexer.vecs.opreturnindex_to_txindex.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
|
||||
@@ -286,15 +291,15 @@ impl Vecs {
|
||||
inputindex_to_inputindex,
|
||||
opreturnindex_to_opreturnindex,
|
||||
outputindex_to_outputindex,
|
||||
p2aindex_to_p2aindex,
|
||||
p2msindex_to_p2msindex,
|
||||
p2pk33index_to_p2pk33index,
|
||||
p2pk65index_to_p2pk65index,
|
||||
p2pkhindex_to_p2pkhindex,
|
||||
p2shindex_to_p2shindex,
|
||||
p2trindex_to_p2trindex,
|
||||
p2wpkhindex_to_p2wpkhindex,
|
||||
p2wshindex_to_p2wshindex,
|
||||
p2aaddressindex_to_p2aaddressindex,
|
||||
p2msoutputindex_to_p2msoutputindex,
|
||||
p2pk33addressindex_to_p2pk33addressindex,
|
||||
p2pk65addressindex_to_p2pk65addressindex,
|
||||
p2pkhaddressindex_to_p2pkhaddressindex,
|
||||
p2shaddressindex_to_p2shaddressindex,
|
||||
p2traddressindex_to_p2traddressindex,
|
||||
p2wpkhaddressindex_to_p2wpkhaddressindex,
|
||||
p2wshaddressindex_to_p2wshaddressindex,
|
||||
txindex_to_input_count,
|
||||
txindex_to_output_count,
|
||||
txindex_to_txindex,
|
||||
@@ -543,108 +548,115 @@ impl Vecs {
|
||||
starting_indexes: brk_indexer::Indexes,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<Indexes> {
|
||||
let indexer_vecs = indexer.vecs();
|
||||
|
||||
// ---
|
||||
// OutputIndex
|
||||
// ---
|
||||
|
||||
self.outputindex_to_outputindex.compute_if_necessary(
|
||||
starting_indexes.outputindex,
|
||||
&indexer_vecs.outputindex_to_value,
|
||||
&indexer.vecs.outputindex_to_value,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.txindex_to_output_count.compute_if_necessary(
|
||||
starting_indexes.txindex,
|
||||
&indexer_vecs.txindex_to_txid,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.txindex_to_input_count.compute_if_necessary(
|
||||
starting_indexes.txindex,
|
||||
&indexer_vecs.txindex_to_txid,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.outputindex_to_txindex.compute_inverse_less_to_more(
|
||||
starting_indexes.txindex,
|
||||
&indexer_vecs.txindex_to_first_outputindex,
|
||||
&indexer.vecs.txindex_to_first_outputindex,
|
||||
&self.txindex_to_output_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.p2pk33index_to_p2pk33index.compute_if_necessary(
|
||||
starting_indexes.p2pk33index,
|
||||
&indexer_vecs.p2pk33index_to_p2pk33bytes,
|
||||
exit,
|
||||
)?;
|
||||
self.p2pk33addressindex_to_p2pk33addressindex
|
||||
.compute_if_necessary(
|
||||
starting_indexes.p2pk33addressindex,
|
||||
&indexer.vecs.p2pk33addressindex_to_p2pk33bytes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.p2pk65index_to_p2pk65index.compute_if_necessary(
|
||||
starting_indexes.p2pk65index,
|
||||
&indexer_vecs.p2pk65index_to_p2pk65bytes,
|
||||
exit,
|
||||
)?;
|
||||
self.p2pk65addressindex_to_p2pk65addressindex
|
||||
.compute_if_necessary(
|
||||
starting_indexes.p2pk65addressindex,
|
||||
&indexer.vecs.p2pk65addressindex_to_p2pk65bytes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.p2pkhindex_to_p2pkhindex.compute_if_necessary(
|
||||
starting_indexes.p2pkhindex,
|
||||
&indexer_vecs.p2pkhindex_to_p2pkhbytes,
|
||||
exit,
|
||||
)?;
|
||||
self.p2pkhaddressindex_to_p2pkhaddressindex
|
||||
.compute_if_necessary(
|
||||
starting_indexes.p2pkhaddressindex,
|
||||
&indexer.vecs.p2pkhaddressindex_to_p2pkhbytes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.p2shindex_to_p2shindex.compute_if_necessary(
|
||||
starting_indexes.p2shindex,
|
||||
&indexer_vecs.p2shindex_to_p2shbytes,
|
||||
exit,
|
||||
)?;
|
||||
self.p2shaddressindex_to_p2shaddressindex
|
||||
.compute_if_necessary(
|
||||
starting_indexes.p2shaddressindex,
|
||||
&indexer.vecs.p2shaddressindex_to_p2shbytes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.p2trindex_to_p2trindex.compute_if_necessary(
|
||||
starting_indexes.p2trindex,
|
||||
&indexer_vecs.p2trindex_to_p2trbytes,
|
||||
exit,
|
||||
)?;
|
||||
self.p2traddressindex_to_p2traddressindex
|
||||
.compute_if_necessary(
|
||||
starting_indexes.p2traddressindex,
|
||||
&indexer.vecs.p2traddressindex_to_p2trbytes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.p2wpkhindex_to_p2wpkhindex.compute_if_necessary(
|
||||
starting_indexes.p2wpkhindex,
|
||||
&indexer_vecs.p2wpkhindex_to_p2wpkhbytes,
|
||||
exit,
|
||||
)?;
|
||||
self.p2wpkhaddressindex_to_p2wpkhaddressindex
|
||||
.compute_if_necessary(
|
||||
starting_indexes.p2wpkhaddressindex,
|
||||
&indexer.vecs.p2wpkhaddressindex_to_p2wpkhbytes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.p2wshindex_to_p2wshindex.compute_if_necessary(
|
||||
starting_indexes.p2wshindex,
|
||||
&indexer_vecs.p2wshindex_to_p2wshbytes,
|
||||
exit,
|
||||
)?;
|
||||
self.p2wshaddressindex_to_p2wshaddressindex
|
||||
.compute_if_necessary(
|
||||
starting_indexes.p2wshaddressindex,
|
||||
&indexer.vecs.p2wshaddressindex_to_p2wshbytes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.emptyoutputindex_to_emptyoutputindex
|
||||
.compute_if_necessary(
|
||||
starting_indexes.emptyoutputindex,
|
||||
&indexer_vecs.emptyoutputindex_to_txindex,
|
||||
&indexer.vecs.emptyoutputindex_to_txindex,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.p2msindex_to_p2msindex.compute_if_necessary(
|
||||
starting_indexes.p2msindex,
|
||||
&indexer_vecs.p2msindex_to_txindex,
|
||||
exit,
|
||||
)?;
|
||||
self.p2msoutputindex_to_p2msoutputindex
|
||||
.compute_if_necessary(
|
||||
starting_indexes.p2msoutputindex,
|
||||
&indexer.vecs.p2msoutputindex_to_txindex,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.opreturnindex_to_opreturnindex.compute_if_necessary(
|
||||
starting_indexes.opreturnindex,
|
||||
&indexer_vecs.opreturnindex_to_txindex,
|
||||
&indexer.vecs.opreturnindex_to_txindex,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.p2aindex_to_p2aindex.compute_if_necessary(
|
||||
starting_indexes.p2aindex,
|
||||
&indexer_vecs.p2aindex_to_p2abytes,
|
||||
exit,
|
||||
)?;
|
||||
self.p2aaddressindex_to_p2aaddressindex
|
||||
.compute_if_necessary(
|
||||
starting_indexes.p2aaddressindex,
|
||||
&indexer.vecs.p2aaddressindex_to_p2abytes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.unknownoutputindex_to_unknownoutputindex
|
||||
.compute_if_necessary(
|
||||
starting_indexes.unknownoutputindex,
|
||||
&indexer_vecs.unknownoutputindex_to_txindex,
|
||||
&indexer.vecs.unknownoutputindex_to_txindex,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -654,7 +666,7 @@ impl Vecs {
|
||||
|
||||
self.inputindex_to_inputindex.compute_if_necessary(
|
||||
starting_indexes.inputindex,
|
||||
&indexer_vecs.inputindex_to_outputindex,
|
||||
&indexer.vecs.inputindex_to_outputindex,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -664,20 +676,20 @@ impl Vecs {
|
||||
|
||||
self.txindex_to_txindex.compute_if_necessary(
|
||||
starting_indexes.txindex,
|
||||
&indexer_vecs.txindex_to_txid,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.height_to_txindex_count.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer_vecs.height_to_first_txindex,
|
||||
&indexer_vecs.txindex_to_txid,
|
||||
&indexer.vecs.height_to_first_txindex,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.txindex_to_height.compute_inverse_less_to_more(
|
||||
starting_indexes.height,
|
||||
&indexer_vecs.height_to_first_txindex,
|
||||
&indexer.vecs.height_to_first_txindex,
|
||||
&self.height_to_txindex_count,
|
||||
exit,
|
||||
)?;
|
||||
@@ -688,13 +700,13 @@ impl Vecs {
|
||||
|
||||
self.height_to_height.compute_from_index(
|
||||
starting_indexes.height,
|
||||
&indexer_vecs.height_to_weight,
|
||||
&indexer.vecs.height_to_weight,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.height_to_date.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer_vecs.height_to_timestamp,
|
||||
&indexer.vecs.height_to_timestamp,
|
||||
|(h, t, ..)| (h, Date::from(t)),
|
||||
exit,
|
||||
)?;
|
||||
@@ -702,7 +714,7 @@ impl Vecs {
|
||||
let mut prev_timestamp_fixed = None;
|
||||
self.height_to_timestamp_fixed.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer_vecs.height_to_timestamp,
|
||||
&indexer.vecs.height_to_timestamp,
|
||||
|(h, timestamp, height_to_timestamp_fixed_iter)| {
|
||||
if prev_timestamp_fixed.is_none() {
|
||||
if let Some(prev_h) = h.decremented() {
|
||||
@@ -779,7 +791,7 @@ impl Vecs {
|
||||
self.dateindex_to_height_count.compute_count_from_indexes(
|
||||
starting_dateindex,
|
||||
&self.dateindex_to_first_height,
|
||||
&indexer_vecs.height_to_weight,
|
||||
&indexer.vecs.height_to_weight,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -829,7 +841,7 @@ impl Vecs {
|
||||
|
||||
self.height_to_difficultyepoch.compute_from_index(
|
||||
starting_indexes.height,
|
||||
&indexer_vecs.height_to_weight,
|
||||
&indexer.vecs.height_to_weight,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -979,7 +991,7 @@ impl Vecs {
|
||||
|
||||
self.height_to_halvingepoch.compute_from_index(
|
||||
starting_indexes.height,
|
||||
&indexer_vecs.height_to_weight,
|
||||
&indexer.vecs.height_to_weight,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -1079,15 +1091,15 @@ impl Vecs {
|
||||
&self.monthindex_to_yearindex,
|
||||
&self.opreturnindex_to_opreturnindex,
|
||||
&self.outputindex_to_outputindex,
|
||||
&self.p2aindex_to_p2aindex,
|
||||
&self.p2msindex_to_p2msindex,
|
||||
&self.p2pk33index_to_p2pk33index,
|
||||
&self.p2pk65index_to_p2pk65index,
|
||||
&self.p2pkhindex_to_p2pkhindex,
|
||||
&self.p2shindex_to_p2shindex,
|
||||
&self.p2trindex_to_p2trindex,
|
||||
&self.p2wpkhindex_to_p2wpkhindex,
|
||||
&self.p2wshindex_to_p2wshindex,
|
||||
&self.p2aaddressindex_to_p2aaddressindex,
|
||||
&self.p2msoutputindex_to_p2msoutputindex,
|
||||
&self.p2pk33addressindex_to_p2pk33addressindex,
|
||||
&self.p2pk65addressindex_to_p2pk65addressindex,
|
||||
&self.p2pkhaddressindex_to_p2pkhaddressindex,
|
||||
&self.p2shaddressindex_to_p2shaddressindex,
|
||||
&self.p2traddressindex_to_p2traddressindex,
|
||||
&self.p2wpkhaddressindex_to_p2wpkhaddressindex,
|
||||
&self.p2wshaddressindex_to_p2wshaddressindex,
|
||||
&self.quarterindex_to_first_monthindex,
|
||||
&self.quarterindex_to_monthindex_count,
|
||||
&self.quarterindex_to_quarterindex,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{fs, path::Path, thread};
|
||||
use std::{path::Path, thread};
|
||||
|
||||
use brk_core::{Date, DateIndex, Dollars, Height, Sats, StoredF32, StoredUsize, Version};
|
||||
use brk_exit::Exit;
|
||||
@@ -36,11 +36,15 @@ pub struct Vecs {
|
||||
pub indexes_to_55d_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_89d_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_144d_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_200d_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_1y_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_2y_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_200w_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_4y_sma: ComputedRatioVecsFromDateIndex,
|
||||
|
||||
pub indexes_to_200d_sma_x2_4: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub indexes_to_200d_sma_x0_8: ComputedVecsFromDateIndex<Dollars>,
|
||||
|
||||
pub price_1d_ago: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub price_1w_ago: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub price_1m_ago: ComputedVecsFromDateIndex<Dollars>,
|
||||
@@ -164,8 +168,6 @@ impl Vecs {
|
||||
_computation: Computation,
|
||||
format: Format,
|
||||
) -> color_eyre::Result<Self> {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
Ok(Self {
|
||||
height_to_marketcap: EagerVec::forced_import(
|
||||
path,
|
||||
@@ -240,7 +242,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_8d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -248,7 +249,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_13d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -256,7 +256,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_21d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -264,7 +263,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_1m_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -272,7 +270,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_34d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -280,7 +277,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_55d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -288,7 +284,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_89d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -296,7 +291,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_144d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -304,7 +298,13 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_200d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"200d_sma",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)?,
|
||||
indexes_to_1y_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -312,7 +312,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_2y_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -320,7 +319,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_200w_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -328,7 +326,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_4y_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -336,7 +333,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
|
||||
_1d_returns: ComputedVecsFromDateIndex::forced_import(
|
||||
@@ -1215,6 +1211,23 @@ impl Vecs {
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
|
||||
indexes_to_200d_sma_x2_4: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"200d_sma_x2_4",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_200d_sma_x0_8: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"200d_sma_x0_8",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1771,6 +1784,7 @@ impl Vecs {
|
||||
(&mut self.indexes_to_55d_sma, 55),
|
||||
(&mut self.indexes_to_89d_sma, 89),
|
||||
(&mut self.indexes_to_144d_sma, 144),
|
||||
(&mut self.indexes_to_200d_sma, 200),
|
||||
(&mut self.indexes_to_1y_sma, 365),
|
||||
(&mut self.indexes_to_2y_sma, 2 * 365),
|
||||
(&mut self.indexes_to_200w_sma, 200 * 7),
|
||||
@@ -1797,7 +1811,51 @@ impl Vecs {
|
||||
});
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
})?;
|
||||
|
||||
self.indexes_to_200d_sma_x0_8.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_200d_sma
|
||||
.price
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
|(i, v, ..)| (i, v * 0.8),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_200d_sma_x2_4.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_200d_sma
|
||||
.price
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
|(i, v, ..)| (i, v * 2.4),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
@@ -1817,10 +1875,13 @@ impl Vecs {
|
||||
self.indexes_to_55d_sma.vecs(),
|
||||
self.indexes_to_89d_sma.vecs(),
|
||||
self.indexes_to_144d_sma.vecs(),
|
||||
self.indexes_to_200d_sma.vecs(),
|
||||
self.indexes_to_1y_sma.vecs(),
|
||||
self.indexes_to_2y_sma.vecs(),
|
||||
self.indexes_to_200w_sma.vecs(),
|
||||
self.indexes_to_4y_sma.vecs(),
|
||||
self.indexes_to_200d_sma_x0_8.vecs(),
|
||||
self.indexes_to_200d_sma_x2_4.vecs(),
|
||||
self.price_1d_ago.vecs(),
|
||||
self.price_1w_ago.vecs(),
|
||||
self.price_1m_ago.vecs(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{fs, path::Path};
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{DifficultyEpoch, HalvingEpoch, StoredF64, Version};
|
||||
use brk_exit::Exit;
|
||||
@@ -27,8 +27,6 @@ impl Vecs {
|
||||
_computation: Computation,
|
||||
format: Format,
|
||||
) -> color_eyre::Result<Self> {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
Ok(Self {
|
||||
indexes_to_difficulty: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
@@ -116,7 +114,7 @@ impl Vecs {
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&indexer.vecs().height_to_difficulty),
|
||||
Some(&indexer.vecs.height_to_difficulty),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{fs, path::Path, thread};
|
||||
use std::{path::Path, thread};
|
||||
|
||||
use brk_core::Version;
|
||||
use brk_exit::Exit;
|
||||
@@ -7,6 +7,7 @@ use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyCollectableVec, Computation, Format};
|
||||
|
||||
pub mod blocks;
|
||||
pub mod cointime;
|
||||
pub mod constants;
|
||||
pub mod fetched;
|
||||
pub mod grouped;
|
||||
@@ -31,6 +32,7 @@ pub struct Vecs {
|
||||
pub transactions: transactions::Vecs,
|
||||
pub stateful: stateful::Vecs,
|
||||
pub fetched: Option<fetched::Vecs>,
|
||||
pub cointime: cointime::Vecs,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -42,8 +44,6 @@ impl Vecs {
|
||||
computation: Computation,
|
||||
format: Format,
|
||||
) -> color_eyre::Result<Self> {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
let (indexes, fetched) = thread::scope(|s| {
|
||||
let indexes_handle = s.spawn(|| {
|
||||
indexes::Vecs::forced_import(
|
||||
@@ -112,6 +112,13 @@ impl Vecs {
|
||||
format,
|
||||
fetched.as_ref(),
|
||||
)?,
|
||||
cointime: cointime::Vecs::forced_import(
|
||||
path,
|
||||
version + VERSION + Version::ZERO,
|
||||
computation,
|
||||
format,
|
||||
fetched.as_ref(),
|
||||
)?,
|
||||
indexes,
|
||||
fetched,
|
||||
})
|
||||
@@ -124,7 +131,8 @@ impl Vecs {
|
||||
fetcher: Option<&mut Fetcher>,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
let starting_indexes = self.indexes.compute(indexer, starting_indexes, exit)?;
|
||||
info!("Computing indexes...");
|
||||
let mut starting_indexes = self.indexes.compute(indexer, starting_indexes, exit)?;
|
||||
|
||||
info!("Computing constants...");
|
||||
self.constants
|
||||
@@ -177,7 +185,17 @@ impl Vecs {
|
||||
&self.transactions,
|
||||
self.fetched.as_ref(),
|
||||
&self.market,
|
||||
starting_indexes,
|
||||
&mut starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.cointime.compute(
|
||||
indexer,
|
||||
&self.indexes,
|
||||
&starting_indexes,
|
||||
self.fetched.as_ref(),
|
||||
&self.transactions,
|
||||
&self.stateful,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -193,6 +211,7 @@ impl Vecs {
|
||||
self.market.vecs(),
|
||||
self.transactions.vecs(),
|
||||
self.stateful.vecs(),
|
||||
self.cointime.vecs(),
|
||||
self.fetched.as_ref().map_or(vec![], |v| v.vecs()),
|
||||
]
|
||||
.into_iter()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use core::panic;
|
||||
use std::{fs, path::Path};
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{
|
||||
Bitcoin, DateIndex, Dollars, Height, Result, Sats, StoredF32, StoredF64, StoredUsize, Version,
|
||||
@@ -57,7 +57,7 @@ pub struct Vecs {
|
||||
pub indexes_to_coinblocks_destroyed: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_coindays_destroyed: ComputedVecsFromHeight<StoredF64>,
|
||||
pub dateindex_to_adjusted_spent_output_profit_ratio: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub dateindex_to_realized_cap_30d_change: Option<EagerVec<DateIndex, Dollars>>,
|
||||
pub indexes_to_realized_cap_30d_change: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub dateindex_to_sell_side_risk_ratio: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub dateindex_to_spent_output_profit_ratio: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub indexes_to_adjusted_value_created: Option<ComputedVecsFromHeight<Dollars>>,
|
||||
@@ -89,6 +89,10 @@ pub struct Vecs {
|
||||
Option<EagerVec<Height, StoredF32>>,
|
||||
pub indexes_to_net_unrealized_profit_and_loss_relative_to_market_cap:
|
||||
Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub indexes_to_realized_profit_relative_to_realized_cap:
|
||||
Option<ComputedVecsFromHeight<StoredF32>>,
|
||||
pub indexes_to_realized_loss_relative_to_realized_cap:
|
||||
Option<ComputedVecsFromHeight<StoredF32>>,
|
||||
pub indexes_to_net_realized_profit_and_loss_relative_to_realized_cap:
|
||||
Option<ComputedVecsFromHeight<StoredF32>>,
|
||||
pub height_to_supply_even_value: Option<ComputedHeightValueVecs>,
|
||||
@@ -117,6 +121,12 @@ pub struct Vecs {
|
||||
Option<ComputedVecsFromDateIndex<StoredF64>>,
|
||||
pub indexes_to_supply_in_profit_relative_to_circulating_supply:
|
||||
Option<ComputedVecsFromDateIndex<StoredF64>>,
|
||||
pub indexes_to_cumulative_net_realized_profit_and_loss_30d_change:
|
||||
Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_realized_cap:
|
||||
Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_market_cap:
|
||||
Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -133,8 +143,6 @@ impl Vecs {
|
||||
) -> color_eyre::Result<Self> {
|
||||
let compute_dollars = fetched.is_some();
|
||||
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
// let prefix = |s: &str| cohort_name.map_or(s.to_string(), |name| format!("{s}_{name}"));
|
||||
|
||||
let suffix = |s: &str| cohort_name.map_or(s.to_string(), |name| format!("{name}_{s}"));
|
||||
@@ -412,7 +420,6 @@ impl Vecs {
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -432,7 +439,9 @@ impl Vecs {
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -452,7 +461,9 @@ impl Vecs {
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -463,7 +474,7 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
StorableVecGeneatorOptions::default().add_sum().add_cumulative(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -558,12 +569,14 @@ impl Vecs {
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
dateindex_to_realized_cap_30d_change: compute_dollars.then(|| {
|
||||
EagerVec::forced_import(
|
||||
indexes_to_realized_cap_30d_change: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&suffix("realized_cap_30d_change"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -574,7 +587,9 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -686,15 +701,37 @@ impl Vecs {
|
||||
.unwrap()
|
||||
},
|
||||
),
|
||||
indexes_to_realized_profit_relative_to_realized_cap: compute_dollars.then(|| {
|
||||
ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
&suffix("realized_profit_relative_to_realized_cap"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_realized_loss_relative_to_realized_cap: compute_dollars.then(|| {
|
||||
ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
&suffix("realized_loss_relative_to_realized_cap"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_net_realized_profit_and_loss_relative_to_realized_cap: compute_dollars.then(
|
||||
|| {
|
||||
ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
&suffix("net_realized_profit_and_loss_relative_to_realized_cap"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
)
|
||||
.unwrap()
|
||||
},
|
||||
@@ -893,7 +930,7 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::TWO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
StorableVecGeneatorOptions::default().add_sum().add_cumulative(),
|
||||
)?,
|
||||
indexes_to_coindays_destroyed: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
@@ -901,8 +938,41 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::TWO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
StorableVecGeneatorOptions::default().add_sum().add_cumulative(),
|
||||
)?,
|
||||
indexes_to_cumulative_net_realized_profit_and_loss_30d_change: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("cumulative_{}", suffix("net_realized_profit_and_loss_30d_change")),
|
||||
true,
|
||||
version + VERSION + Version::new(3),
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last()
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_realized_cap: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("cumulative_{}", suffix("net_realized_profit_and_loss_30d_change_relative_to_realized_cap")),
|
||||
true,
|
||||
version + VERSION + Version::new(3),
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last()
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_market_cap: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("cumulative_{}", suffix("net_realized_profit_and_loss_30d_change_relative_to_market_cap")),
|
||||
true,
|
||||
version + VERSION + Version::new(3),
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last()
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1877,6 +1947,7 @@ impl Vecs {
|
||||
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
||||
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
||||
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
if let Some(v) = self
|
||||
@@ -2021,18 +2092,26 @@ impl Vecs {
|
||||
Some(self.height_to_adjusted_value_destroyed.as_ref().unwrap()),
|
||||
)?;
|
||||
|
||||
self.dateindex_to_realized_cap_30d_change
|
||||
self.indexes_to_realized_cap_30d_change
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_change(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_realized_cap
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.unwrap_last(),
|
||||
30,
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_change(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_realized_cap
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.unwrap_last(),
|
||||
30,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_net_realized_profit_and_loss
|
||||
@@ -2280,6 +2359,42 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_realized_profit_relative_to_realized_cap
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.height,
|
||||
self.height_to_realized_profit.as_ref().unwrap(),
|
||||
*height_to_realized_cap.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_realized_loss_relative_to_realized_cap
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.height,
|
||||
self.height_to_realized_loss.as_ref().unwrap(),
|
||||
*height_to_realized_cap.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_net_realized_profit_and_loss_relative_to_realized_cap
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
@@ -2435,6 +2550,64 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_change(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_net_realized_profit_and_loss
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.unwrap_cumulative(),
|
||||
30,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_realized_cap.
|
||||
as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change.as_ref().unwrap().dateindex.as_ref().unwrap(),
|
||||
*dateindex_to_realized_cap.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_market_cap.
|
||||
as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change.as_ref().unwrap().dateindex.as_ref().unwrap(),
|
||||
market.indexes_to_marketcap.dateindex.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
if let Some(height_to_supply_even_relative_to_circulating_supply) = self
|
||||
.height_to_supply_even_relative_to_circulating_supply
|
||||
.as_mut()
|
||||
@@ -2618,9 +2791,9 @@ impl Vecs {
|
||||
self.indexes_to_adjusted_value_destroyed
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.dateindex_to_realized_cap_30d_change
|
||||
self.indexes_to_realized_cap_30d_change
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v]),
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_net_realized_profit_and_loss
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
@@ -2703,6 +2876,12 @@ impl Vecs {
|
||||
self.indexes_to_net_unrealized_profit_and_loss_relative_to_market_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_realized_profit_relative_to_realized_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_realized_loss_relative_to_realized_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_net_realized_profit_and_loss_relative_to_realized_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
@@ -2756,6 +2935,12 @@ impl Vecs {
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_coinblocks_destroyed.vecs(),
|
||||
self.indexes_to_coindays_destroyed.vecs(),
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_realized_cap.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_market_cap.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
|
||||
@@ -4,8 +4,8 @@ use brk_core::{DateIndex, Height, InputIndex, OutputIndex, OutputType, Result, S
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{
|
||||
AnyCollectableVec, AnyVec, BaseVecIterator, CollectableVec, Computation, EagerVec, Format,
|
||||
GenericStoredVec, StoredIndex, StoredVec, UnsafeSlice, VecIterator,
|
||||
AnyCollectableVec, AnyVec, CollectableVec, Computation, EagerVec, Format, GenericStoredVec,
|
||||
StoredIndex, StoredVec, UnsafeSlice, VecIterator,
|
||||
};
|
||||
use log::info;
|
||||
use outputs::OutputCohorts;
|
||||
@@ -39,7 +39,7 @@ pub struct Vecs {
|
||||
pub indexes_to_unspendable_supply: ComputedValueVecsFromHeight,
|
||||
pub height_to_opreturn_supply: EagerVec<Height, Sats>,
|
||||
pub indexes_to_opreturn_supply: ComputedValueVecsFromHeight,
|
||||
utxos_vecs: Outputs<(OutputFilter, cohort::Vecs)>,
|
||||
pub utxos_vecs: Outputs<(OutputFilter, cohort::Vecs)>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -1202,21 +1202,19 @@ impl Vecs {
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
market: &market::Vecs,
|
||||
// Must take ownership as its indexes will be updated for this specific function
|
||||
mut starting_indexes: Indexes,
|
||||
starting_indexes: &mut Indexes,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
let indexer_vecs = indexer.vecs();
|
||||
|
||||
let height_to_first_outputindex = &indexer_vecs.height_to_first_outputindex;
|
||||
let height_to_first_inputindex = &indexer_vecs.height_to_first_inputindex;
|
||||
let height_to_first_outputindex = &indexer.vecs.height_to_first_outputindex;
|
||||
let height_to_first_inputindex = &indexer.vecs.height_to_first_inputindex;
|
||||
let height_to_output_count = transactions.indexes_to_output_count.height.unwrap_sum();
|
||||
let height_to_input_count = transactions.indexes_to_input_count.height.unwrap_sum();
|
||||
let inputindex_to_outputindex = &indexer_vecs.inputindex_to_outputindex;
|
||||
let outputindex_to_value = &indexer_vecs.outputindex_to_value;
|
||||
let inputindex_to_outputindex = &indexer.vecs.inputindex_to_outputindex;
|
||||
let outputindex_to_value = &indexer.vecs.outputindex_to_value;
|
||||
let txindex_to_height = &indexes.txindex_to_height;
|
||||
let height_to_timestamp_fixed = &indexes.height_to_timestamp_fixed;
|
||||
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 height_to_unclaimed_rewards = transactions
|
||||
.indexes_to_unclaimed_rewards
|
||||
.sats
|
||||
@@ -1289,7 +1287,7 @@ impl Vecs {
|
||||
base_version + self.height_to_opreturn_supply.inner_version(),
|
||||
)?;
|
||||
|
||||
let mut chain_state: Vec<BlockState>;
|
||||
let mut chain_state: Vec<BlockState> = vec![];
|
||||
let mut chain_state_starting_height = Height::from(self.chain_state.len());
|
||||
|
||||
let stateful_starting_height = match separate_utxo_vecs
|
||||
@@ -1322,287 +1320,286 @@ impl Vecs {
|
||||
.collect::<Vec<_>>();
|
||||
chain_state_starting_height
|
||||
}
|
||||
Ordering::Less => {
|
||||
// todo!("rollback instead");
|
||||
chain_state = vec![];
|
||||
chain_state_starting_height = Height::ZERO;
|
||||
Height::ZERO
|
||||
}
|
||||
Ordering::Less => Height::ZERO,
|
||||
};
|
||||
if stateful_starting_height.is_zero() {
|
||||
info!("Starting processing utxos from the start");
|
||||
separate_utxo_vecs
|
||||
.par_iter_mut()
|
||||
.try_for_each(|(_, v)| v.state.price_to_amount.reset())?;
|
||||
}
|
||||
|
||||
let starting_height = starting_indexes
|
||||
.height
|
||||
.min(stateful_starting_height)
|
||||
.min(Height::from(self.height_to_unspendable_supply.len()))
|
||||
.min(Height::from(self.height_to_opreturn_supply.len()));
|
||||
|
||||
if starting_height == Height::from(height_to_date_fixed.len()) {
|
||||
return Ok(());
|
||||
if starting_height.is_zero() {
|
||||
info!("Starting processing utxos from the start");
|
||||
|
||||
// todo!("rollback instead");
|
||||
chain_state = vec![];
|
||||
chain_state_starting_height = Height::ZERO;
|
||||
|
||||
separate_utxo_vecs
|
||||
.par_iter_mut()
|
||||
.try_for_each(|(_, v)| v.state.price_to_amount.reset())?;
|
||||
}
|
||||
|
||||
// ---
|
||||
// INIT
|
||||
// ---
|
||||
if starting_height < Height::from(height_to_date_fixed.len()) {
|
||||
starting_indexes.update_from_height(starting_height, indexes);
|
||||
|
||||
separate_utxo_vecs
|
||||
.par_iter_mut()
|
||||
.for_each(|(_, v)| v.init(starting_height));
|
||||
separate_utxo_vecs
|
||||
.par_iter_mut()
|
||||
.for_each(|(_, v)| v.init(starting_height));
|
||||
|
||||
let mut unspendable_supply = if let Some(prev_height) = starting_height.decremented() {
|
||||
self.height_to_unspendable_supply
|
||||
.into_iter()
|
||||
.unwrap_get_inner(prev_height)
|
||||
} else {
|
||||
Sats::ZERO
|
||||
};
|
||||
let mut opreturn_supply = if let Some(prev_height) = starting_height.decremented() {
|
||||
self.height_to_opreturn_supply
|
||||
.into_iter()
|
||||
.unwrap_get_inner(prev_height)
|
||||
} else {
|
||||
Sats::ZERO
|
||||
};
|
||||
|
||||
let mut height = starting_height;
|
||||
starting_indexes.update_from_height(height, indexes);
|
||||
|
||||
(height.unwrap_to_usize()..height_to_first_outputindex_iter.len())
|
||||
.map(Height::from)
|
||||
.try_for_each(|_height| -> color_eyre::Result<()> {
|
||||
height = _height;
|
||||
|
||||
self.utxos_vecs
|
||||
.as_mut_separate_vecs()
|
||||
.iter_mut()
|
||||
.for_each(|(_, v)| v.state.reset_single_iteration_values());
|
||||
|
||||
info!("Processing chain at {height}...");
|
||||
|
||||
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
|
||||
let price = height_to_close_iter
|
||||
.as_mut()
|
||||
.map(|i| *i.unwrap_get_inner(height));
|
||||
let first_outputindex = height_to_first_outputindex_iter
|
||||
.unwrap_get_inner(height)
|
||||
.unwrap_to_usize();
|
||||
let first_inputindex = height_to_first_inputindex_iter
|
||||
.unwrap_get_inner(height)
|
||||
.unwrap_to_usize();
|
||||
let output_count = height_to_output_count_iter.unwrap_get_inner(height);
|
||||
let input_count = height_to_input_count_iter.unwrap_get_inner(height);
|
||||
|
||||
let (mut height_to_sent, mut received) = thread::scope(|s| {
|
||||
if chain_state_starting_height <= height {
|
||||
s.spawn(|| {
|
||||
self.utxos_vecs
|
||||
.tick_tock_next_block(&chain_state, timestamp);
|
||||
});
|
||||
}
|
||||
|
||||
let sent_handle = s.spawn(|| {
|
||||
// Skip coinbase
|
||||
(first_inputindex + 1..first_inputindex + *input_count)
|
||||
.into_par_iter()
|
||||
.map(InputIndex::from)
|
||||
.map(|inputindex| {
|
||||
let outputindex = inputindex_to_outputindex
|
||||
.get_or_read(inputindex, &inputindex_to_outputindex_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let value = outputindex_to_value
|
||||
.get_or_read(outputindex, &outputindex_to_value_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let input_type = outputindex_to_outputtype
|
||||
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
// dbg!(input_type);
|
||||
|
||||
if input_type.is_unspendable() {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
let input_txindex = outputindex_to_txindex
|
||||
.get_or_read(outputindex, &outputindex_to_txindex_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let height = txindex_to_height
|
||||
.get_or_read(input_txindex, &txindex_to_height_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
(height, value, input_type)
|
||||
})
|
||||
.fold(
|
||||
BTreeMap::<Height, Transacted>::default,
|
||||
|mut tree, (height, value, input_type)| {
|
||||
tree.entry(height).or_default().iterate(value, input_type);
|
||||
tree
|
||||
},
|
||||
)
|
||||
.reduce(BTreeMap::<Height, Transacted>::default, |first, second| {
|
||||
let (mut source, to_consume) = if first.len() > second.len() {
|
||||
(first, second)
|
||||
} else {
|
||||
(second, first)
|
||||
};
|
||||
to_consume.into_iter().for_each(|(k, v)| {
|
||||
*source.entry(k).or_default() += v;
|
||||
});
|
||||
source
|
||||
})
|
||||
});
|
||||
|
||||
let received_handle = s.spawn(|| {
|
||||
(first_outputindex..first_outputindex + *output_count)
|
||||
.into_par_iter()
|
||||
.map(OutputIndex::from)
|
||||
.map(|outputindex| {
|
||||
let value = outputindex_to_value
|
||||
.get_or_read(outputindex, &outputindex_to_value_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let output_type = outputindex_to_outputtype
|
||||
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
(value, output_type)
|
||||
})
|
||||
.fold(
|
||||
Transacted::default,
|
||||
|mut transacted, (value, output_type)| {
|
||||
transacted.iterate(value, output_type);
|
||||
transacted
|
||||
},
|
||||
)
|
||||
.reduce(Transacted::default, |acc, transacted| acc + transacted)
|
||||
});
|
||||
|
||||
(sent_handle.join().unwrap(), received_handle.join().unwrap())
|
||||
});
|
||||
|
||||
unspendable_supply += received
|
||||
.by_type
|
||||
.unspendable
|
||||
.as_vec()
|
||||
let mut unspendable_supply = if let Some(prev_height) = starting_height.decremented() {
|
||||
self.height_to_unspendable_supply
|
||||
.into_iter()
|
||||
.map(|state| state.value)
|
||||
.sum::<Sats>()
|
||||
+ height_to_unclaimed_rewards_iter.unwrap_get_inner(height);
|
||||
|
||||
opreturn_supply += received.by_type.unspendable.opreturn.value;
|
||||
|
||||
if height == Height::new(0) {
|
||||
received = Transacted::default();
|
||||
unspendable_supply += Sats::FIFTY_BTC;
|
||||
} else if height == Height::new(91_842) || height == Height::new(91_880) {
|
||||
// Need to destroy invalid coinbases due to duplicate txids
|
||||
if height == Height::new(91_842) {
|
||||
height_to_sent.entry(Height::new(91_812)).or_default()
|
||||
} else {
|
||||
height_to_sent.entry(Height::new(91_722)).or_default()
|
||||
}
|
||||
.iterate(Sats::FIFTY_BTC, OutputType::P2PK65);
|
||||
};
|
||||
|
||||
if chain_state_starting_height <= height {
|
||||
// Push current block state before processing sends and receives
|
||||
chain_state.push(BlockState {
|
||||
supply: received.spendable_supply.clone(),
|
||||
price,
|
||||
timestamp,
|
||||
});
|
||||
|
||||
self.utxos_vecs.receive(received, height, price);
|
||||
|
||||
let unsafe_chain_state = UnsafeSlice::new(&mut chain_state);
|
||||
|
||||
height_to_sent.par_iter().for_each(|(height, sent)| unsafe {
|
||||
(*unsafe_chain_state.get(height.unwrap_to_usize())).supply -=
|
||||
&sent.spendable_supply;
|
||||
});
|
||||
|
||||
self.utxos_vecs.send(height_to_sent, chain_state.as_slice());
|
||||
} else {
|
||||
dbg!(chain_state_starting_height, height);
|
||||
panic!("temp, just making sure")
|
||||
}
|
||||
|
||||
let mut separate_utxo_vecs = self.utxos_vecs.as_mut_separate_vecs();
|
||||
|
||||
separate_utxo_vecs
|
||||
.iter_mut()
|
||||
.try_for_each(|(_, v)| v.forced_pushed_at(height, exit))?;
|
||||
|
||||
self.height_to_unspendable_supply.forced_push_at(
|
||||
height,
|
||||
unspendable_supply,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
.unwrap_get_inner(prev_height)
|
||||
} else {
|
||||
Sats::ZERO
|
||||
};
|
||||
let mut opreturn_supply = if let Some(prev_height) = starting_height.decremented() {
|
||||
self.height_to_opreturn_supply
|
||||
.forced_push_at(height, opreturn_supply, exit)?;
|
||||
.into_iter()
|
||||
.unwrap_get_inner(prev_height)
|
||||
} else {
|
||||
Sats::ZERO
|
||||
};
|
||||
|
||||
let date = height_to_date_fixed_iter.unwrap_get_inner(height);
|
||||
let dateindex = DateIndex::try_from(date).unwrap();
|
||||
let date_first_height = dateindex_to_first_height_iter.unwrap_get_inner(dateindex);
|
||||
let date_height_count = dateindex_to_height_count_iter.unwrap_get_inner(dateindex);
|
||||
let is_date_last_height = date_first_height
|
||||
+ Height::from(date_height_count).decremented().unwrap()
|
||||
== height;
|
||||
let date_price = dateindex_to_close_iter
|
||||
.as_mut()
|
||||
.map(|v| is_date_last_height.then(|| *v.unwrap_get_inner(dateindex)));
|
||||
let mut height = starting_height;
|
||||
|
||||
separate_utxo_vecs.par_iter_mut().try_for_each(|(_, v)| {
|
||||
v.compute_then_force_push_unrealized_states(
|
||||
(height.unwrap_to_usize()..height_to_date_fixed.len())
|
||||
.map(Height::from)
|
||||
.try_for_each(|_height| -> color_eyre::Result<()> {
|
||||
height = _height;
|
||||
|
||||
self.utxos_vecs
|
||||
.as_mut_separate_vecs()
|
||||
.iter_mut()
|
||||
.for_each(|(_, v)| v.state.reset_single_iteration_values());
|
||||
|
||||
info!("Processing chain at {height}...");
|
||||
|
||||
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
|
||||
let price = height_to_close_iter
|
||||
.as_mut()
|
||||
.map(|i| *i.unwrap_get_inner(height));
|
||||
let first_outputindex = height_to_first_outputindex_iter
|
||||
.unwrap_get_inner(height)
|
||||
.unwrap_to_usize();
|
||||
let first_inputindex = height_to_first_inputindex_iter
|
||||
.unwrap_get_inner(height)
|
||||
.unwrap_to_usize();
|
||||
let output_count = height_to_output_count_iter.unwrap_get_inner(height);
|
||||
let input_count = height_to_input_count_iter.unwrap_get_inner(height);
|
||||
|
||||
let (mut height_to_sent, mut received) = thread::scope(|s| {
|
||||
if chain_state_starting_height <= height {
|
||||
s.spawn(|| {
|
||||
self.utxos_vecs
|
||||
.tick_tock_next_block(&chain_state, timestamp);
|
||||
});
|
||||
}
|
||||
|
||||
let sent_handle = s.spawn(|| {
|
||||
// Skip coinbase
|
||||
(first_inputindex + 1..first_inputindex + *input_count)
|
||||
.into_par_iter()
|
||||
.map(InputIndex::from)
|
||||
.map(|inputindex| {
|
||||
let outputindex = inputindex_to_outputindex
|
||||
.get_or_read(inputindex, &inputindex_to_outputindex_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let value = outputindex_to_value
|
||||
.get_or_read(outputindex, &outputindex_to_value_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let input_type = outputindex_to_outputtype
|
||||
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
// dbg!(input_type);
|
||||
|
||||
if input_type.is_unspendable() {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
let input_txindex = outputindex_to_txindex
|
||||
.get_or_read(outputindex, &outputindex_to_txindex_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let height = txindex_to_height
|
||||
.get_or_read(input_txindex, &txindex_to_height_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
(height, value, input_type)
|
||||
})
|
||||
.fold(
|
||||
BTreeMap::<Height, Transacted>::default,
|
||||
|mut tree, (height, value, input_type)| {
|
||||
tree.entry(height).or_default().iterate(value, input_type);
|
||||
tree
|
||||
},
|
||||
)
|
||||
.reduce(BTreeMap::<Height, Transacted>::default, |first, second| {
|
||||
let (mut source, to_consume) = if first.len() > second.len() {
|
||||
(first, second)
|
||||
} else {
|
||||
(second, first)
|
||||
};
|
||||
to_consume.into_iter().for_each(|(k, v)| {
|
||||
*source.entry(k).or_default() += v;
|
||||
});
|
||||
source
|
||||
})
|
||||
});
|
||||
|
||||
let received_handle = s.spawn(|| {
|
||||
(first_outputindex..first_outputindex + *output_count)
|
||||
.into_par_iter()
|
||||
.map(OutputIndex::from)
|
||||
.map(|outputindex| {
|
||||
let value = outputindex_to_value
|
||||
.get_or_read(outputindex, &outputindex_to_value_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let output_type = outputindex_to_outputtype
|
||||
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
(value, output_type)
|
||||
})
|
||||
.fold(
|
||||
Transacted::default,
|
||||
|mut transacted, (value, output_type)| {
|
||||
transacted.iterate(value, output_type);
|
||||
transacted
|
||||
},
|
||||
)
|
||||
.reduce(Transacted::default, |acc, transacted| acc + transacted)
|
||||
});
|
||||
|
||||
(sent_handle.join().unwrap(), received_handle.join().unwrap())
|
||||
});
|
||||
|
||||
unspendable_supply += received
|
||||
.by_type
|
||||
.unspendable
|
||||
.as_vec()
|
||||
.into_iter()
|
||||
.map(|state| state.value)
|
||||
.sum::<Sats>()
|
||||
+ height_to_unclaimed_rewards_iter.unwrap_get_inner(height);
|
||||
|
||||
opreturn_supply += received.by_type.unspendable.opreturn.value;
|
||||
|
||||
if height == Height::new(0) {
|
||||
received = Transacted::default();
|
||||
unspendable_supply += Sats::FIFTY_BTC;
|
||||
} else if height == Height::new(91_842) || height == Height::new(91_880) {
|
||||
// Need to destroy invalid coinbases due to duplicate txids
|
||||
if height == Height::new(91_842) {
|
||||
height_to_sent.entry(Height::new(91_812)).or_default()
|
||||
} else {
|
||||
height_to_sent.entry(Height::new(91_722)).or_default()
|
||||
}
|
||||
.iterate(Sats::FIFTY_BTC, OutputType::P2PK65);
|
||||
};
|
||||
|
||||
if chain_state_starting_height <= height {
|
||||
// Push current block state before processing sends and receives
|
||||
chain_state.push(BlockState {
|
||||
supply: received.spendable_supply.clone(),
|
||||
price,
|
||||
timestamp,
|
||||
});
|
||||
|
||||
self.utxos_vecs.receive(received, height, price);
|
||||
|
||||
let unsafe_chain_state = UnsafeSlice::new(&mut chain_state);
|
||||
|
||||
height_to_sent.par_iter().for_each(|(height, sent)| unsafe {
|
||||
(*unsafe_chain_state.get(height.unwrap_to_usize())).supply -=
|
||||
&sent.spendable_supply;
|
||||
});
|
||||
|
||||
self.utxos_vecs.send(height_to_sent, chain_state.as_slice());
|
||||
} else {
|
||||
dbg!(chain_state_starting_height, height);
|
||||
panic!("temp, just making sure")
|
||||
}
|
||||
|
||||
let mut separate_utxo_vecs = self.utxos_vecs.as_mut_separate_vecs();
|
||||
|
||||
separate_utxo_vecs
|
||||
.iter_mut()
|
||||
.try_for_each(|(_, v)| v.forced_pushed_at(height, exit))?;
|
||||
|
||||
self.height_to_unspendable_supply.forced_push_at(
|
||||
height,
|
||||
price,
|
||||
is_date_last_height.then_some(dateindex),
|
||||
date_price,
|
||||
unspendable_supply,
|
||||
exit,
|
||||
)
|
||||
)?;
|
||||
|
||||
self.height_to_opreturn_supply
|
||||
.forced_push_at(height, opreturn_supply, exit)?;
|
||||
|
||||
let date = height_to_date_fixed_iter.unwrap_get_inner(height);
|
||||
let dateindex = DateIndex::try_from(date).unwrap();
|
||||
let date_first_height =
|
||||
dateindex_to_first_height_iter.unwrap_get_inner(dateindex);
|
||||
let date_height_count =
|
||||
dateindex_to_height_count_iter.unwrap_get_inner(dateindex);
|
||||
let is_date_last_height = date_first_height
|
||||
+ Height::from(date_height_count).decremented().unwrap()
|
||||
== height;
|
||||
let date_price = dateindex_to_close_iter
|
||||
.as_mut()
|
||||
.map(|v| is_date_last_height.then(|| *v.unwrap_get_inner(dateindex)));
|
||||
|
||||
separate_utxo_vecs.par_iter_mut().try_for_each(|(_, v)| {
|
||||
v.compute_then_force_push_unrealized_states(
|
||||
height,
|
||||
price,
|
||||
is_date_last_height.then_some(dateindex),
|
||||
date_price,
|
||||
exit,
|
||||
)
|
||||
})?;
|
||||
|
||||
if height != Height::ZERO && height.unwrap_to_usize() % 20_000 == 0 {
|
||||
info!("Flushing...");
|
||||
exit.block();
|
||||
self.flush_states(height, &chain_state, exit)?;
|
||||
exit.release();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
if height != Height::ZERO && height.unwrap_to_usize() % 20_000 == 0 {
|
||||
info!("Flushing...");
|
||||
exit.block();
|
||||
self.flush_states(height, &chain_state, exit)?;
|
||||
exit.release();
|
||||
}
|
||||
exit.block();
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
info!("Flushing...");
|
||||
|
||||
exit.block();
|
||||
self.flush_states(height, &chain_state, exit)?;
|
||||
}
|
||||
|
||||
info!("Flushing...");
|
||||
|
||||
self.flush_states(height, &chain_state, exit)?;
|
||||
|
||||
info!("Computing overlaping...");
|
||||
info!("Computing overlapping...");
|
||||
|
||||
self.utxos_vecs
|
||||
.compute_overlaping_vecs(&starting_indexes, exit)?;
|
||||
.compute_overlapping_vecs(starting_indexes, exit)?;
|
||||
|
||||
info!("Computing rest part 1...");
|
||||
|
||||
@@ -1610,7 +1607,7 @@ impl Vecs {
|
||||
.as_mut_vecs()
|
||||
.par_iter_mut()
|
||||
.try_for_each(|(_, v)| {
|
||||
v.compute_rest_part1(indexer, indexes, fetched, &starting_indexes, exit)
|
||||
v.compute_rest_part1(indexer, indexes, fetched, starting_indexes, exit)
|
||||
})?;
|
||||
|
||||
info!("Computing rest part 2...");
|
||||
@@ -1625,6 +1622,13 @@ impl Vecs {
|
||||
.dateindex
|
||||
.clone();
|
||||
let height_to_realized_cap = self.utxos_vecs.all.1.height_to_realized_cap.clone();
|
||||
let dateindex_to_realized_cap = self
|
||||
.utxos_vecs
|
||||
.all
|
||||
.1
|
||||
.indexes_to_realized_cap
|
||||
.as_ref()
|
||||
.map(|v| v.dateindex.unwrap_last().clone());
|
||||
|
||||
self.utxos_vecs
|
||||
.as_mut_vecs()
|
||||
@@ -1634,11 +1638,12 @@ impl Vecs {
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
&starting_indexes,
|
||||
starting_indexes,
|
||||
market,
|
||||
&height_to_supply,
|
||||
dateindex_to_supply.as_ref().unwrap(),
|
||||
height_to_realized_cap.as_ref(),
|
||||
dateindex_to_realized_cap.as_ref(),
|
||||
exit,
|
||||
)
|
||||
})?;
|
||||
@@ -1646,7 +1651,7 @@ impl Vecs {
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
&starting_indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.height_to_unspendable_supply),
|
||||
)?;
|
||||
@@ -1654,7 +1659,7 @@ impl Vecs {
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
&starting_indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.height_to_opreturn_supply),
|
||||
)?;
|
||||
|
||||
@@ -14,7 +14,7 @@ pub trait OutputCohorts {
|
||||
fn tick_tock_next_block(&mut self, chain_state: &[BlockState], timestamp: Timestamp);
|
||||
fn send(&mut self, height_to_sent: BTreeMap<Height, Transacted>, chain_state: &[BlockState]);
|
||||
fn receive(&mut self, received: Transacted, height: Height, price: Option<Dollars>);
|
||||
fn compute_overlaping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()>;
|
||||
fn compute_overlapping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()>;
|
||||
}
|
||||
|
||||
impl OutputCohorts for Outputs<(OutputFilter, cohort::Vecs)> {
|
||||
@@ -172,7 +172,7 @@ impl OutputCohorts for Outputs<(OutputFilter, cohort::Vecs)> {
|
||||
});
|
||||
}
|
||||
|
||||
fn compute_overlaping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
fn compute_overlapping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
let by_date_range = self.by_date_range.as_vec();
|
||||
let by_size_range = self.by_size_range.as_vec();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{fs, path::Path};
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{
|
||||
CheckedSub, Feerate, HalvingEpoch, Height, InputIndex, OutputIndex, Sats, StoredU32,
|
||||
@@ -98,16 +98,14 @@ impl Vecs {
|
||||
) -> color_eyre::Result<Self> {
|
||||
let compute_dollars = fetched.is_some();
|
||||
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
let inputindex_to_value = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"value",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().inputindex_to_outputindex.boxed_clone(),
|
||||
indexer.vecs().outputindex_to_value.boxed_clone(),
|
||||
indexer.vecs.inputindex_to_outputindex.boxed_clone(),
|
||||
indexer.vecs.outputindex_to_value.boxed_clone(),
|
||||
|index: InputIndex, inputindex_to_outputindex_iter, outputindex_to_value_iter| {
|
||||
inputindex_to_outputindex_iter
|
||||
.next_at(index.unwrap_to_usize())
|
||||
@@ -133,8 +131,8 @@ impl Vecs {
|
||||
"weight",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().txindex_to_base_size.boxed_clone(),
|
||||
indexer.vecs().txindex_to_total_size.boxed_clone(),
|
||||
indexer.vecs.txindex_to_base_size.boxed_clone(),
|
||||
indexer.vecs.txindex_to_total_size.boxed_clone(),
|
||||
|index: TxIndex, txindex_to_base_size_iter, txindex_to_total_size_iter| {
|
||||
let index = index.unwrap_to_usize();
|
||||
txindex_to_base_size_iter
|
||||
@@ -179,7 +177,7 @@ impl Vecs {
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexes.txindex_to_height.boxed_clone(),
|
||||
indexer.vecs().height_to_first_txindex.boxed_clone(),
|
||||
indexer.vecs.height_to_first_txindex.boxed_clone(),
|
||||
|index: TxIndex, txindex_to_height_iter, height_to_first_txindex_iter| {
|
||||
txindex_to_height_iter
|
||||
.next_at(index.unwrap_to_usize())
|
||||
@@ -202,7 +200,7 @@ impl Vecs {
|
||||
"input_value",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().txindex_to_first_inputindex.boxed_clone(),
|
||||
indexer.vecs.txindex_to_first_inputindex.boxed_clone(),
|
||||
indexes.txindex_to_input_count.boxed_clone(),
|
||||
inputindex_to_value.boxed_clone(),
|
||||
|index: TxIndex,
|
||||
@@ -251,9 +249,9 @@ impl Vecs {
|
||||
"output_value",
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
indexer.vecs().txindex_to_first_outputindex.boxed_clone(),
|
||||
indexer.vecs.txindex_to_first_outputindex.boxed_clone(),
|
||||
indexes.txindex_to_output_count.boxed_clone(),
|
||||
indexer.vecs().outputindex_to_value.boxed_clone(),
|
||||
indexer.vecs.outputindex_to_value.boxed_clone(),
|
||||
|index: TxIndex,
|
||||
txindex_to_first_outputindex_iter,
|
||||
txindex_to_output_count_iter,
|
||||
@@ -688,8 +686,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_txindex,
|
||||
&indexer.vecs().txindex_to_txid,
|
||||
&indexer.vecs.height_to_first_txindex,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -713,7 +711,7 @@ impl Vecs {
|
||||
|
||||
let compute_indexes_to_tx_vany =
|
||||
|indexes_to_tx_vany: &mut ComputedVecsFromHeight<StoredUsize>, txversion| {
|
||||
let mut txindex_to_txversion_iter = indexer.vecs().txindex_to_txversion.iter();
|
||||
let mut txindex_to_txversion_iter = indexer.vecs.txindex_to_txversion.iter();
|
||||
indexes_to_tx_vany.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
@@ -722,8 +720,8 @@ impl Vecs {
|
||||
|vec, indexer, _, starting_indexes, exit| {
|
||||
vec.compute_filtered_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_txindex,
|
||||
&indexer.vecs().txindex_to_txid,
|
||||
&indexer.vecs.height_to_first_txindex,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
|txindex| {
|
||||
let v = txindex_to_txversion_iter.unwrap_get_inner(txindex);
|
||||
v == txversion
|
||||
@@ -739,31 +737,31 @@ impl Vecs {
|
||||
|
||||
self.txindex_to_is_coinbase.compute_if_necessary(
|
||||
starting_indexes.txindex,
|
||||
&indexer.vecs().txindex_to_txid,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.txindex_to_weight.compute_if_necessary(
|
||||
starting_indexes.txindex,
|
||||
&indexer.vecs().txindex_to_txid,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.txindex_to_vsize.compute_if_necessary(
|
||||
starting_indexes.txindex,
|
||||
&indexer.vecs().txindex_to_txid,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.inputindex_to_value.compute_if_necessary(
|
||||
starting_indexes.inputindex,
|
||||
&indexer.vecs().inputindex_to_outputindex,
|
||||
&indexer.vecs.inputindex_to_outputindex,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.txindex_to_output_value.compute_if_necessary(
|
||||
starting_indexes.txindex,
|
||||
&indexer.vecs().txindex_to_txid,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -775,9 +773,9 @@ impl Vecs {
|
||||
// |vec, indexer, _, starting_indexes, exit| {
|
||||
// vec.compute_sum_from_indexes(
|
||||
// starting_indexes.txindex,
|
||||
// &indexer.vecs().txindex_to_first_outputindex,
|
||||
// &indexer.vecs.txindex_to_first_outputindex,
|
||||
// self.indexes_to_output_count.txindex.as_ref().unwrap(),
|
||||
// &indexer.vecs().outputindex_to_value,
|
||||
// &indexer.vecs.outputindex_to_value,
|
||||
// exit,
|
||||
// )
|
||||
// },
|
||||
@@ -785,7 +783,7 @@ impl Vecs {
|
||||
|
||||
self.txindex_to_input_value.compute_if_necessary(
|
||||
starting_indexes.txindex,
|
||||
&indexer.vecs().txindex_to_txid,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -797,7 +795,7 @@ impl Vecs {
|
||||
// |vec, indexer, _, starting_indexes, exit| {
|
||||
// vec.compute_sum_from_indexes(
|
||||
// starting_indexes.txindex,
|
||||
// &indexer.vecs().txindex_to_first_inputindex,
|
||||
// &indexer.vecs.txindex_to_first_inputindex,
|
||||
// self.indexes_to_input_count.txindex.as_ref().unwrap(),
|
||||
// &self.inputindex_to_value,
|
||||
// exit,
|
||||
@@ -807,13 +805,13 @@ impl Vecs {
|
||||
|
||||
self.txindex_to_fee.compute_if_necessary(
|
||||
starting_indexes.txindex,
|
||||
&indexer.vecs().txindex_to_txid,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.txindex_to_feerate.compute_if_necessary(
|
||||
starting_indexes.txindex,
|
||||
&indexer.vecs().txindex_to_txid,
|
||||
&indexer.vecs.txindex_to_txid,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -858,12 +856,12 @@ impl Vecs {
|
||||
exit,
|
||||
|vec, indexer, _, starting_indexes, exit| {
|
||||
let mut txindex_to_first_outputindex_iter =
|
||||
indexer.vecs().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_value_iter = indexer.vecs().outputindex_to_value.iter();
|
||||
let mut outputindex_to_value_iter = indexer.vecs.outputindex_to_value.iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_txindex,
|
||||
&indexer.vecs.height_to_first_txindex,
|
||||
|(height, txindex, ..)| {
|
||||
let first_outputindex = txindex_to_first_outputindex_iter
|
||||
.unwrap_get_inner(txindex)
|
||||
@@ -933,8 +931,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_p2aindex,
|
||||
&indexer.vecs().p2aindex_to_p2abytes,
|
||||
&indexer.vecs.height_to_first_p2aaddressindex,
|
||||
&indexer.vecs.p2aaddressindex_to_p2abytes,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -948,8 +946,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_p2msindex,
|
||||
&indexer.vecs().p2msindex_to_txindex,
|
||||
&indexer.vecs.height_to_first_p2msoutputindex,
|
||||
&indexer.vecs.p2msoutputindex_to_txindex,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -963,8 +961,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_p2pk33index,
|
||||
&indexer.vecs().p2pk33index_to_p2pk33bytes,
|
||||
&indexer.vecs.height_to_first_p2pk33addressindex,
|
||||
&indexer.vecs.p2pk33addressindex_to_p2pk33bytes,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -978,8 +976,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_p2pk65index,
|
||||
&indexer.vecs().p2pk65index_to_p2pk65bytes,
|
||||
&indexer.vecs.height_to_first_p2pk65addressindex,
|
||||
&indexer.vecs.p2pk65addressindex_to_p2pk65bytes,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -993,8 +991,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_p2pkhindex,
|
||||
&indexer.vecs().p2pkhindex_to_p2pkhbytes,
|
||||
&indexer.vecs.height_to_first_p2pkhaddressindex,
|
||||
&indexer.vecs.p2pkhaddressindex_to_p2pkhbytes,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -1008,8 +1006,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_p2shindex,
|
||||
&indexer.vecs().p2shindex_to_p2shbytes,
|
||||
&indexer.vecs.height_to_first_p2shaddressindex,
|
||||
&indexer.vecs.p2shaddressindex_to_p2shbytes,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -1023,8 +1021,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_p2trindex,
|
||||
&indexer.vecs().p2trindex_to_p2trbytes,
|
||||
&indexer.vecs.height_to_first_p2traddressindex,
|
||||
&indexer.vecs.p2traddressindex_to_p2trbytes,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -1038,8 +1036,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_p2wpkhindex,
|
||||
&indexer.vecs().p2wpkhindex_to_p2wpkhbytes,
|
||||
&indexer.vecs.height_to_first_p2wpkhaddressindex,
|
||||
&indexer.vecs.p2wpkhaddressindex_to_p2wpkhbytes,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -1053,8 +1051,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_p2wshindex,
|
||||
&indexer.vecs().p2wshindex_to_p2wshbytes,
|
||||
&indexer.vecs.height_to_first_p2wshaddressindex,
|
||||
&indexer.vecs.p2wshaddressindex_to_p2wshbytes,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -1068,8 +1066,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_opreturnindex,
|
||||
&indexer.vecs().opreturnindex_to_txindex,
|
||||
&indexer.vecs.height_to_first_opreturnindex,
|
||||
&indexer.vecs.opreturnindex_to_txindex,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -1083,8 +1081,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_unknownoutputindex,
|
||||
&indexer.vecs().unknownoutputindex_to_txindex,
|
||||
&indexer.vecs.height_to_first_unknownoutputindex,
|
||||
&indexer.vecs.unknownoutputindex_to_txindex,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -1098,8 +1096,8 @@ impl Vecs {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs().height_to_first_emptyoutputindex,
|
||||
&indexer.vecs().emptyoutputindex_to_txindex,
|
||||
&indexer.vecs.height_to_first_emptyoutputindex,
|
||||
&indexer.vecs.emptyoutputindex_to_txindex,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
|
||||
@@ -20,6 +20,7 @@ pub enum Error {
|
||||
|
||||
WrongEndian,
|
||||
DifferentVersion { found: Version, expected: Version },
|
||||
UnexpectedData,
|
||||
MmapsVecIsTooSmall,
|
||||
IndexTooHigh,
|
||||
EmptyVec,
|
||||
@@ -102,12 +103,13 @@ impl fmt::Display for Error {
|
||||
Error::BincodeDecodeError(error) => Debug::fmt(&error, f),
|
||||
Error::BincodeEncodeError(error) => Debug::fmt(&error, f),
|
||||
Error::ZeroCopyError => write!(f, "ZeroCopy error"),
|
||||
Error::UnexpectedData => write!(f, "Unexpected data"),
|
||||
|
||||
Error::WrongEndian => write!(f, "Wrong endian"),
|
||||
Error::DifferentVersion { found, expected } => {
|
||||
write!(
|
||||
f,
|
||||
"Different version; found: {found:?}, expected: {expected:?}"
|
||||
"Different version found: {found:?}, expected: {expected:?}"
|
||||
)
|
||||
}
|
||||
Error::MmapsVecIsTooSmall => write!(f, "Mmaps vec is too small"),
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
|
||||
mod enums;
|
||||
mod structs;
|
||||
mod traits;
|
||||
mod utils;
|
||||
|
||||
pub use enums::*;
|
||||
pub use structs::*;
|
||||
pub use traits::*;
|
||||
pub use utils::*;
|
||||
|
||||
@@ -7,7 +7,7 @@ use serde::Serialize;
|
||||
// use color_eyre::eyre::eyre;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Error};
|
||||
use crate::{CheckedSub, Error, Printable};
|
||||
|
||||
use super::Date;
|
||||
|
||||
@@ -93,3 +93,13 @@ impl fmt::Display for DateIndex {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for DateIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"dateindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["d", "date", "dateindex"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::{fmt::Debug, ops::Add};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::{Date, DateIndex, YearIndex};
|
||||
|
||||
@@ -83,3 +83,13 @@ impl From<YearIndex> for DecadeIndex {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for DecadeIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"decadeindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["decade", "decadeindex"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::Height;
|
||||
|
||||
@@ -80,3 +80,13 @@ impl CheckedSub for DifficultyEpoch {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for DifficultyEpoch {
|
||||
fn to_string() -> &'static str {
|
||||
"difficultyepoch"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["difficulty", "difficultyepoch"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,6 +139,24 @@ impl Div<usize> for Dollars {
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<StoredF64> for Dollars {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: StoredF64) -> Self::Output {
|
||||
self / f64::from(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<f64> for Dollars {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: f64) -> Self::Output {
|
||||
if self.is_nan() || rhs == 0.0 {
|
||||
Dollars::NAN
|
||||
} else {
|
||||
Dollars::from(Cents::from(Self::from(self.0 / rhs)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Bitcoin> for Dollars {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: Bitcoin) -> Self::Output {
|
||||
@@ -178,6 +196,24 @@ impl Mul<usize> for Close<Dollars> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<StoredF64> for Close<Dollars> {
|
||||
type Output = Dollars;
|
||||
fn mul(self, rhs: StoredF64) -> Self::Output {
|
||||
*self * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f64> for Dollars {
|
||||
type Output = Dollars;
|
||||
fn mul(self, rhs: f64) -> Self::Output {
|
||||
if rhs.fract() != 0.0 {
|
||||
Self::from(self.0 * rhs)
|
||||
} else {
|
||||
self * rhs as i64
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Bitcoin> for Dollars {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: Bitcoin) -> Self::Output {
|
||||
@@ -208,11 +244,14 @@ impl Mul<Sats> for Dollars {
|
||||
impl Mul<StoredF32> for Dollars {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: StoredF32) -> Self::Output {
|
||||
if rhs.fract() != 0.0 {
|
||||
Self::from(self.0 * *rhs as f64)
|
||||
} else {
|
||||
self * *rhs as i64
|
||||
}
|
||||
self * *rhs as f64
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<StoredF64> for Dollars {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: StoredF64) -> Self::Output {
|
||||
self * *rhs
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Printable, TypeIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct EmptyOutputIndex(TypeIndex);
|
||||
impl From<TypeIndex> for EmptyOutputIndex {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<EmptyOutputIndex> for usize {
|
||||
fn from(value: EmptyOutputIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for EmptyOutputIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(TypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for EmptyOutputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<EmptyOutputIndex> for EmptyOutputIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
impl Printable for EmptyOutputIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"emptyoutputindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["emptyout", "emptyoutputindex"]
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use std::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::Height;
|
||||
|
||||
@@ -86,3 +86,13 @@ impl Div<usize> for HalvingEpoch {
|
||||
Self::from(self.0 as usize / rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for HalvingEpoch {
|
||||
fn to_string() -> &'static str {
|
||||
"halvingepoch"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["halving", "halvingepoch"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
|
||||
use zerocopy::{FromBytes, IntoBytes};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::StoredUsize;
|
||||
|
||||
@@ -209,3 +209,13 @@ impl From<Height> for byteview::ByteView {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for Height {
|
||||
fn to_string() -> &'static str {
|
||||
"height"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["h", "height"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::Vin;
|
||||
|
||||
@@ -96,3 +96,13 @@ impl From<InputIndex> for usize {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for InputIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"inputindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["in", "inputindex"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
mod addressbytes;
|
||||
mod addressbyteshash;
|
||||
// mod addressindex;
|
||||
// mod addressindexoutputindex;
|
||||
// mod addresstype;
|
||||
mod bitcoin;
|
||||
mod blockhash;
|
||||
mod blockhashprefix;
|
||||
@@ -12,15 +9,25 @@ mod dateindex;
|
||||
mod decadeindex;
|
||||
mod difficultyepoch;
|
||||
mod dollars;
|
||||
mod emptyoutputindex;
|
||||
mod feerate;
|
||||
mod halvingepoch;
|
||||
mod height;
|
||||
mod inputindex;
|
||||
mod monthindex;
|
||||
mod ohlc;
|
||||
mod opreturnindex;
|
||||
mod outputindex;
|
||||
mod outputtype;
|
||||
mod outputtypeindex;
|
||||
mod p2aaddressindex;
|
||||
mod p2msoutputindex;
|
||||
mod p2pk33addressindex;
|
||||
mod p2pk65addressindex;
|
||||
mod p2pkhaddressindex;
|
||||
mod p2shaddressindex;
|
||||
mod p2traddressindex;
|
||||
mod p2wpkhaddressindex;
|
||||
mod p2wshaddressindex;
|
||||
mod quarterindex;
|
||||
mod rawlocktime;
|
||||
mod sats;
|
||||
@@ -35,7 +42,9 @@ mod txid;
|
||||
mod txidprefix;
|
||||
mod txindex;
|
||||
mod txversion;
|
||||
mod typeindex;
|
||||
mod unit;
|
||||
mod unknownoutputindex;
|
||||
mod version;
|
||||
mod vin;
|
||||
mod vout;
|
||||
@@ -45,9 +54,6 @@ mod yearindex;
|
||||
|
||||
pub use addressbytes::*;
|
||||
pub use addressbyteshash::*;
|
||||
// pub use addressindex::*;
|
||||
// pub use addressindexoutputindex::*;
|
||||
// pub use addresstype::*;
|
||||
pub use bitcoin::*;
|
||||
pub use blockhash::*;
|
||||
pub use blockhashprefix::*;
|
||||
@@ -57,15 +63,25 @@ pub use dateindex::*;
|
||||
pub use decadeindex::*;
|
||||
pub use difficultyepoch::*;
|
||||
pub use dollars::*;
|
||||
pub use emptyoutputindex::*;
|
||||
pub use feerate::*;
|
||||
pub use halvingepoch::*;
|
||||
pub use height::*;
|
||||
pub use inputindex::*;
|
||||
pub use monthindex::*;
|
||||
pub use ohlc::*;
|
||||
pub use opreturnindex::*;
|
||||
pub use outputindex::*;
|
||||
pub use outputtype::*;
|
||||
pub use outputtypeindex::*;
|
||||
pub use p2aaddressindex::*;
|
||||
pub use p2msoutputindex::*;
|
||||
pub use p2pk33addressindex::*;
|
||||
pub use p2pk65addressindex::*;
|
||||
pub use p2pkhaddressindex::*;
|
||||
pub use p2shaddressindex::*;
|
||||
pub use p2traddressindex::*;
|
||||
pub use p2wpkhaddressindex::*;
|
||||
pub use p2wshaddressindex::*;
|
||||
pub use quarterindex::*;
|
||||
pub use rawlocktime::*;
|
||||
pub use sats::*;
|
||||
@@ -80,7 +96,9 @@ pub use txid::*;
|
||||
pub use txidprefix::*;
|
||||
pub use txindex::*;
|
||||
pub use txversion::*;
|
||||
pub use typeindex::*;
|
||||
pub use unit::*;
|
||||
pub use unknownoutputindex::*;
|
||||
pub use version::*;
|
||||
pub use vin::*;
|
||||
pub use vout::*;
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::{fmt::Debug, ops::Add};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::{Date, DateIndex, YearIndex};
|
||||
|
||||
@@ -68,3 +68,13 @@ impl CheckedSub for MonthIndex {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for MonthIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"monthindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["m", "month", "monthindex"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::ops::{Add, Div};
|
||||
|
||||
use derive_deref::Deref;
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::{Serialize, Serializer, ser::SerializeTuple};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
@@ -172,6 +172,7 @@ impl From<Close<Sats>> for OHLCSats {
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Serialize,
|
||||
)]
|
||||
#[repr(C)]
|
||||
@@ -259,6 +260,7 @@ where
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Serialize,
|
||||
)]
|
||||
#[repr(C)]
|
||||
@@ -346,6 +348,7 @@ where
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Serialize,
|
||||
)]
|
||||
#[repr(C)]
|
||||
@@ -433,6 +436,7 @@ where
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Serialize,
|
||||
)]
|
||||
#[repr(C)]
|
||||
@@ -520,3 +524,13 @@ where
|
||||
Self(self.0 / rhs)
|
||||
}
|
||||
}
|
||||
|
||||
// impl<T> Mul<usize> for Close<T>
|
||||
// where
|
||||
// T: Mul<usize, Output = T>,
|
||||
// {
|
||||
// type Output = Self;
|
||||
// fn mul(self, rhs: usize) -> Self::Output {
|
||||
// Self(self.0 * rhs)
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Printable, TypeIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct OpReturnIndex(TypeIndex);
|
||||
impl From<TypeIndex> for OpReturnIndex {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<OpReturnIndex> for usize {
|
||||
fn from(value: OpReturnIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for OpReturnIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(TypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for OpReturnIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<OpReturnIndex> for OpReturnIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for OpReturnIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"opreturnindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["op", "opreturn", "opreturnindex"]
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::Vout;
|
||||
|
||||
@@ -102,3 +102,13 @@ impl From<OutputIndex> for usize {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for OutputIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"outputindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["out", "outputindex"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,634 +0,0 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use byteview::ByteView;
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy::{FromBytes, IntoBytes};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct OutputTypeIndex(u32);
|
||||
|
||||
impl OutputTypeIndex {
|
||||
pub fn increment(&mut self) {
|
||||
self.0 += 1;
|
||||
}
|
||||
|
||||
pub fn incremented(self) -> Self {
|
||||
Self(self.0 + 1)
|
||||
}
|
||||
|
||||
pub fn copy_then_increment(&mut self) -> Self {
|
||||
let i = *self;
|
||||
self.increment();
|
||||
i
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for OutputTypeIndex {
|
||||
fn from(value: u32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for OutputTypeIndex {
|
||||
fn from(value: u64) -> Self {
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
impl From<OutputTypeIndex> for u64 {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
value.0 as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for OutputTypeIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
impl From<OutputTypeIndex> for usize {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for OutputTypeIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 + rhs as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<OutputTypeIndex> for OutputTypeIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: OutputTypeIndex) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
impl From<ByteView> for OutputTypeIndex {
|
||||
fn from(value: ByteView) -> Self {
|
||||
Self::read_from_bytes(&value).unwrap()
|
||||
}
|
||||
}
|
||||
impl From<OutputTypeIndex> for ByteView {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct EmptyOutputIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for EmptyOutputIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<EmptyOutputIndex> for usize {
|
||||
fn from(value: EmptyOutputIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for EmptyOutputIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for EmptyOutputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<EmptyOutputIndex> for EmptyOutputIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2MSIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2MSIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2MSIndex> for usize {
|
||||
fn from(value: P2MSIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2MSIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2MSIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2MSIndex> for P2MSIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2AIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2AIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2AIndex> for usize {
|
||||
fn from(value: P2AIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2AIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2AIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2AIndex> for P2AIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct OpReturnIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for OpReturnIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<OpReturnIndex> for usize {
|
||||
fn from(value: OpReturnIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for OpReturnIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for OpReturnIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<OpReturnIndex> for OpReturnIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct UnknownOutputIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for UnknownOutputIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<UnknownOutputIndex> for usize {
|
||||
fn from(value: UnknownOutputIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for UnknownOutputIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for UnknownOutputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<UnknownOutputIndex> for UnknownOutputIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2PK33Index(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2PK33Index {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2PK33Index> for usize {
|
||||
fn from(value: P2PK33Index) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2PK33Index {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2PK33Index {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2PK33Index> for P2PK33Index {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2PK65Index(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2PK65Index {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2PK65Index> for usize {
|
||||
fn from(value: P2PK65Index) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2PK65Index {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2PK65Index {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2PK65Index> for P2PK65Index {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2PKHIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2PKHIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2PKHIndex> for usize {
|
||||
fn from(value: P2PKHIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2PKHIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2PKHIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2PKHIndex> for P2PKHIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2SHIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2SHIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2SHIndex> for usize {
|
||||
fn from(value: P2SHIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2SHIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2SHIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2SHIndex> for P2SHIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2TRIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2TRIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2TRIndex> for usize {
|
||||
fn from(value: P2TRIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2TRIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2TRIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2TRIndex> for P2TRIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2WPKHIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2WPKHIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2WPKHIndex> for usize {
|
||||
fn from(value: P2WPKHIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2WPKHIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2WPKHIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2WPKHIndex> for P2WPKHIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2WSHIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2WSHIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2WSHIndex> for usize {
|
||||
fn from(value: P2WSHIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2WSHIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2WSHIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2WSHIndex> for P2WSHIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Printable, TypeIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2AAddressIndex(TypeIndex);
|
||||
impl From<TypeIndex> for P2AAddressIndex {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2AAddressIndex> for usize {
|
||||
fn from(value: P2AAddressIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2AAddressIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(TypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2AAddressIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2AAddressIndex> for P2AAddressIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
impl Printable for P2AAddressIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"p2aaddressindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["aaddr", "p2aaddr", "p2aaddressindex"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Printable, TypeIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2MSOutputIndex(TypeIndex);
|
||||
impl From<TypeIndex> for P2MSOutputIndex {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2MSOutputIndex> for usize {
|
||||
fn from(value: P2MSOutputIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2MSOutputIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(TypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2MSOutputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2MSOutputIndex> for P2MSOutputIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for P2MSOutputIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"p2msoutputindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["msout", "p2msout", "p2msoutputindex"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Printable, TypeIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2PK33AddressIndex(TypeIndex);
|
||||
impl From<TypeIndex> for P2PK33AddressIndex {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2PK33AddressIndex> for usize {
|
||||
fn from(value: P2PK33AddressIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2PK33AddressIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(TypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2PK33AddressIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2PK33AddressIndex> for P2PK33AddressIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for P2PK33AddressIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"p2pk33addressindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["pk33addr", "p2pk33addr", "p2pk33addressindex"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Printable, TypeIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2PK65AddressIndex(TypeIndex);
|
||||
impl From<TypeIndex> for P2PK65AddressIndex {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2PK65AddressIndex> for usize {
|
||||
fn from(value: P2PK65AddressIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2PK65AddressIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(TypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2PK65AddressIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2PK65AddressIndex> for P2PK65AddressIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for P2PK65AddressIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"p2pk65addressindex"
|
||||
}
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["pk65addr", "p2pk65addr", "p2pk65addressindex"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Printable, TypeIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2PKHAddressIndex(TypeIndex);
|
||||
impl From<TypeIndex> for P2PKHAddressIndex {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2PKHAddressIndex> for usize {
|
||||
fn from(value: P2PKHAddressIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2PKHAddressIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(TypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2PKHAddressIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2PKHAddressIndex> for P2PKHAddressIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for P2PKHAddressIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"p2pkhaddressindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["pkhaddr", "p2pkhaddr", "p2pkhaddressindex"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Printable, TypeIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2SHAddressIndex(TypeIndex);
|
||||
impl From<TypeIndex> for P2SHAddressIndex {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2SHAddressIndex> for usize {
|
||||
fn from(value: P2SHAddressIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2SHAddressIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(TypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2SHAddressIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2SHAddressIndex> for P2SHAddressIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for P2SHAddressIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"p2shaddressindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["shaddr", "p2shaddr", "p2shaddressindex"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Printable, TypeIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2TRAddressIndex(TypeIndex);
|
||||
impl From<TypeIndex> for P2TRAddressIndex {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2TRAddressIndex> for usize {
|
||||
fn from(value: P2TRAddressIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2TRAddressIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(TypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2TRAddressIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2TRAddressIndex> for P2TRAddressIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for P2TRAddressIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"p2traddressindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["traddr", "p2traddr", "p2traddressindex"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Printable, TypeIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2WPKHAddressIndex(TypeIndex);
|
||||
impl From<TypeIndex> for P2WPKHAddressIndex {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2WPKHAddressIndex> for usize {
|
||||
fn from(value: P2WPKHAddressIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2WPKHAddressIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(TypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2WPKHAddressIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2WPKHAddressIndex> for P2WPKHAddressIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for P2WPKHAddressIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"p2wpkhaddressindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["wpkhaddr", "p2wpkhaddr", "p2wpkhaddressindex"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Printable, TypeIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2WSHAddressIndex(TypeIndex);
|
||||
impl From<TypeIndex> for P2WSHAddressIndex {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2WSHAddressIndex> for usize {
|
||||
fn from(value: P2WSHAddressIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2WSHAddressIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(TypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2WSHAddressIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2WSHAddressIndex> for P2WSHAddressIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for P2WSHAddressIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"p2wshaddressindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["wshaddr", "p2wshaddr", "p2wshaddressindex"]
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ use std::{fmt::Debug, ops::Add};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::MonthIndex;
|
||||
|
||||
@@ -62,3 +62,13 @@ impl CheckedSub for QuarterIndex {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for QuarterIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"quarterindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["q", "quarter", "quarterindex"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use byteview::ByteView;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, copy_first_8bytes};
|
||||
use crate::{CheckedSub, StoredF64, copy_first_8bytes};
|
||||
|
||||
use super::{Bitcoin, Cents, Dollars, Height};
|
||||
|
||||
@@ -112,6 +112,13 @@ impl Mul<Height> for Sats {
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<StoredF64> for Sats {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: StoredF64) -> Self::Output {
|
||||
Sats::from((self.0 as f64 * f64::from(rhs)) as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sum for Sats {
|
||||
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||
let sats: u64 = iter.map(|sats| sats.0).sum();
|
||||
|
||||
@@ -8,7 +8,7 @@ use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::{Dollars, StoredF64};
|
||||
|
||||
@@ -148,3 +148,13 @@ impl Ord for StoredF32 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for StoredF32 {
|
||||
fn to_string() -> &'static str {
|
||||
"f32"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["f32"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{Bitcoin, CheckedSub, Dollars};
|
||||
use crate::{Bitcoin, CheckedSub, Dollars, Printable};
|
||||
|
||||
#[derive(
|
||||
Debug, Deref, Default, Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout, Serialize,
|
||||
@@ -51,6 +51,13 @@ impl Div<usize> for StoredF64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<StoredF64> for StoredF64 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 / rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for StoredF64 {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
@@ -113,3 +120,13 @@ impl From<Bitcoin> for StoredF64 {
|
||||
Self(f64::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for StoredF64 {
|
||||
fn to_string() -> &'static str {
|
||||
"f64"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["f64"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,12 @@ use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::{
|
||||
EmptyOutputIndex, OpReturnIndex, P2AIndex, P2MSIndex, P2PK33Index, P2PK65Index, P2PKHIndex,
|
||||
P2SHIndex, P2TRIndex, P2WPKHIndex, P2WSHIndex, UnknownOutputIndex,
|
||||
EmptyOutputIndex, OpReturnIndex, P2AAddressIndex, P2MSOutputIndex, P2PK33AddressIndex,
|
||||
P2PK65AddressIndex, P2PKHAddressIndex, P2SHAddressIndex, P2TRAddressIndex, P2WPKHAddressIndex,
|
||||
P2WSHAddressIndex, UnknownOutputIndex,
|
||||
};
|
||||
|
||||
#[derive(
|
||||
@@ -93,20 +94,20 @@ impl From<StoredU32> for usize {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PK65Index> for StoredU32 {
|
||||
fn from(value: P2PK65Index) -> Self {
|
||||
impl From<P2PK65AddressIndex> for StoredU32 {
|
||||
fn from(value: P2PK65AddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PK33Index> for StoredU32 {
|
||||
fn from(value: P2PK33Index) -> Self {
|
||||
impl From<P2PK33AddressIndex> for StoredU32 {
|
||||
fn from(value: P2PK33AddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PKHIndex> for StoredU32 {
|
||||
fn from(value: P2PKHIndex) -> Self {
|
||||
impl From<P2PKHAddressIndex> for StoredU32 {
|
||||
fn from(value: P2PKHAddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
@@ -117,38 +118,38 @@ impl From<OpReturnIndex> for StoredU32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2MSIndex> for StoredU32 {
|
||||
fn from(value: P2MSIndex) -> Self {
|
||||
impl From<P2MSOutputIndex> for StoredU32 {
|
||||
fn from(value: P2MSOutputIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2SHIndex> for StoredU32 {
|
||||
fn from(value: P2SHIndex) -> Self {
|
||||
impl From<P2SHAddressIndex> for StoredU32 {
|
||||
fn from(value: P2SHAddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2WSHIndex> for StoredU32 {
|
||||
fn from(value: P2WSHIndex) -> Self {
|
||||
impl From<P2WSHAddressIndex> for StoredU32 {
|
||||
fn from(value: P2WSHAddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2WPKHIndex> for StoredU32 {
|
||||
fn from(value: P2WPKHIndex) -> Self {
|
||||
impl From<P2WPKHAddressIndex> for StoredU32 {
|
||||
fn from(value: P2WPKHAddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2TRIndex> for StoredU32 {
|
||||
fn from(value: P2TRIndex) -> Self {
|
||||
impl From<P2TRAddressIndex> for StoredU32 {
|
||||
fn from(value: P2TRAddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2AIndex> for StoredU32 {
|
||||
fn from(value: P2AIndex) -> Self {
|
||||
impl From<P2AAddressIndex> for StoredU32 {
|
||||
fn from(value: P2AAddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
@@ -164,3 +165,13 @@ impl From<EmptyOutputIndex> for StoredU32 {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for StoredU32 {
|
||||
fn to_string() -> &'static str {
|
||||
"u32"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["u32"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::{InputIndex, OutputIndex, TxIndex};
|
||||
|
||||
@@ -97,3 +97,13 @@ impl From<OutputIndex> for StoredU64 {
|
||||
Self(*value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for StoredU64 {
|
||||
fn to_string() -> &'static str {
|
||||
"u64"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["u64"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
pub type StoredPhantom = StoredU8;
|
||||
|
||||
@@ -93,3 +93,13 @@ impl From<StoredU8> for usize {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for StoredU8 {
|
||||
fn to_string() -> &'static str {
|
||||
"u8"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["u8"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,13 @@ use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::{
|
||||
DateIndex, EmptyOutputIndex, Height, InputIndex, MonthIndex, OpReturnIndex, OutputIndex,
|
||||
P2AIndex, P2MSIndex, P2PK33Index, P2PK65Index, P2PKHIndex, P2SHIndex, P2TRIndex, P2WPKHIndex,
|
||||
P2WSHIndex, TxIndex, UnknownOutputIndex, YearIndex,
|
||||
P2AAddressIndex, P2MSOutputIndex, P2PK33AddressIndex, P2PK65AddressIndex, P2PKHAddressIndex,
|
||||
P2SHAddressIndex, P2TRAddressIndex, P2WPKHAddressIndex, P2WSHAddressIndex, TxIndex,
|
||||
UnknownOutputIndex, YearIndex,
|
||||
};
|
||||
|
||||
#[derive(
|
||||
@@ -122,20 +123,20 @@ impl From<TxIndex> for StoredUsize {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PK65Index> for StoredUsize {
|
||||
fn from(value: P2PK65Index) -> Self {
|
||||
impl From<P2PK65AddressIndex> for StoredUsize {
|
||||
fn from(value: P2PK65AddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PK33Index> for StoredUsize {
|
||||
fn from(value: P2PK33Index) -> Self {
|
||||
impl From<P2PK33AddressIndex> for StoredUsize {
|
||||
fn from(value: P2PK33AddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PKHIndex> for StoredUsize {
|
||||
fn from(value: P2PKHIndex) -> Self {
|
||||
impl From<P2PKHAddressIndex> for StoredUsize {
|
||||
fn from(value: P2PKHAddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
@@ -146,38 +147,38 @@ impl From<OpReturnIndex> for StoredUsize {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2MSIndex> for StoredUsize {
|
||||
fn from(value: P2MSIndex) -> Self {
|
||||
impl From<P2MSOutputIndex> for StoredUsize {
|
||||
fn from(value: P2MSOutputIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2SHIndex> for StoredUsize {
|
||||
fn from(value: P2SHIndex) -> Self {
|
||||
impl From<P2SHAddressIndex> for StoredUsize {
|
||||
fn from(value: P2SHAddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2WSHIndex> for StoredUsize {
|
||||
fn from(value: P2WSHIndex) -> Self {
|
||||
impl From<P2WSHAddressIndex> for StoredUsize {
|
||||
fn from(value: P2WSHAddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2WPKHIndex> for StoredUsize {
|
||||
fn from(value: P2WPKHIndex) -> Self {
|
||||
impl From<P2WPKHAddressIndex> for StoredUsize {
|
||||
fn from(value: P2WPKHAddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2TRIndex> for StoredUsize {
|
||||
fn from(value: P2TRIndex) -> Self {
|
||||
impl From<P2TRAddressIndex> for StoredUsize {
|
||||
fn from(value: P2TRAddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2AIndex> for StoredUsize {
|
||||
fn from(value: P2AIndex) -> Self {
|
||||
impl From<P2AAddressIndex> for StoredUsize {
|
||||
fn from(value: P2AAddressIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
@@ -193,3 +194,13 @@ impl From<EmptyOutputIndex> for StoredUsize {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for StoredUsize {
|
||||
fn to_string() -> &'static str {
|
||||
"usize"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["usize"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use serde::Serialize;
|
||||
use zerocopy::{FromBytes, IntoBytes};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::StoredU32;
|
||||
|
||||
@@ -111,3 +111,13 @@ impl From<TxIndex> for StoredU32 {
|
||||
Self::from(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for TxIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"txindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["tx", "txindex"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use byteview::ByteView;
|
||||
use serde::Serialize;
|
||||
use zerocopy::{FromBytes, IntoBytes};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct TypeIndex(u32);
|
||||
|
||||
impl TypeIndex {
|
||||
pub fn increment(&mut self) {
|
||||
self.0 += 1;
|
||||
}
|
||||
|
||||
pub fn incremented(self) -> Self {
|
||||
Self(self.0 + 1)
|
||||
}
|
||||
|
||||
pub fn copy_then_increment(&mut self) -> Self {
|
||||
let i = *self;
|
||||
self.increment();
|
||||
i
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for TypeIndex {
|
||||
fn from(value: u32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for TypeIndex {
|
||||
fn from(value: u64) -> Self {
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
impl From<TypeIndex> for u64 {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
value.0 as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for TypeIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
impl From<TypeIndex> for usize {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for TypeIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 + rhs as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<TypeIndex> for TypeIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: TypeIndex) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
impl From<ByteView> for TypeIndex {
|
||||
fn from(value: ByteView) -> Self {
|
||||
Self::read_from_bytes(&value).unwrap()
|
||||
}
|
||||
}
|
||||
impl From<TypeIndex> for ByteView {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub<TypeIndex> for TypeIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Printable, TypeIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct UnknownOutputIndex(TypeIndex);
|
||||
impl From<TypeIndex> for UnknownOutputIndex {
|
||||
fn from(value: TypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<UnknownOutputIndex> for usize {
|
||||
fn from(value: UnknownOutputIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for UnknownOutputIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(TypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for UnknownOutputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<UnknownOutputIndex> for UnknownOutputIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for UnknownOutputIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"unknownoutputindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["unknownout", "unknownoutputindex"]
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,18 @@ use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
use crate::{Error, Result};
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, FromBytes, IntoBytes, Immutable, KnownLayout,
|
||||
Default,
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
FromBytes,
|
||||
IntoBytes,
|
||||
Immutable,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct Version(u64);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::{fmt::Debug, ops::Add};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::{Date, DateIndex};
|
||||
|
||||
@@ -86,3 +86,13 @@ impl CheckedSub for WeekIndex {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for WeekIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"weekindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["w", "week", "weekindex"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::{fmt::Debug, ops::Add};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
use crate::{CheckedSub, Printable};
|
||||
|
||||
use super::{Date, DateIndex, MonthIndex};
|
||||
|
||||
@@ -80,3 +80,13 @@ impl From<MonthIndex> for YearIndex {
|
||||
Self((usize::from(value) / 12) as u8)
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for YearIndex {
|
||||
fn to_string() -> &'static str {
|
||||
"yearindex"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["y", "year", "yearindex"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
mod printable;
|
||||
|
||||
pub use printable::*;
|
||||
@@ -0,0 +1,4 @@
|
||||
pub trait Printable {
|
||||
fn to_string() -> &'static str;
|
||||
fn to_possible_strings() -> &'static [&'static str];
|
||||
}
|
||||
@@ -3,9 +3,11 @@ mod checked_sub;
|
||||
mod paths;
|
||||
mod pause;
|
||||
mod rlimit;
|
||||
mod serde;
|
||||
|
||||
pub use bytes::*;
|
||||
pub use checked_sub::*;
|
||||
pub use paths::*;
|
||||
pub use pause::*;
|
||||
pub use rlimit::*;
|
||||
pub use serde::*;
|
||||
|
||||
@@ -3,5 +3,7 @@ use log::info;
|
||||
pub fn pause() {
|
||||
info!("Press enter to continue...");
|
||||
let mut buffer = String::new();
|
||||
std::io::stdin().read_line(&mut buffer).expect("Failed to read line");
|
||||
std::io::stdin()
|
||||
.read_line(&mut buffer)
|
||||
.expect("Failed to read line");
|
||||
}
|
||||
|
||||
@@ -4,14 +4,12 @@ use rlimit::{Resource, getrlimit};
|
||||
|
||||
pub fn setrlimit() -> io::Result<()> {
|
||||
let no_file_limit = getrlimit(Resource::NOFILE)?;
|
||||
|
||||
rlimit::setrlimit(
|
||||
Resource::NOFILE,
|
||||
no_file_limit.0.max(210_000),
|
||||
no_file_limit.1,
|
||||
)?;
|
||||
|
||||
// let no_stack = getrlimit(Resource::STACK)?;
|
||||
// rlimit::setrlimit(Resource::STACK, no_stack.1, no_stack.1)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
pub fn default_on_error<'de, D, T>(deserializer: D) -> Result<T, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
T: Deserialize<'de> + Default,
|
||||
{
|
||||
match T::deserialize(deserializer) {
|
||||
Ok(v) => Ok(v),
|
||||
Err(_) => Ok(T::default()),
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ repository.workspace = true
|
||||
brk_core = { workspace = true }
|
||||
brk_logger = { workspace = true }
|
||||
color-eyre = { workspace = true }
|
||||
jiff = { workspace = true }
|
||||
log = { workspace = true }
|
||||
minreq = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
@@ -31,4 +31,4 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
A crate that can fetch the Bitcoin price, either by date or height, from Binance and Kibo.
|
||||
A crate that can fetch the Bitcoin price, either by date or height, from Binance, Kraken and the main instance of BRK.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use brk_core::{Date, Height};
|
||||
use brk_fetcher::{BRK, Fetcher};
|
||||
use brk_fetcher::{BRK, Binance, Fetcher, Kraken};
|
||||
|
||||
fn main() -> color_eyre::Result<()> {
|
||||
color_eyre::install()?;
|
||||
@@ -12,6 +12,19 @@ fn main() -> color_eyre::Result<()> {
|
||||
|
||||
let mut fetcher = Fetcher::import(None)?;
|
||||
|
||||
Binance::fetch_1d().map(|b| {
|
||||
dbg!(b.last_key_value());
|
||||
})?;
|
||||
Kraken::fetch_1d().map(|b| {
|
||||
dbg!(b.last_key_value());
|
||||
})?;
|
||||
Binance::fetch_1mn().map(|b| {
|
||||
dbg!(b.last_key_value());
|
||||
})?;
|
||||
Kraken::fetch_1mn().map(|b| {
|
||||
dbg!(b.last_key_value());
|
||||
})?;
|
||||
|
||||
dbg!(fetcher.get_date(Date::new(2025, 6, 5))?);
|
||||
dbg!(fetcher.get_height(
|
||||
899911_u32.into(),
|
||||
|
||||
@@ -13,10 +13,8 @@ pub struct BRK {
|
||||
dateindex_to_ohlc: BTreeMap<DateIndex, Vec<OHLCCents>>,
|
||||
}
|
||||
|
||||
const API_URL: &str = "https://bitcoinresearchkit.org/api";
|
||||
|
||||
const API_URL: &str = "https://bitcoinresearchkit.org/api/vecs";
|
||||
const RETRIES: usize = 10;
|
||||
|
||||
const CHUNK_SIZE: usize = 10_000;
|
||||
|
||||
impl BRK {
|
||||
@@ -40,11 +38,11 @@ impl BRK {
|
||||
.unwrap()
|
||||
.get(usize::from(height.checked_sub(key).unwrap()))
|
||||
.cloned()
|
||||
.ok_or(eyre!("Couldn't find height in kibo"))
|
||||
.ok_or(eyre!("Couldn't find height in BRK"))
|
||||
}
|
||||
|
||||
fn fetch_height_prices(height: Height) -> color_eyre::Result<Vec<OHLCCents>> {
|
||||
info!("Fetching Kibo height {height} prices...");
|
||||
info!("Fetching BRK height {height} prices...");
|
||||
|
||||
retry(
|
||||
|_| {
|
||||
@@ -89,11 +87,11 @@ impl BRK {
|
||||
.unwrap()
|
||||
.get(usize::from(dateindex.checked_sub(key).unwrap()))
|
||||
.cloned()
|
||||
.ok_or(eyre!("Couldn't find date in kibo"))
|
||||
.ok_or(eyre!("Couldn't find date in BRK"))
|
||||
}
|
||||
|
||||
fn fetch_date_prices(dateindex: DateIndex) -> color_eyre::Result<Vec<OHLCCents>> {
|
||||
info!("Fetching Kibo dateindex {dateindex} prices...");
|
||||
info!("Fetching BRK dateindex {dateindex} prices...");
|
||||
|
||||
retry(
|
||||
|_| {
|
||||
|
||||
@@ -32,7 +32,7 @@ impl Kraken {
|
||||
)
|
||||
}
|
||||
|
||||
fn fetch_1mn() -> color_eyre::Result<BTreeMap<Timestamp, OHLCCents>> {
|
||||
pub fn fetch_1mn() -> color_eyre::Result<BTreeMap<Timestamp, OHLCCents>> {
|
||||
info!("Fetching 1mn prices from Kraken...");
|
||||
|
||||
retry(
|
||||
@@ -54,7 +54,7 @@ impl Kraken {
|
||||
.ok_or(color_eyre::eyre::Error::msg("Couldn't find date"))
|
||||
}
|
||||
|
||||
fn fetch_1d() -> color_eyre::Result<BTreeMap<Date, OHLCCents>> {
|
||||
pub fn fetch_1d() -> color_eyre::Result<BTreeMap<Date, OHLCCents>> {
|
||||
info!("Fetching daily prices from Kraken...");
|
||||
|
||||
retry(
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#![doc = include_str!("../examples/main.rs")]
|
||||
#![doc = "```"]
|
||||
|
||||
use std::{collections::BTreeMap, fs, path::Path, thread::sleep, time::Duration};
|
||||
use std::{collections::BTreeMap, path::Path, thread::sleep, time::Duration};
|
||||
|
||||
use brk_core::{Close, Date, Dollars, Height, High, Low, OHLCCents, Open, Timestamp};
|
||||
use color_eyre::eyre::Error;
|
||||
@@ -24,10 +24,6 @@ pub struct Fetcher {
|
||||
|
||||
impl Fetcher {
|
||||
pub fn import(hars_path: Option<&Path>) -> color_eyre::Result<Self> {
|
||||
if let Some(path) = hars_path {
|
||||
fs::create_dir_all(path)?;
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
binance: Binance::init(hars_path),
|
||||
kraken: Kraken::default(),
|
||||
@@ -40,11 +36,11 @@ impl Fetcher {
|
||||
}
|
||||
|
||||
fn get_date_(&mut self, date: Date, tries: usize) -> color_eyre::Result<OHLCCents> {
|
||||
self.binance
|
||||
self.kraken
|
||||
.get_from_1d(&date)
|
||||
.or_else(|_| {
|
||||
// eprintln!("{e}");
|
||||
self.kraken.get_from_1d(&date)
|
||||
self.binance.get_from_1d(&date)
|
||||
})
|
||||
.or_else(|_| {
|
||||
// eprintln!("{e}");
|
||||
@@ -90,11 +86,11 @@ impl Fetcher {
|
||||
let previous_timestamp = previous_timestamp.map(|t| t.floor_seconds());
|
||||
|
||||
let ohlc = self
|
||||
.binance
|
||||
.kraken
|
||||
.get_from_1mn(timestamp, previous_timestamp)
|
||||
.unwrap_or_else(|_report| {
|
||||
// eprintln!("{_report}");
|
||||
self.kraken
|
||||
self.binance
|
||||
.get_from_1mn(timestamp, previous_timestamp)
|
||||
.unwrap_or_else(|_report| {
|
||||
// // eprintln!("{_report}");
|
||||
@@ -185,8 +181,8 @@ How to fix this:
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.kraken.clear();
|
||||
self.binance.clear();
|
||||
self.brk.clear();
|
||||
self.kraken.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ use brk_core::default_bitcoin_path;
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_parser::Parser;
|
||||
use brk_vec::Format;
|
||||
|
||||
fn main() -> color_eyre::Result<()> {
|
||||
color_eyre::install()?;
|
||||
@@ -25,12 +24,9 @@ fn main() -> color_eyre::Result<()> {
|
||||
|
||||
let outputs = Path::new("../../_outputs");
|
||||
|
||||
let mut indexer = Indexer::new(outputs, Format::Raw, false)?;
|
||||
let mut indexer = Indexer::forced_import(outputs)?;
|
||||
|
||||
indexer.import_stores()?;
|
||||
indexer.import_vecs()?;
|
||||
|
||||
indexer.index(&parser, rpc, &exit)?;
|
||||
indexer.index(&parser, rpc, &exit, true)?;
|
||||
|
||||
dbg!(i.elapsed());
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use bitcoincore_rpc::Client;
|
||||
use brk_core::{
|
||||
BlockHash, CheckedSub, EmptyOutputIndex, Height, InputIndex, OpReturnIndex, OutputIndex,
|
||||
OutputType, OutputTypeIndex, P2AIndex, P2MSIndex, P2PK33Index, P2PK65Index, P2PKHIndex,
|
||||
P2SHIndex, P2TRIndex, P2WPKHIndex, P2WSHIndex, Result, TxIndex, UnknownOutputIndex,
|
||||
OutputType, P2AAddressIndex, P2MSOutputIndex, P2PK33AddressIndex, P2PK65AddressIndex,
|
||||
P2PKHAddressIndex, P2SHAddressIndex, P2TRAddressIndex, P2WPKHAddressIndex, P2WSHAddressIndex,
|
||||
Result, TxIndex, TypeIndex, UnknownOutputIndex,
|
||||
};
|
||||
use brk_parser::NUMBER_OF_UNSAFE_BLOCKS;
|
||||
use brk_vec::{AnyIterableVec, AnyVec, IndexedVec, StoredIndex, StoredType};
|
||||
use brk_vec::{AnyIndexedVec, AnyIterableVec, AnyVec, IndexedVec, StoredIndex, StoredType};
|
||||
use color_eyre::eyre::ContextCompat;
|
||||
|
||||
use crate::{Stores, Vecs};
|
||||
@@ -15,15 +16,15 @@ pub struct Indexes {
|
||||
pub emptyoutputindex: EmptyOutputIndex,
|
||||
pub height: Height,
|
||||
pub opreturnindex: OpReturnIndex,
|
||||
pub p2msindex: P2MSIndex,
|
||||
pub p2pk33index: P2PK33Index,
|
||||
pub p2pk65index: P2PK65Index,
|
||||
pub p2pkhindex: P2PKHIndex,
|
||||
pub p2shindex: P2SHIndex,
|
||||
pub p2trindex: P2TRIndex,
|
||||
pub p2wpkhindex: P2WPKHIndex,
|
||||
pub p2wshindex: P2WSHIndex,
|
||||
pub p2aindex: P2AIndex,
|
||||
pub p2msoutputindex: P2MSOutputIndex,
|
||||
pub p2pk33addressindex: P2PK33AddressIndex,
|
||||
pub p2pk65addressindex: P2PK65AddressIndex,
|
||||
pub p2pkhaddressindex: P2PKHAddressIndex,
|
||||
pub p2shaddressindex: P2SHAddressIndex,
|
||||
pub p2traddressindex: P2TRAddressIndex,
|
||||
pub p2wpkhaddressindex: P2WPKHAddressIndex,
|
||||
pub p2wshaddressindex: P2WSHAddressIndex,
|
||||
pub p2aaddressindex: P2AAddressIndex,
|
||||
pub txindex: TxIndex,
|
||||
pub inputindex: InputIndex,
|
||||
pub outputindex: OutputIndex,
|
||||
@@ -31,19 +32,19 @@ pub struct Indexes {
|
||||
}
|
||||
|
||||
impl Indexes {
|
||||
pub fn outputtypeindex(&self, outputtype: OutputType) -> OutputTypeIndex {
|
||||
pub fn typeindex(&self, outputtype: OutputType) -> TypeIndex {
|
||||
match outputtype {
|
||||
OutputType::Empty => *self.emptyoutputindex,
|
||||
OutputType::OpReturn => *self.opreturnindex,
|
||||
OutputType::P2A => *self.p2aindex,
|
||||
OutputType::P2MS => *self.p2msindex,
|
||||
OutputType::P2PK33 => *self.p2pkhindex,
|
||||
OutputType::P2PK65 => *self.p2pk65index,
|
||||
OutputType::P2PKH => *self.p2pkhindex,
|
||||
OutputType::P2SH => *self.p2shindex,
|
||||
OutputType::P2TR => *self.p2trindex,
|
||||
OutputType::P2WPKH => *self.p2wpkhindex,
|
||||
OutputType::P2WSH => *self.p2wshindex,
|
||||
OutputType::P2A => *self.p2aaddressindex,
|
||||
OutputType::P2MS => *self.p2msoutputindex,
|
||||
OutputType::P2PK33 => *self.p2pkhaddressindex,
|
||||
OutputType::P2PK65 => *self.p2pk65addressindex,
|
||||
OutputType::P2PKH => *self.p2pkhaddressindex,
|
||||
OutputType::P2SH => *self.p2shaddressindex,
|
||||
OutputType::P2TR => *self.p2traddressindex,
|
||||
OutputType::P2WPKH => *self.p2wpkhaddressindex,
|
||||
OutputType::P2WSH => *self.p2wshaddressindex,
|
||||
OutputType::Unknown => *self.unknownoutputindex,
|
||||
}
|
||||
}
|
||||
@@ -58,28 +59,28 @@ impl Indexes {
|
||||
.push_if_needed(height, self.outputindex)?;
|
||||
vecs.height_to_first_emptyoutputindex
|
||||
.push_if_needed(height, self.emptyoutputindex)?;
|
||||
vecs.height_to_first_p2msindex
|
||||
.push_if_needed(height, self.p2msindex)?;
|
||||
vecs.height_to_first_p2msoutputindex
|
||||
.push_if_needed(height, self.p2msoutputindex)?;
|
||||
vecs.height_to_first_opreturnindex
|
||||
.push_if_needed(height, self.opreturnindex)?;
|
||||
vecs.height_to_first_p2aindex
|
||||
.push_if_needed(height, self.p2aindex)?;
|
||||
vecs.height_to_first_p2aaddressindex
|
||||
.push_if_needed(height, self.p2aaddressindex)?;
|
||||
vecs.height_to_first_unknownoutputindex
|
||||
.push_if_needed(height, self.unknownoutputindex)?;
|
||||
vecs.height_to_first_p2pk33index
|
||||
.push_if_needed(height, self.p2pk33index)?;
|
||||
vecs.height_to_first_p2pk65index
|
||||
.push_if_needed(height, self.p2pk65index)?;
|
||||
vecs.height_to_first_p2pkhindex
|
||||
.push_if_needed(height, self.p2pkhindex)?;
|
||||
vecs.height_to_first_p2shindex
|
||||
.push_if_needed(height, self.p2shindex)?;
|
||||
vecs.height_to_first_p2trindex
|
||||
.push_if_needed(height, self.p2trindex)?;
|
||||
vecs.height_to_first_p2wpkhindex
|
||||
.push_if_needed(height, self.p2wpkhindex)?;
|
||||
vecs.height_to_first_p2wshindex
|
||||
.push_if_needed(height, self.p2wshindex)?;
|
||||
vecs.height_to_first_p2pk33addressindex
|
||||
.push_if_needed(height, self.p2pk33addressindex)?;
|
||||
vecs.height_to_first_p2pk65addressindex
|
||||
.push_if_needed(height, self.p2pk65addressindex)?;
|
||||
vecs.height_to_first_p2pkhaddressindex
|
||||
.push_if_needed(height, self.p2pkhaddressindex)?;
|
||||
vecs.height_to_first_p2shaddressindex
|
||||
.push_if_needed(height, self.p2shaddressindex)?;
|
||||
vecs.height_to_first_p2traddressindex
|
||||
.push_if_needed(height, self.p2traddressindex)?;
|
||||
vecs.height_to_first_p2wpkhaddressindex
|
||||
.push_if_needed(height, self.p2wpkhaddressindex)?;
|
||||
vecs.height_to_first_p2wshaddressindex
|
||||
.push_if_needed(height, self.p2wshaddressindex)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -110,13 +111,7 @@ impl TryFrom<(&mut Vecs, &Stores, &Client)> for Indexes {
|
||||
vecs.height_to_blockhash
|
||||
.iter()
|
||||
.get(*height)
|
||||
.is_none_or(|saved_blockhash| {
|
||||
let b = &rpc_blockhash != saved_blockhash.as_ref();
|
||||
if b {
|
||||
dbg!(rpc_blockhash, saved_blockhash.as_ref());
|
||||
}
|
||||
b
|
||||
})
|
||||
.is_none_or(|saved_blockhash| &rpc_blockhash != saved_blockhash.as_ref())
|
||||
})
|
||||
.unwrap_or(starting_height);
|
||||
|
||||
@@ -128,9 +123,9 @@ impl TryFrom<(&mut Vecs, &Stores, &Client)> for Indexes {
|
||||
)
|
||||
.context("")?,
|
||||
height,
|
||||
p2msindex: starting_index(
|
||||
&vecs.height_to_first_p2msindex,
|
||||
&vecs.p2msindex_to_txindex,
|
||||
p2msoutputindex: starting_index(
|
||||
&vecs.height_to_first_p2msoutputindex,
|
||||
&vecs.p2msoutputindex_to_txindex,
|
||||
height,
|
||||
)
|
||||
.context("")?,
|
||||
@@ -140,51 +135,51 @@ impl TryFrom<(&mut Vecs, &Stores, &Client)> for Indexes {
|
||||
height,
|
||||
)
|
||||
.context("")?,
|
||||
p2pk33index: starting_index(
|
||||
&vecs.height_to_first_p2pk33index,
|
||||
&vecs.p2pk33index_to_p2pk33bytes,
|
||||
p2pk33addressindex: starting_index(
|
||||
&vecs.height_to_first_p2pk33addressindex,
|
||||
&vecs.p2pk33addressindex_to_p2pk33bytes,
|
||||
height,
|
||||
)
|
||||
.context("")?,
|
||||
p2pk65index: starting_index(
|
||||
&vecs.height_to_first_p2pk65index,
|
||||
&vecs.p2pk65index_to_p2pk65bytes,
|
||||
p2pk65addressindex: starting_index(
|
||||
&vecs.height_to_first_p2pk65addressindex,
|
||||
&vecs.p2pk65addressindex_to_p2pk65bytes,
|
||||
height,
|
||||
)
|
||||
.context("")?,
|
||||
p2pkhindex: starting_index(
|
||||
&vecs.height_to_first_p2pkhindex,
|
||||
&vecs.p2pkhindex_to_p2pkhbytes,
|
||||
p2pkhaddressindex: starting_index(
|
||||
&vecs.height_to_first_p2pkhaddressindex,
|
||||
&vecs.p2pkhaddressindex_to_p2pkhbytes,
|
||||
height,
|
||||
)
|
||||
.context("")?,
|
||||
p2shindex: starting_index(
|
||||
&vecs.height_to_first_p2shindex,
|
||||
&vecs.p2shindex_to_p2shbytes,
|
||||
p2shaddressindex: starting_index(
|
||||
&vecs.height_to_first_p2shaddressindex,
|
||||
&vecs.p2shaddressindex_to_p2shbytes,
|
||||
height,
|
||||
)
|
||||
.context("")?,
|
||||
p2trindex: starting_index(
|
||||
&vecs.height_to_first_p2trindex,
|
||||
&vecs.p2trindex_to_p2trbytes,
|
||||
p2traddressindex: starting_index(
|
||||
&vecs.height_to_first_p2traddressindex,
|
||||
&vecs.p2traddressindex_to_p2trbytes,
|
||||
height,
|
||||
)
|
||||
.context("")?,
|
||||
p2wpkhindex: starting_index(
|
||||
&vecs.height_to_first_p2wpkhindex,
|
||||
&vecs.p2wpkhindex_to_p2wpkhbytes,
|
||||
p2wpkhaddressindex: starting_index(
|
||||
&vecs.height_to_first_p2wpkhaddressindex,
|
||||
&vecs.p2wpkhaddressindex_to_p2wpkhbytes,
|
||||
height,
|
||||
)
|
||||
.context("")?,
|
||||
p2wshindex: starting_index(
|
||||
&vecs.height_to_first_p2wshindex,
|
||||
&vecs.p2wshindex_to_p2wshbytes,
|
||||
p2wshaddressindex: starting_index(
|
||||
&vecs.height_to_first_p2wshaddressindex,
|
||||
&vecs.p2wshaddressindex_to_p2wshbytes,
|
||||
height,
|
||||
)
|
||||
.context("")?,
|
||||
p2aindex: starting_index(
|
||||
&vecs.height_to_first_p2aindex,
|
||||
&vecs.p2aindex_to_p2abytes,
|
||||
p2aaddressindex: starting_index(
|
||||
&vecs.height_to_first_p2aaddressindex,
|
||||
&vecs.p2aaddressindex_to_p2abytes,
|
||||
height,
|
||||
)
|
||||
.context("")?,
|
||||
@@ -221,10 +216,10 @@ where
|
||||
I: StoredType + StoredIndex + From<usize>,
|
||||
T: StoredType,
|
||||
{
|
||||
if height_to_index
|
||||
.height()
|
||||
.is_ok_and(|h| h + 1_u32 == starting_height)
|
||||
{
|
||||
let h = height_to_index.height();
|
||||
if h.is_zero() {
|
||||
None
|
||||
} else if height_to_index.height() + 1_u32 == starting_height {
|
||||
Some(I::from(index_to_else.len()))
|
||||
} else {
|
||||
height_to_index.iter().get_inner(starting_height)
|
||||
|
||||