mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-22 12:23:04 -07:00
Compare commits
61 Commits
v0.2.0
...
v0.3.0-alpha.3
| Author | SHA1 | Date | |
|---|---|---|---|
| 366ac33e23 | |||
| b5a7023bd3 | |||
| 883b38c77c | |||
| 59c767a9e2 | |||
| 9b5bb848f7 | |||
| 5bf06530ce | |||
| 768e6870cb | |||
| 79829ddd53 | |||
| 78082801c6 | |||
| 50771ddccc | |||
| 3a8a9ddecc | |||
| 6cd45c1f1f | |||
| 1a2db43cf5 | |||
| 4840e564f4 | |||
| 744dce932c | |||
| 8dfc1bc932 | |||
| d92cf43c57 | |||
| 099699872e | |||
| 5099903043 | |||
| 982fe47a33 | |||
| 65d5fadd13 | |||
| b55f5255ad | |||
| 83edef4806 | |||
| d4936d889a | |||
| c938cc8eae | |||
| 0558834eef | |||
| 098950fdde | |||
| 91e68a1d1e | |||
| 7172ddb247 | |||
| 96f2e058f7 | |||
| 8782944191 | |||
| ae26db6df2 | |||
| d038141a8a | |||
| f6960c61d6 | |||
| 07fa2d2c9a | |||
| 82c6d69a0b | |||
| d4dc1b9e49 | |||
| 24d2b7b142 | |||
| b6e56c4e9f | |||
| 45c77a4c3b | |||
| 09af190ac0 | |||
| d24f3691cb | |||
| daaaa15483 | |||
| 041652d85d | |||
| 17570e12b8 | |||
| 78172734db | |||
| 19d4a193ff | |||
| 66680368b6 | |||
| b4ded21ea3 | |||
| 7412373d8a | |||
| 259960b80b | |||
| 18bb4186a8 | |||
| 6d3307c0df | |||
| 6eea20b89a | |||
| 5077cefda8 | |||
| 14d7adfdd5 | |||
| 000027fab8 | |||
| ade23795b8 | |||
| 67ad33b07a | |||
| d54874d3a4 | |||
| ec6420254a |
Generated
+132
-135
@@ -338,7 +338,7 @@ checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||
|
||||
[[package]]
|
||||
name = "brk"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"brk_bencher",
|
||||
"brk_bindgen",
|
||||
@@ -399,7 +399,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_alloc"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"libmimalloc-sys",
|
||||
"mimalloc",
|
||||
@@ -407,7 +407,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_bencher"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"brk_error",
|
||||
"brk_logger",
|
||||
@@ -417,14 +417,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_bencher_visualizer"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"plotters",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brk_bindgen"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"brk_cohort",
|
||||
"brk_query",
|
||||
@@ -437,14 +437,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_cli"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"brk_alloc",
|
||||
"brk_computer",
|
||||
"brk_error",
|
||||
"brk_indexer",
|
||||
"brk_iterator",
|
||||
"brk_logger",
|
||||
"brk_mempool",
|
||||
"brk_query",
|
||||
@@ -463,7 +462,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_client"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"brk_cohort",
|
||||
"brk_types",
|
||||
@@ -474,7 +473,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_cohort"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"brk_error",
|
||||
"brk_traversable",
|
||||
@@ -486,7 +485,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_computer"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"brk_alloc",
|
||||
@@ -494,12 +493,10 @@ dependencies = [
|
||||
"brk_cohort",
|
||||
"brk_error",
|
||||
"brk_indexer",
|
||||
"brk_iterator",
|
||||
"brk_logger",
|
||||
"brk_oracle",
|
||||
"brk_reader",
|
||||
"brk_rpc",
|
||||
"brk_store",
|
||||
"brk_traversable",
|
||||
"brk_types",
|
||||
"color-eyre",
|
||||
@@ -517,7 +514,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_error"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
@@ -534,7 +531,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_fetcher"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"brk_error",
|
||||
"brk_logger",
|
||||
@@ -546,14 +543,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_indexer"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"brk_alloc",
|
||||
"brk_bencher",
|
||||
"brk_cohort",
|
||||
"brk_error",
|
||||
"brk_iterator",
|
||||
"brk_logger",
|
||||
"brk_reader",
|
||||
"brk_rpc",
|
||||
@@ -562,6 +558,7 @@ dependencies = [
|
||||
"brk_types",
|
||||
"color-eyre",
|
||||
"fjall",
|
||||
"parking_lot",
|
||||
"rayon",
|
||||
"rlimit",
|
||||
"rustc-hash",
|
||||
@@ -573,7 +570,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_iterator"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"brk_error",
|
||||
"brk_reader",
|
||||
@@ -583,7 +580,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_logger"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"jiff",
|
||||
"owo-colors",
|
||||
@@ -594,7 +591,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_mempool"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"brk_error",
|
||||
"brk_logger",
|
||||
@@ -609,7 +606,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_oracle"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"brk_indexer",
|
||||
"brk_types",
|
||||
@@ -619,7 +616,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_query"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"brk_computer",
|
||||
@@ -641,7 +638,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_reader"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"brk_error",
|
||||
@@ -656,7 +653,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_rpc"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
@@ -673,7 +670,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_server"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"aide",
|
||||
"axum",
|
||||
@@ -708,7 +705,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_store"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"brk_error",
|
||||
"brk_types",
|
||||
@@ -719,7 +716,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_traversable"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"brk_traversable_derive",
|
||||
"brk_types",
|
||||
@@ -732,7 +729,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_traversable_derive"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -741,7 +738,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_types"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"brk_error",
|
||||
@@ -764,7 +761,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_website"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.3"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"brk_logger",
|
||||
@@ -836,9 +833,9 @@ checksum = "1c53ba0f290bfc610084c05582d9c5d421662128fc69f4bf236707af6fd321b9"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.57"
|
||||
version = "1.2.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423"
|
||||
checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
@@ -1308,9 +1305,9 @@ checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "fjall"
|
||||
version = "3.1.2"
|
||||
version = "3.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a9530ff159bc3ad3a15da746da0f6e95375c2ac64708cbb85ec1ebd26761a84"
|
||||
checksum = "0ebf22b812878dcd767879cb19e03124fd62563dce6410f96538175fba0c132d"
|
||||
dependencies = [
|
||||
"byteorder-lite",
|
||||
"byteview",
|
||||
@@ -1318,7 +1315,7 @@ dependencies = [
|
||||
"flume",
|
||||
"log",
|
||||
"lsm-tree",
|
||||
"lz4_flex",
|
||||
"lz4_flex 0.11.6",
|
||||
"tempfile",
|
||||
"xxhash-rust",
|
||||
]
|
||||
@@ -1672,9 +1669,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.8.1"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11"
|
||||
checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
@@ -1686,7 +1683,6 @@ dependencies = [
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"smallvec",
|
||||
"tokio",
|
||||
]
|
||||
@@ -1732,12 +1728,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_collections"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
|
||||
checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"potential_utf",
|
||||
"utf8_iter",
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
"zerovec",
|
||||
@@ -1745,9 +1742,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_locale_core"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
|
||||
checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"litemap",
|
||||
@@ -1758,9 +1755,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
|
||||
checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4"
|
||||
dependencies = [
|
||||
"icu_collections",
|
||||
"icu_normalizer_data",
|
||||
@@ -1772,15 +1769,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer_data"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
|
||||
checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38"
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties"
|
||||
version = "2.1.2"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec"
|
||||
checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de"
|
||||
dependencies = [
|
||||
"icu_collections",
|
||||
"icu_locale_core",
|
||||
@@ -1792,15 +1789,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties_data"
|
||||
version = "2.1.2"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af"
|
||||
checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14"
|
||||
|
||||
[[package]]
|
||||
name = "icu_provider"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
|
||||
checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_locale_core",
|
||||
@@ -1967,9 +1964,9 @@ checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.91"
|
||||
version = "0.3.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c"
|
||||
checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
@@ -2007,9 +2004,9 @@ checksum = "803ec87c9cfb29b9d2633f20cba1f488db3fd53f2158b1024cbefb47ba05d413"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.183"
|
||||
version = "0.2.184"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
||||
checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
@@ -2045,9 +2042,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.14"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a"
|
||||
checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -2060,9 +2057,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
|
||||
checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
|
||||
|
||||
[[package]]
|
||||
name = "litrs"
|
||||
@@ -2087,9 +2084,9 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "lsm-tree"
|
||||
version = "3.1.2"
|
||||
version = "3.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d67f95fd716870329c30aaeedf87f23d426564e6ce46efa045a91444faf2a19"
|
||||
checksum = "e9bfd2a6ea0c1d430c13643002f35800a87f200fc8ac4827f18a2db9d9fd0644"
|
||||
dependencies = [
|
||||
"byteorder-lite",
|
||||
"byteview",
|
||||
@@ -2097,7 +2094,7 @@ dependencies = [
|
||||
"enum_dispatch",
|
||||
"interval-heap",
|
||||
"log",
|
||||
"lz4_flex",
|
||||
"lz4_flex 0.11.6",
|
||||
"quick_cache",
|
||||
"rustc-hash",
|
||||
"self_cell",
|
||||
@@ -2109,13 +2106,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lz4_flex"
|
||||
version = "0.13.0"
|
||||
version = "0.11.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db9a0d582c2874f68138a16ce1867e0ffde6c0bb0a0df85e1f36d04146db488a"
|
||||
checksum = "373f5eceeeab7925e0c1098212f2fbc4d416adec9d35051a6ab251e824c1854a"
|
||||
dependencies = [
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lz4_flex"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db9a0d582c2874f68138a16ce1867e0ffde6c0bb0a0df85e1f36d04146db488a"
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.8.4"
|
||||
@@ -2180,9 +2183,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.1.1"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
|
||||
checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
@@ -2201,9 +2204,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050"
|
||||
checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
@@ -2216,9 +2219,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oas3"
|
||||
version = "0.20.1"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16f67c885c7b19aaf652e84102035258ecb4e0425a4f71037e187798e367bd87"
|
||||
checksum = "05ed0821ab10d7703415a06df039c2493f3a7667999d8b4e104731de0c53796f"
|
||||
dependencies = [
|
||||
"derive_more",
|
||||
"http",
|
||||
@@ -2324,12 +2327,6 @@ version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.32"
|
||||
@@ -2412,9 +2409,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "potential_utf"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
|
||||
checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564"
|
||||
dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
@@ -2545,9 +2542,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rawdb"
|
||||
version = "0.7.2"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "912a9c6f76a5f141057139d510b969b082ff74f39a72a1c27178d8e1eeec95dc"
|
||||
checksum = "f23b5d5fae99af33e8d0c82763b890c469dcf18b48600ed78b0d70fce4dbe189"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
@@ -2678,9 +2675,9 @@ checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
version = "2.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
@@ -2916,9 +2913,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.0.4"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
|
||||
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
@@ -2963,9 +2960,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.8"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
|
||||
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
@@ -3134,9 +3131,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
|
||||
checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"zerovec",
|
||||
@@ -3182,9 +3179,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "1.0.7+spec-1.1.0"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd28d57d8a6f6e458bc0b8784f8fdcc4b99a437936056fa122cb234f18656a96"
|
||||
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde_core",
|
||||
@@ -3197,27 +3194,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "1.0.1+spec-1.1.0"
|
||||
version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b320e741db58cac564e26c607d3cc1fdc4a88fd36c879568c07856ed83ff3e9"
|
||||
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.10+spec-1.1.0"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7df25b4befd31c4816df190124375d5a20c6b6921e2cad937316de3fccd63420"
|
||||
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_writer"
|
||||
version = "1.0.7+spec-1.1.0"
|
||||
version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f17aaa1c6e3dc22b1da4b6bba97d066e354c7945cac2f7852d4e4e7ca7a6b56d"
|
||||
checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
@@ -3352,9 +3349,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.12.0"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||
checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
@@ -3439,14 +3436,14 @@ checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23"
|
||||
|
||||
[[package]]
|
||||
name = "vecdb"
|
||||
version = "0.7.2"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6f89be182f86511ee28832cc04039d818564b88c63b14093fcf1871c732c0dd"
|
||||
checksum = "a5fe60956ddba8c141ca8020aaf5bea55683475b83d19006c5f44b85c71bf974"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"libc",
|
||||
"log",
|
||||
"lz4_flex",
|
||||
"lz4_flex 0.13.0",
|
||||
"parking_lot",
|
||||
"pco",
|
||||
"rawdb",
|
||||
@@ -3462,9 +3459,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "vecdb_derive"
|
||||
version = "0.7.2"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42915a5ca404d941e3e6d024f794403c481e5aeb96b1867d12d1f1e972d1433f"
|
||||
checksum = "789897c1999d5d74f977020ad3d449846df046194103a4afcbac6d49baeaaffc"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
@@ -3512,9 +3509,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.114"
|
||||
version = "0.2.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e"
|
||||
checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
@@ -3525,9 +3522,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.114"
|
||||
version = "0.2.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6"
|
||||
checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -3535,9 +3532,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.114"
|
||||
version = "0.2.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3"
|
||||
checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
@@ -3548,9 +3545,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.114"
|
||||
version = "0.2.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16"
|
||||
checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -3591,9 +3588,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.91"
|
||||
version = "0.3.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9"
|
||||
checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
@@ -3788,9 +3785,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8"
|
||||
checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5"
|
||||
|
||||
[[package]]
|
||||
name = "wio"
|
||||
@@ -3891,9 +3888,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
|
||||
checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"
|
||||
|
||||
[[package]]
|
||||
name = "xxhash-rust"
|
||||
@@ -3914,9 +3911,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
|
||||
checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca"
|
||||
dependencies = [
|
||||
"stable_deref_trait",
|
||||
"yoke-derive",
|
||||
@@ -3925,9 +3922,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "yoke-derive"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
|
||||
checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3937,18 +3934,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.47"
|
||||
version = "0.8.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87"
|
||||
checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.47"
|
||||
version = "0.8.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89"
|
||||
checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3957,18 +3954,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
|
||||
checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
|
||||
dependencies = [
|
||||
"zerofrom-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom-derive"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
||||
checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3984,9 +3981,9 @@ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
||||
|
||||
[[package]]
|
||||
name = "zerotrie"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
|
||||
checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"yoke",
|
||||
@@ -3995,9 +3992,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerovec"
|
||||
version = "0.11.5"
|
||||
version = "0.11.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
|
||||
checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239"
|
||||
dependencies = [
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
@@ -4006,9 +4003,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerovec-derive"
|
||||
version = "0.11.2"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
|
||||
checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
+28
-27
@@ -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.2.0"
|
||||
package.version = "0.3.0-alpha.3"
|
||||
package.homepage = "https://bitcoinresearchkit.org"
|
||||
package.repository = "https://github.com/bitcoinresearchkit/brk"
|
||||
package.readme = "README.md"
|
||||
@@ -40,42 +40,42 @@ aide = { version = "0.16.0-alpha.3", features = ["axum-json", "axum-query"] }
|
||||
axum = { version = "0.8.8", default-features = false, features = ["http1", "json", "query", "tokio", "tracing"] }
|
||||
bitcoin = { version = "0.32.8", features = ["serde"] }
|
||||
bitcoincore-rpc = "0.19.0"
|
||||
brk_alloc = { version = "0.2.0", path = "crates/brk_alloc" }
|
||||
brk_bencher = { version = "0.2.0", path = "crates/brk_bencher" }
|
||||
brk_bindgen = { version = "0.2.0", path = "crates/brk_bindgen" }
|
||||
brk_cli = { version = "0.2.0", path = "crates/brk_cli" }
|
||||
brk_client = { version = "0.2.0", path = "crates/brk_client" }
|
||||
brk_cohort = { version = "0.2.0", path = "crates/brk_cohort" }
|
||||
brk_computer = { version = "0.2.0", path = "crates/brk_computer" }
|
||||
brk_error = { version = "0.2.0", path = "crates/brk_error" }
|
||||
brk_fetcher = { version = "0.2.0", path = "crates/brk_fetcher" }
|
||||
brk_indexer = { version = "0.2.0", path = "crates/brk_indexer" }
|
||||
brk_iterator = { version = "0.2.0", path = "crates/brk_iterator" }
|
||||
brk_logger = { version = "0.2.0", path = "crates/brk_logger" }
|
||||
brk_mempool = { version = "0.2.0", path = "crates/brk_mempool" }
|
||||
brk_oracle = { version = "0.2.0", path = "crates/brk_oracle" }
|
||||
brk_query = { version = "0.2.0", path = "crates/brk_query", features = ["tokio"] }
|
||||
brk_reader = { version = "0.2.0", path = "crates/brk_reader" }
|
||||
brk_rpc = { version = "0.2.0", path = "crates/brk_rpc" }
|
||||
brk_server = { version = "0.2.0", path = "crates/brk_server" }
|
||||
brk_store = { version = "0.2.0", path = "crates/brk_store" }
|
||||
brk_traversable = { version = "0.2.0", path = "crates/brk_traversable", features = ["pco", "derive"] }
|
||||
brk_traversable_derive = { version = "0.2.0", path = "crates/brk_traversable_derive" }
|
||||
brk_types = { version = "0.2.0", path = "crates/brk_types" }
|
||||
brk_website = { version = "0.2.0", path = "crates/brk_website" }
|
||||
brk_alloc = { version = "0.3.0-alpha.3", path = "crates/brk_alloc" }
|
||||
brk_bencher = { version = "0.3.0-alpha.3", path = "crates/brk_bencher" }
|
||||
brk_bindgen = { version = "0.3.0-alpha.3", path = "crates/brk_bindgen" }
|
||||
brk_cli = { version = "0.3.0-alpha.3", path = "crates/brk_cli" }
|
||||
brk_client = { version = "0.3.0-alpha.3", path = "crates/brk_client" }
|
||||
brk_cohort = { version = "0.3.0-alpha.3", path = "crates/brk_cohort" }
|
||||
brk_computer = { version = "0.3.0-alpha.3", path = "crates/brk_computer" }
|
||||
brk_error = { version = "0.3.0-alpha.3", path = "crates/brk_error" }
|
||||
brk_fetcher = { version = "0.3.0-alpha.3", path = "crates/brk_fetcher" }
|
||||
brk_indexer = { version = "0.3.0-alpha.3", path = "crates/brk_indexer" }
|
||||
brk_iterator = { version = "0.3.0-alpha.3", path = "crates/brk_iterator" }
|
||||
brk_logger = { version = "0.3.0-alpha.3", path = "crates/brk_logger" }
|
||||
brk_mempool = { version = "0.3.0-alpha.3", path = "crates/brk_mempool" }
|
||||
brk_oracle = { version = "0.3.0-alpha.3", path = "crates/brk_oracle" }
|
||||
brk_query = { version = "0.3.0-alpha.3", path = "crates/brk_query", features = ["tokio"] }
|
||||
brk_reader = { version = "0.3.0-alpha.3", path = "crates/brk_reader" }
|
||||
brk_rpc = { version = "0.3.0-alpha.3", path = "crates/brk_rpc" }
|
||||
brk_server = { version = "0.3.0-alpha.3", path = "crates/brk_server" }
|
||||
brk_store = { version = "0.3.0-alpha.3", path = "crates/brk_store" }
|
||||
brk_traversable = { version = "0.3.0-alpha.3", path = "crates/brk_traversable", features = ["pco", "derive"] }
|
||||
brk_traversable_derive = { version = "0.3.0-alpha.3", path = "crates/brk_traversable_derive" }
|
||||
brk_types = { version = "0.3.0-alpha.3", path = "crates/brk_types" }
|
||||
brk_website = { version = "0.3.0-alpha.3", path = "crates/brk_website" }
|
||||
byteview = "0.10.1"
|
||||
color-eyre = "0.6.5"
|
||||
corepc-client = { package = "brk-corepc-client", version = "0.11.0", features = ["client-sync"] }
|
||||
corepc-jsonrpc = { package = "brk-corepc-jsonrpc", version = "0.19.0", features = ["simple_http"], default-features = false }
|
||||
derive_more = { version = "2.1.1", features = ["deref", "deref_mut"] }
|
||||
fjall = "3.1.2"
|
||||
fjall = "=3.0.4"
|
||||
indexmap = { version = "2.13.0", features = ["serde"] }
|
||||
jiff = { version = "0.2.23", features = ["perf-inline", "tz-system"], default-features = false }
|
||||
owo-colors = "4.3.0"
|
||||
parking_lot = "0.12.5"
|
||||
pco = "1.0.1"
|
||||
rayon = "1.11.0"
|
||||
rustc-hash = "2.1.1"
|
||||
rustc-hash = "2.1.2"
|
||||
schemars = { version = "1.2.1", features = ["indexmap2"] }
|
||||
serde = "1.0.228"
|
||||
serde_bytes = "0.11.19"
|
||||
@@ -87,7 +87,7 @@ tower-http = { version = "0.6.8", features = ["catch-panic", "compression-br", "
|
||||
tower-layer = "0.3"
|
||||
tracing = { version = "0.1", default-features = false, features = ["std"] }
|
||||
ureq = { version = "3.3.0", features = ["json"] }
|
||||
vecdb = { version = "0.7.2", features = ["derive", "serde_json", "pco", "schemars"] }
|
||||
vecdb = { version = "0.9.3", features = ["derive", "serde_json", "pco", "schemars"] }
|
||||
# vecdb = { path = "../anydb/crates/vecdb", features = ["derive", "serde_json", "pco", "schemars"] }
|
||||
|
||||
[workspace.metadata.release]
|
||||
@@ -95,6 +95,7 @@ shared-version = true
|
||||
tag-name = "v{{version}}"
|
||||
pre-release-commit-message = "release: v{{version}}"
|
||||
tag-message = "release: v{{version}}"
|
||||
allow-branch = ["main", "next"]
|
||||
|
||||
[workspace.metadata.dist]
|
||||
cargo-dist-version = "0.30.2"
|
||||
|
||||
@@ -12,6 +12,6 @@ brk_cohort = { workspace = true }
|
||||
brk_query = { workspace = true }
|
||||
brk_types = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
oas3 = "0.20"
|
||||
oas3 = "0.21"
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
@@ -108,7 +108,13 @@ fn fill_mixed_empty_field_parts(
|
||||
// Recurse first (bottom-up)
|
||||
for (field_name, child_node) in children {
|
||||
let child_path = build_child_path(path, field_name);
|
||||
fill_mixed_empty_field_parts(child_node, &child_path, pattern_lookup, patterns, node_bases);
|
||||
fill_mixed_empty_field_parts(
|
||||
child_node,
|
||||
&child_path,
|
||||
pattern_lookup,
|
||||
patterns,
|
||||
node_bases,
|
||||
);
|
||||
}
|
||||
|
||||
// Check if this node has mixed empty/non-empty field_parts
|
||||
@@ -351,16 +357,18 @@ fn try_embedded_disc(
|
||||
}
|
||||
|
||||
/// Strategy 2: suffix discriminator (e.g., all field_parts differ by `_4y` suffix)
|
||||
fn try_suffix_disc(
|
||||
majority: &[&InstanceAnalysis],
|
||||
fields: &[PatternField],
|
||||
) -> Option<PatternMode> {
|
||||
fn try_suffix_disc(majority: &[&InstanceAnalysis], fields: &[PatternField]) -> Option<PatternMode> {
|
||||
let first = &majority[0];
|
||||
|
||||
// Use a non-empty field to detect the suffix
|
||||
let ref_field = fields
|
||||
.iter()
|
||||
.find(|f| first.field_parts.get(&f.name).is_some_and(|v| !v.is_empty()))
|
||||
.find(|f| {
|
||||
first
|
||||
.field_parts
|
||||
.get(&f.name)
|
||||
.is_some_and(|v| !v.is_empty())
|
||||
})
|
||||
.map(|f| &f.name)?;
|
||||
let ref_first = first.field_parts.get(ref_field)?;
|
||||
|
||||
@@ -763,19 +771,51 @@ mod tests {
|
||||
fn test_embedded_disc_percentile_bands() {
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "bps".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "price".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "ratio".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField {
|
||||
name: "bps".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
PatternField {
|
||||
name: "price".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
PatternField {
|
||||
name: "ratio".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
];
|
||||
let pct99 = InstanceAnalysis {
|
||||
base: "realized_price".into(),
|
||||
field_parts: [("bps".into(), "ratio_pct99_bps".into()), ("price".into(), "pct99".into()), ("ratio".into(), "ratio_pct99".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
field_parts: [
|
||||
("bps".into(), "ratio_pct99_bps".into()),
|
||||
("price".into(), "pct99".into()),
|
||||
("ratio".into(), "ratio_pct99".into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let pct1 = InstanceAnalysis {
|
||||
base: "realized_price".into(),
|
||||
field_parts: [("bps".into(), "ratio_pct1_bps".into()), ("price".into(), "pct1".into()), ("ratio".into(), "ratio_pct1".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
field_parts: [
|
||||
("bps".into(), "ratio_pct1_bps".into()),
|
||||
("price".into(), "pct1".into()),
|
||||
("ratio".into(), "ratio_pct1".into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[pct99, pct1], &fields);
|
||||
assert!(mode.is_some());
|
||||
@@ -793,19 +833,51 @@ mod tests {
|
||||
fn test_suffix_disc_period_windows() {
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "p1sd".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "sd".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "zscore".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField {
|
||||
name: "p1sd".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
PatternField {
|
||||
name: "sd".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
PatternField {
|
||||
name: "zscore".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
];
|
||||
let all_time = InstanceAnalysis {
|
||||
base: "realized_price".into(),
|
||||
field_parts: [("p1sd".into(), "p1sd".into()), ("sd".into(), "ratio_sd".into()), ("zscore".into(), "ratio_zscore".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
field_parts: [
|
||||
("p1sd".into(), "p1sd".into()),
|
||||
("sd".into(), "ratio_sd".into()),
|
||||
("zscore".into(), "ratio_zscore".into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let four_year = InstanceAnalysis {
|
||||
base: "realized_price".into(),
|
||||
field_parts: [("p1sd".into(), "p1sd_4y".into()), ("sd".into(), "ratio_sd_4y".into()), ("zscore".into(), "ratio_zscore_4y".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
field_parts: [
|
||||
("p1sd".into(), "p1sd_4y".into()),
|
||||
("sd".into(), "ratio_sd_4y".into()),
|
||||
("zscore".into(), "ratio_zscore_4y".into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[all_time, four_year], &fields);
|
||||
assert!(mode.is_some());
|
||||
@@ -823,18 +895,39 @@ mod tests {
|
||||
fn test_suffix_disc_with_empty_fields() {
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "band".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "sd".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField {
|
||||
name: "band".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
PatternField {
|
||||
name: "sd".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
];
|
||||
let all_time = InstanceAnalysis {
|
||||
base: "price".into(),
|
||||
field_parts: [("band".into(), "".into()), ("sd".into(), "ratio_sd".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
field_parts: [("band".into(), "".into()), ("sd".into(), "ratio_sd".into())]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let four_year = InstanceAnalysis {
|
||||
base: "price".into(),
|
||||
field_parts: [("band".into(), "".into()), ("sd".into(), "ratio_sd_4y".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
field_parts: [
|
||||
("band".into(), "".into()),
|
||||
("sd".into(), "ratio_sd_4y".into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[all_time, four_year], &fields);
|
||||
assert!(mode.is_some());
|
||||
@@ -851,18 +944,39 @@ mod tests {
|
||||
fn test_suffix_disc_empty_to_nonempty() {
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "all".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "sth".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField {
|
||||
name: "all".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
PatternField {
|
||||
name: "sth".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
];
|
||||
let regular = InstanceAnalysis {
|
||||
base: "supply".into(),
|
||||
field_parts: [("all".into(), "".into()), ("sth".into(), "sth_".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
field_parts: [("all".into(), "".into()), ("sth".into(), "sth_".into())]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let profitability = InstanceAnalysis {
|
||||
base: "utxos_in_profit".into(),
|
||||
field_parts: [("all".into(), "supply".into()), ("sth".into(), "sth_supply".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
field_parts: [
|
||||
("all".into(), "supply".into()),
|
||||
("sth".into(), "sth_supply".into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[regular, profitability], &fields);
|
||||
assert!(mode.is_some());
|
||||
@@ -879,43 +993,91 @@ mod tests {
|
||||
fn test_outlier_rejects_pattern() {
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "ratio".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "value".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField {
|
||||
name: "ratio".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
PatternField {
|
||||
name: "value".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
];
|
||||
// SOPR case: one instance has outlier naming (no common prefix)
|
||||
let normal = InstanceAnalysis {
|
||||
base: "series".into(),
|
||||
field_parts: [("ratio".into(), "ratio".into()), ("value".into(), "value".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
field_parts: [
|
||||
("ratio".into(), "ratio".into()),
|
||||
("value".into(), "value".into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let outlier = InstanceAnalysis {
|
||||
base: "".into(),
|
||||
field_parts: [("ratio".into(), "asopr".into()), ("value".into(), "adj_value".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: true,
|
||||
field_parts: [
|
||||
("ratio".into(), "asopr".into()),
|
||||
("value".into(), "adj_value".into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: true,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[normal, outlier], &fields);
|
||||
assert!(mode.is_some(), "Outlier should be filtered out, leaving a valid pattern from non-outlier instances");
|
||||
assert!(
|
||||
mode.is_some(),
|
||||
"Outlier should be filtered out, leaving a valid pattern from non-outlier instances"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unanimity_rejects_disagreeing_instances() {
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "a".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "b".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField {
|
||||
name: "a".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
PatternField {
|
||||
name: "b".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
];
|
||||
let inst1 = InstanceAnalysis {
|
||||
base: "x".into(),
|
||||
field_parts: [("a".into(), "foo".into()), ("b".into(), "bar".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
field_parts: [("a".into(), "foo".into()), ("b".into(), "bar".into())]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let inst2 = InstanceAnalysis {
|
||||
base: "y".into(),
|
||||
field_parts: [("a".into(), "baz".into()), ("b".into(), "qux".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
field_parts: [("a".into(), "baz".into()), ("b".into(), "qux".into())]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[inst1, inst2], &fields);
|
||||
assert!(mode.is_none(), "Should be non-parameterizable when no pattern detected");
|
||||
assert!(
|
||||
mode.is_none(),
|
||||
"Should be non-parameterizable when no pattern detected"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -925,20 +1087,43 @@ mod tests {
|
||||
// Should keep identity (empty parts) so both children receive acc unchanged.
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "absolute".into(), rust_type: "TypeA".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "rate".into(), rust_type: "TypeB".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField {
|
||||
name: "absolute".into(),
|
||||
rust_type: "TypeA".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
PatternField {
|
||||
name: "rate".into(),
|
||||
rust_type: "TypeB".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
];
|
||||
let inst = InstanceAnalysis {
|
||||
base: "supply_delta".into(),
|
||||
field_parts: [("absolute".into(), "".into()), ("rate".into(), "".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
field_parts: [("absolute".into(), "".into()), ("rate".into(), "".into())]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[inst], &fields);
|
||||
assert!(mode.is_some());
|
||||
match mode.unwrap() {
|
||||
PatternMode::Suffix { relatives } => {
|
||||
assert_eq!(relatives.get("absolute"), Some(&"".to_string()), "absolute should be identity");
|
||||
assert_eq!(relatives.get("rate"), Some(&"".to_string()), "rate should be identity");
|
||||
assert_eq!(
|
||||
relatives.get("absolute"),
|
||||
Some(&"".to_string()),
|
||||
"absolute should be identity"
|
||||
);
|
||||
assert_eq!(
|
||||
relatives.get("rate"),
|
||||
Some(&"".to_string()),
|
||||
"rate should be identity"
|
||||
);
|
||||
}
|
||||
other => panic!("Expected Suffix with identity, got {:?}", other),
|
||||
}
|
||||
@@ -975,16 +1160,26 @@ mod tests {
|
||||
// Parent patterns containing non-parameterizable children should also
|
||||
// be detected via metadata.is_parameterizable (recursive check).
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "a".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
];
|
||||
let fields = vec![PatternField {
|
||||
name: "a".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
}];
|
||||
let inst = InstanceAnalysis {
|
||||
base: "".into(),
|
||||
field_parts: [("a".into(), "standalone_name".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: true,
|
||||
field_parts: [("a".into(), "standalone_name".into())]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: true,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[inst], &fields);
|
||||
assert!(mode.is_none(), "Pattern with outlier should be non-parameterizable");
|
||||
assert!(
|
||||
mode.is_none(),
|
||||
"Pattern with outlier should be non-parameterizable"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -998,9 +1193,27 @@ mod tests {
|
||||
let pattern = StructuralPattern {
|
||||
name: "TestPattern".into(),
|
||||
fields: vec![
|
||||
PatternField { name: "_0sd".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "p1sd".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "sd".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField {
|
||||
name: "_0sd".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
PatternField {
|
||||
name: "p1sd".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
PatternField {
|
||||
name: "sd".into(),
|
||||
rust_type: "T".into(),
|
||||
json_type: "n".into(),
|
||||
indexes: BTreeSet::new(),
|
||||
type_param: None,
|
||||
},
|
||||
],
|
||||
mode: Some(PatternMode::Templated {
|
||||
templates: [
|
||||
@@ -1059,9 +1272,15 @@ mod tests {
|
||||
assert_eq!(analysis.field_parts.get("loss"), Some(&"".to_string()));
|
||||
assert_eq!(analysis.field_parts.get("supply"), Some(&"".to_string()));
|
||||
// others should be non-empty
|
||||
assert_eq!(analysis.field_parts.get("cap"), Some(&"realized_cap".to_string()));
|
||||
assert_eq!(
|
||||
analysis.field_parts.get("cap"),
|
||||
Some(&"realized_cap".to_string())
|
||||
);
|
||||
assert_eq!(analysis.field_parts.get("mvrv"), Some(&"mvrv".to_string()));
|
||||
assert_eq!(analysis.field_parts.get("price"), Some(&"realized_price".to_string()));
|
||||
assert_eq!(
|
||||
analysis.field_parts.get("price"),
|
||||
Some(&"realized_price".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1111,12 +1330,20 @@ mod tests {
|
||||
&mut path_to_pattern,
|
||||
);
|
||||
|
||||
let result = node_bases.get("test").expect("should have node_bases entry");
|
||||
let result = node_bases
|
||||
.get("test")
|
||||
.expect("should have node_bases entry");
|
||||
assert_eq!(result.base, "utxos");
|
||||
assert!(!result.has_outlier);
|
||||
assert_eq!(result.field_parts.get("cap"), Some(&"realized_cap".to_string()));
|
||||
assert_eq!(
|
||||
result.field_parts.get("cap"),
|
||||
Some(&"realized_cap".to_string())
|
||||
);
|
||||
assert_eq!(result.field_parts.get("mvrv"), Some(&"mvrv".to_string()));
|
||||
// loss branch returns base "utxos_realized_loss" which yields field_part "realized_loss"
|
||||
assert_eq!(result.field_parts.get("loss"), Some(&"realized_loss".to_string()));
|
||||
assert_eq!(
|
||||
result.field_parts.get("loss"),
|
||||
Some(&"realized_loss".to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use brk_cohort::{
|
||||
AGE_RANGE_NAMES, AMOUNT_RANGE_NAMES, CLASS_NAMES, EPOCH_NAMES, LOSS_NAMES,
|
||||
OVER_AGE_NAMES, OVER_AMOUNT_NAMES, PROFITABILITY_RANGE_NAMES, PROFIT_NAMES,
|
||||
SPENDABLE_TYPE_NAMES, TERM_NAMES, UNDER_AGE_NAMES, UNDER_AMOUNT_NAMES,
|
||||
AGE_RANGE_NAMES, AMOUNT_RANGE_NAMES, CLASS_NAMES, EPOCH_NAMES, LOSS_NAMES, OVER_AGE_NAMES,
|
||||
OVER_AMOUNT_NAMES, PROFIT_NAMES, PROFITABILITY_RANGE_NAMES, SPENDABLE_TYPE_NAMES, TERM_NAMES,
|
||||
UNDER_AGE_NAMES, UNDER_AMOUNT_NAMES,
|
||||
};
|
||||
use brk_types::{Index, PoolSlug, pools};
|
||||
use serde::Serialize;
|
||||
@@ -64,7 +64,10 @@ impl CohortConstants {
|
||||
("AMOUNT_RANGE_NAMES", to_value(&AMOUNT_RANGE_NAMES)),
|
||||
("OVER_AMOUNT_NAMES", to_value(&OVER_AMOUNT_NAMES)),
|
||||
("UNDER_AMOUNT_NAMES", to_value(&UNDER_AMOUNT_NAMES)),
|
||||
("PROFITABILITY_RANGE_NAMES", to_value(&PROFITABILITY_RANGE_NAMES)),
|
||||
(
|
||||
"PROFITABILITY_RANGE_NAMES",
|
||||
to_value(&PROFITABILITY_RANGE_NAMES),
|
||||
),
|
||||
("PROFIT_NAMES", to_value(&PROFIT_NAMES)),
|
||||
("LOSS_NAMES", to_value(&LOSS_NAMES)),
|
||||
]
|
||||
|
||||
@@ -8,7 +8,9 @@ use std::fmt::Write;
|
||||
|
||||
use brk_types::SeriesLeafWithSchema;
|
||||
|
||||
use crate::{ClientMetadata, LanguageSyntax, PatternBaseResult, PatternField, PatternMode, StructuralPattern};
|
||||
use crate::{
|
||||
ClientMetadata, LanguageSyntax, PatternBaseResult, PatternField, PatternMode, StructuralPattern,
|
||||
};
|
||||
|
||||
/// Create a path suffix from a name.
|
||||
fn path_suffix(name: &str) -> String {
|
||||
@@ -33,9 +35,7 @@ fn compute_parameterized_value<S: LanguageSyntax>(
|
||||
if let Some(child_pattern) = metadata.find_pattern(&field.rust_type)
|
||||
&& child_pattern.is_templated()
|
||||
{
|
||||
let disc_template = pattern
|
||||
.get_field_part(&field.name)
|
||||
.unwrap_or(&field.name);
|
||||
let disc_template = pattern.get_field_part(&field.name).unwrap_or(&field.name);
|
||||
let disc_arg = syntax.disc_arg_expr(disc_template);
|
||||
let acc_arg = syntax.owned_expr("acc");
|
||||
return syntax.constructor(&field.rust_type, &format!("{acc_arg}, {disc_arg}"));
|
||||
|
||||
@@ -125,8 +125,8 @@ pub fn prepare_tree_node<'a>(
|
||||
p.is_suffix_mode() == base_result.is_suffix_mode
|
||||
&& p.field_parts_match(&base_result.field_parts)
|
||||
});
|
||||
let is_parameterizable = matching_pattern
|
||||
.is_none_or(|p| metadata.is_parameterizable(&p.name));
|
||||
let is_parameterizable =
|
||||
matching_pattern.is_none_or(|p| metadata.is_parameterizable(&p.name));
|
||||
|
||||
// should_inline determines if we generate an inline struct type
|
||||
let should_inline = !is_leaf
|
||||
|
||||
@@ -82,18 +82,19 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
|
||||
} else {
|
||||
writeln!(output, " const params = new URLSearchParams();").unwrap();
|
||||
for param in &endpoint.query_params {
|
||||
let ident = sanitize_ident(¶m.name);
|
||||
if param.required {
|
||||
writeln!(
|
||||
output,
|
||||
" params.set('{}', String({}));",
|
||||
param.name, param.name
|
||||
param.name, ident
|
||||
)
|
||||
.unwrap();
|
||||
} else {
|
||||
writeln!(
|
||||
output,
|
||||
" if ({} !== undefined) params.set('{}', String({}));",
|
||||
param.name, param.name, param.name
|
||||
ident, param.name, ident
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
@@ -127,14 +128,19 @@ fn endpoint_to_method_name(endpoint: &Endpoint) -> String {
|
||||
fn build_method_params(endpoint: &Endpoint) -> String {
|
||||
let mut params = Vec::new();
|
||||
for param in &endpoint.path_params {
|
||||
params.push(param.name.clone());
|
||||
params.push(sanitize_ident(¶m.name));
|
||||
}
|
||||
for param in &endpoint.query_params {
|
||||
params.push(param.name.clone());
|
||||
params.push(sanitize_ident(¶m.name));
|
||||
}
|
||||
params.join(", ")
|
||||
}
|
||||
|
||||
/// Strip characters invalid in JS identifiers (e.g. `[]` from `txId[]`).
|
||||
fn sanitize_ident(name: &str) -> String {
|
||||
name.replace(['[', ']'], "")
|
||||
}
|
||||
|
||||
fn build_path_template(path: &str, path_params: &[Parameter]) -> String {
|
||||
let mut result = path.to_string();
|
||||
for param in path_params {
|
||||
|
||||
@@ -22,6 +22,20 @@ pub fn generate_base_client(output: &mut String) {
|
||||
const _isBrowser = typeof window !== 'undefined' && 'caches' in window;
|
||||
const _runIdle = (/** @type {{VoidFunction}} */ fn) => (globalThis.requestIdleCallback ?? setTimeout)(fn);
|
||||
const _defaultCacheName = '__BRK_CLIENT__';
|
||||
/** @param {{*}} v */
|
||||
const _addCamelGetters = (v) => {{
|
||||
if (Array.isArray(v)) {{ v.forEach(_addCamelGetters); return v; }}
|
||||
if (v && typeof v === 'object' && v.constructor === Object) {{
|
||||
for (const k in v) {{
|
||||
if (k.includes('_')) {{
|
||||
const c = k.replace(/_([a-z])/g, (_, l) => l.toUpperCase());
|
||||
if (!(c in v)) Object.defineProperty(v, c, {{ get() {{ return this[k]; }} }});
|
||||
}}
|
||||
_addCamelGetters(v[k]);
|
||||
}}
|
||||
}}
|
||||
return v;
|
||||
}};
|
||||
|
||||
/**
|
||||
* @param {{string|boolean|undefined}} cache
|
||||
@@ -418,7 +432,7 @@ class BrkClientBase {{
|
||||
const cachePromise = cache?.match(url).then(async (res) => {{
|
||||
cachedRes = res ?? null;
|
||||
if (!res) return null;
|
||||
const json = await res.json();
|
||||
const json = _addCamelGetters(await res.json());
|
||||
if (!resolved && onUpdate) {{
|
||||
resolved = true;
|
||||
onUpdate(json);
|
||||
@@ -428,7 +442,7 @@ class BrkClientBase {{
|
||||
|
||||
const networkPromise = this.get(path).then(async (res) => {{
|
||||
const cloned = res.clone();
|
||||
const json = await res.json();
|
||||
const json = _addCamelGetters(await res.json());
|
||||
// Skip update if ETag matches and cache already delivered
|
||||
if (cachedRes?.headers.get('ETag') === res.headers.get('ETag')) {{
|
||||
if (!resolved && onUpdate) {{
|
||||
@@ -726,7 +740,12 @@ pub fn generate_structural_patterns(
|
||||
writeln!(output, " */").unwrap();
|
||||
|
||||
if pattern.is_templated() {
|
||||
writeln!(output, "function create{}(client, acc, disc) {{", pattern.name).unwrap();
|
||||
writeln!(
|
||||
output,
|
||||
"function create{}(client, acc, disc) {{",
|
||||
pattern.name
|
||||
)
|
||||
.unwrap();
|
||||
} else {
|
||||
writeln!(output, "function create{}(client, acc) {{", pattern.name).unwrap();
|
||||
}
|
||||
|
||||
@@ -56,11 +56,7 @@ pub fn generate_main_client(output: &mut String, endpoints: &[Endpoint]) {
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(output, " \"\"\"").unwrap();
|
||||
writeln!(
|
||||
output,
|
||||
" return SeriesEndpoint(self, series, index)"
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(output, " return SeriesEndpoint(self, series, index)").unwrap();
|
||||
writeln!(output).unwrap();
|
||||
|
||||
// Generate helper methods
|
||||
@@ -105,7 +101,7 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
|
||||
.response_type
|
||||
.as_deref()
|
||||
.map(js_type_to_python)
|
||||
.unwrap_or_else(|| "Any".to_string()),
|
||||
.unwrap_or_else(|| "str".to_string()),
|
||||
);
|
||||
|
||||
let return_type = if endpoint.supports_csv {
|
||||
@@ -163,11 +159,17 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
|
||||
// Build path
|
||||
let path = build_path_template(&endpoint.path, &endpoint.path_params);
|
||||
|
||||
let fetch_method = if endpoint.returns_json() {
|
||||
"get_json"
|
||||
} else {
|
||||
"get_text"
|
||||
};
|
||||
|
||||
if endpoint.query_params.is_empty() {
|
||||
if endpoint.path_params.is_empty() {
|
||||
writeln!(output, " return self.get_json('{}')", path).unwrap();
|
||||
writeln!(output, " return self.{}('{}')", fetch_method, path).unwrap();
|
||||
} else {
|
||||
writeln!(output, " return self.get_json(f'{}')", path).unwrap();
|
||||
writeln!(output, " return self.{}(f'{}')", fetch_method, path).unwrap();
|
||||
}
|
||||
} else {
|
||||
writeln!(output, " params = []").unwrap();
|
||||
@@ -201,9 +203,9 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
|
||||
if endpoint.supports_csv {
|
||||
writeln!(output, " if format == 'csv':").unwrap();
|
||||
writeln!(output, " return self.get_text(path)").unwrap();
|
||||
writeln!(output, " return self.get_json(path)").unwrap();
|
||||
writeln!(output, " return self.{}(path)", fetch_method).unwrap();
|
||||
} else {
|
||||
writeln!(output, " return self.get_json(path)").unwrap();
|
||||
writeln!(output, " return self.{}(path)", fetch_method).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -684,7 +684,6 @@ pub fn generate_structural_patterns(
|
||||
writeln!(output, "# Reusable structural pattern classes\n").unwrap();
|
||||
|
||||
for pattern in patterns {
|
||||
|
||||
// Generate class
|
||||
if pattern.is_generic {
|
||||
writeln!(output, "class {}(Generic[T]):", pattern.name).unwrap();
|
||||
|
||||
@@ -93,7 +93,7 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
|
||||
.response_type
|
||||
.as_deref()
|
||||
.map(js_type_to_rust)
|
||||
.unwrap_or_else(|| "serde_json::Value".to_string());
|
||||
.unwrap_or_else(|| "String".to_string());
|
||||
|
||||
let return_type = if endpoint.supports_csv {
|
||||
format!("FormatResponse<{}>", base_return_type)
|
||||
@@ -132,29 +132,43 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
|
||||
.unwrap();
|
||||
|
||||
let (path, index_arg) = build_path_template(endpoint);
|
||||
let fetch_method = if endpoint.returns_json() {
|
||||
"get_json"
|
||||
} else {
|
||||
"get_text"
|
||||
};
|
||||
|
||||
if endpoint.query_params.is_empty() {
|
||||
writeln!(
|
||||
output,
|
||||
" self.base.get_json(&format!(\"{}\"{}))",
|
||||
path, index_arg
|
||||
" self.base.{}(&format!(\"{}\"{}))",
|
||||
fetch_method, path, index_arg
|
||||
)
|
||||
.unwrap();
|
||||
} else {
|
||||
writeln!(output, " let mut query = Vec::new();").unwrap();
|
||||
for param in &endpoint.query_params {
|
||||
if param.required {
|
||||
let ident = sanitize_ident(¶m.name);
|
||||
let is_array = param.param_type.ends_with("[]");
|
||||
if is_array {
|
||||
writeln!(
|
||||
output,
|
||||
" for v in {} {{ query.push(format!(\"{}={{}}\", v)); }}",
|
||||
ident, param.name
|
||||
)
|
||||
.unwrap();
|
||||
} else if param.required {
|
||||
writeln!(
|
||||
output,
|
||||
" query.push(format!(\"{}={{}}\", {}));",
|
||||
param.name, param.name
|
||||
param.name, ident
|
||||
)
|
||||
.unwrap();
|
||||
} else {
|
||||
writeln!(
|
||||
output,
|
||||
" if let Some(v) = {} {{ query.push(format!(\"{}={{}}\", v)); }}",
|
||||
param.name, param.name
|
||||
ident, param.name
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
@@ -177,12 +191,13 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
|
||||
writeln!(output, " }} else {{").unwrap();
|
||||
writeln!(
|
||||
output,
|
||||
" self.base.get_json(&path).map(FormatResponse::Json)"
|
||||
" self.base.{}(&path).map(FormatResponse::Json)",
|
||||
fetch_method
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(output, " }}").unwrap();
|
||||
} else {
|
||||
writeln!(output, " self.base.get_json(&path)").unwrap();
|
||||
writeln!(output, " self.base.{}(&path)", fetch_method).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,26 +213,35 @@ fn build_method_params(endpoint: &Endpoint) -> String {
|
||||
let mut params = Vec::new();
|
||||
for param in &endpoint.path_params {
|
||||
let rust_type = param_type_to_rust(¶m.param_type);
|
||||
params.push(format!(", {}: {}", param.name, rust_type));
|
||||
params.push(format!(", {}: {}", sanitize_ident(¶m.name), rust_type));
|
||||
}
|
||||
for param in &endpoint.query_params {
|
||||
let rust_type = param_type_to_rust(¶m.param_type);
|
||||
let name = sanitize_ident(¶m.name);
|
||||
if param.required {
|
||||
params.push(format!(", {}: {}", param.name, rust_type));
|
||||
params.push(format!(", {}: {}", name, rust_type));
|
||||
} else {
|
||||
params.push(format!(", {}: Option<{}>", param.name, rust_type));
|
||||
params.push(format!(", {}: Option<{}>", name, rust_type));
|
||||
}
|
||||
}
|
||||
params.join("")
|
||||
}
|
||||
|
||||
/// Strip characters invalid in Rust identifiers (e.g. `[]` from `txId[]`).
|
||||
fn sanitize_ident(name: &str) -> String {
|
||||
name.replace(['[', ']'], "")
|
||||
}
|
||||
|
||||
/// Convert parameter type to Rust type for function signatures.
|
||||
fn param_type_to_rust(param_type: &str) -> String {
|
||||
if let Some(inner) = param_type.strip_suffix("[]") {
|
||||
return format!("&[{}]", param_type_to_rust(inner));
|
||||
}
|
||||
match param_type {
|
||||
"string" | "*" => "&str".to_string(),
|
||||
"integer" | "number" => "i64".to_string(),
|
||||
"boolean" => "bool".to_string(),
|
||||
other => other.to_string(), // Domain types like Index, SeriesName, Format
|
||||
other => other.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,11 @@ impl Endpoint {
|
||||
self.method == "GET" && !self.deprecated
|
||||
}
|
||||
|
||||
/// Returns true if this endpoint returns JSON (has a response_type extracted from application/json).
|
||||
pub fn returns_json(&self) -> bool {
|
||||
self.response_type.is_some()
|
||||
}
|
||||
|
||||
/// Returns the operation ID or generates one from the path.
|
||||
/// The returned string uses the raw case from the spec (typically camelCase).
|
||||
pub fn operation_name(&self) -> String {
|
||||
|
||||
@@ -74,6 +74,9 @@ pub fn escape_python_keyword(name: &str) -> String {
|
||||
"try", "while", "with", "yield",
|
||||
];
|
||||
|
||||
// Strip characters invalid in identifiers (e.g. `[]` from `txId[]`)
|
||||
let name = name.replace(['[', ']'], "");
|
||||
|
||||
// Prefix with underscore if starts with digit
|
||||
let name = if name.starts_with(|c: char| c.is_ascii_digit()) {
|
||||
format!("_{}", name)
|
||||
|
||||
@@ -13,7 +13,6 @@ brk_alloc = { workspace = true }
|
||||
brk_computer = { workspace = true }
|
||||
brk_error = { workspace = true, features = ["tokio", "vecdb"] }
|
||||
brk_indexer = { workspace = true }
|
||||
brk_iterator = { workspace = true }
|
||||
brk_logger = { workspace = true }
|
||||
brk_mempool = { workspace = true }
|
||||
brk_query = { workspace = true }
|
||||
@@ -26,7 +25,7 @@ owo-colors = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
toml = "1.0.7"
|
||||
toml = "1.1.2"
|
||||
vecdb = { workspace = true }
|
||||
|
||||
[[bin]]
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
# BRK CLI
|
||||
|
||||
Command-line interface for running a Bitcoin Research Kit instance.
|
||||
Run your own Bitcoin Research Kit instance. One binary, one command. Full sync in ~4-7h depending on hardware. ~44% disk overhead vs 250% for mempool/electrs.
|
||||
|
||||
## Demo
|
||||
|
||||
- [bitview.space](https://bitview.space) - web interface
|
||||
- [bitview.space/api](https://bitview.space/api) - API docs
|
||||
[bitview.space](https://bitview.space) is the official free hosted instance.
|
||||
|
||||
## Requirements
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ use brk_alloc::Mimalloc;
|
||||
use brk_computer::Computer;
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_iterator::Blocks;
|
||||
use brk_mempool::Mempool;
|
||||
use brk_query::AsyncQuery;
|
||||
use brk_reader::Reader;
|
||||
@@ -37,8 +36,6 @@ pub fn main() -> anyhow::Result<()> {
|
||||
|
||||
let reader = Reader::new(config.blocksdir(), &client);
|
||||
|
||||
let blocks = Blocks::new(&client, &reader);
|
||||
|
||||
let mut indexer = Indexer::forced_import(&config.brkdir())?;
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
@@ -52,7 +49,7 @@ pub fn main() -> anyhow::Result<()> {
|
||||
info!("Indexing {blocks_behind} blocks before starting server...");
|
||||
info!("---");
|
||||
sleep(Duration::from_secs(10));
|
||||
indexer.index(&blocks, &client, &exit)?;
|
||||
indexer.index(&reader, &client, &exit)?;
|
||||
drop(indexer);
|
||||
Mimalloc::collect();
|
||||
indexer = Indexer::forced_import(&config.brkdir())?;
|
||||
@@ -102,14 +99,14 @@ pub fn main() -> anyhow::Result<()> {
|
||||
let total_start = Instant::now();
|
||||
|
||||
let starting_indexes = if cfg!(debug_assertions) {
|
||||
indexer.checked_index(&blocks, &client, &exit)?
|
||||
indexer.checked_index(&reader, &client, &exit)?
|
||||
} else {
|
||||
indexer.index(&blocks, &client, &exit)?
|
||||
indexer.index(&reader, &client, &exit)?
|
||||
};
|
||||
|
||||
Mimalloc::collect();
|
||||
|
||||
computer.compute(&indexer, starting_indexes, &reader, &exit)?;
|
||||
computer.compute(&indexer, starting_indexes, &exit)?;
|
||||
|
||||
info!("Total time: {:?}", total_start.elapsed());
|
||||
info!("Waiting for new blocks...");
|
||||
|
||||
+563
-275
File diff suppressed because it is too large
Load Diff
@@ -14,3 +14,6 @@ brk_traversable = { workspace = true }
|
||||
vecdb = { workspace = true }
|
||||
rayon = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
|
||||
[package.metadata.cargo-machete]
|
||||
ignored = ["vecdb"]
|
||||
|
||||
@@ -75,7 +75,8 @@ impl<T> AddrGroups<T> {
|
||||
}
|
||||
|
||||
pub fn iter_overlapping_mut(&mut self) -> impl Iterator<Item = &mut T> {
|
||||
self.under_amount.iter_mut().chain(self.over_amount.iter_mut())
|
||||
self.under_amount
|
||||
.iter_mut()
|
||||
.chain(self.over_amount.iter_mut())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -201,7 +201,29 @@ impl<T> AgeRange<T> {
|
||||
}
|
||||
|
||||
pub fn from_array(arr: [T; 21]) -> Self {
|
||||
let [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20] = arr;
|
||||
let [
|
||||
a0,
|
||||
a1,
|
||||
a2,
|
||||
a3,
|
||||
a4,
|
||||
a5,
|
||||
a6,
|
||||
a7,
|
||||
a8,
|
||||
a9,
|
||||
a10,
|
||||
a11,
|
||||
a12,
|
||||
a13,
|
||||
a14,
|
||||
a15,
|
||||
a16,
|
||||
a17,
|
||||
a18,
|
||||
a19,
|
||||
a20,
|
||||
] = arr;
|
||||
Self {
|
||||
under_1h: a0,
|
||||
_1h_to_1d: a1,
|
||||
|
||||
@@ -84,7 +84,11 @@ pub const AMOUNT_RANGE_NAMES: AmountRange<CohortName> = AmountRange {
|
||||
_10sats_to_100sats: CohortName::new("10sats_to_100sats", "10-100 sats", "10-100 Sats"),
|
||||
_100sats_to_1k_sats: CohortName::new("100sats_to_1k_sats", "100-1k sats", "100-1K Sats"),
|
||||
_1k_sats_to_10k_sats: CohortName::new("1k_sats_to_10k_sats", "1k-10k sats", "1K-10K Sats"),
|
||||
_10k_sats_to_100k_sats: CohortName::new("10k_sats_to_100k_sats", "10k-100k sats", "10K-100K Sats"),
|
||||
_10k_sats_to_100k_sats: CohortName::new(
|
||||
"10k_sats_to_100k_sats",
|
||||
"10k-100k sats",
|
||||
"10K-100K Sats",
|
||||
),
|
||||
_100k_sats_to_1m_sats: CohortName::new("100k_sats_to_1m_sats", "100k-1M sats", "100K-1M Sats"),
|
||||
_1m_sats_to_10m_sats: CohortName::new("1m_sats_to_10m_sats", "1M-10M sats", "1M-10M Sats"),
|
||||
_10m_sats_to_1btc: CohortName::new("10m_sats_to_1btc", "0.1-1 BTC", "0.1-1 BTC"),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
mod addr;
|
||||
mod amount_filter;
|
||||
mod age_range;
|
||||
mod amount_filter;
|
||||
mod amount_range;
|
||||
mod by_addr_type;
|
||||
mod by_any_addr;
|
||||
@@ -30,8 +30,8 @@ mod utxo;
|
||||
pub use brk_types::{Age, Term};
|
||||
|
||||
pub use addr::*;
|
||||
pub use amount_filter::*;
|
||||
pub use age_range::*;
|
||||
pub use amount_filter::*;
|
||||
pub use amount_range::*;
|
||||
pub use by_addr_type::*;
|
||||
pub use by_any_addr::*;
|
||||
|
||||
@@ -153,6 +153,6 @@ impl<T> Loss<T> {
|
||||
.into_iter()
|
||||
.rev()
|
||||
.enumerate()
|
||||
.map(move |(n, threshold)| (threshold, &ranges[len - 1 - n..]))
|
||||
.map(move |(n, threshold)| (threshold, &ranges[len - 2 - n..]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,19 +43,31 @@ pub const OVER_AMOUNT_NAMES: OverAmount<CohortName> = OverAmount {
|
||||
pub const OVER_AMOUNT_FILTERS: OverAmount<Filter> = OverAmount {
|
||||
_1sat: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1sat)),
|
||||
_10sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10sats)),
|
||||
_100sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._100sats)),
|
||||
_1k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1k_sats)),
|
||||
_10k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10k_sats)),
|
||||
_100sats: Filter::Amount(AmountFilter::GreaterOrEqual(
|
||||
OVER_AMOUNT_THRESHOLDS._100sats,
|
||||
)),
|
||||
_1k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(
|
||||
OVER_AMOUNT_THRESHOLDS._1k_sats,
|
||||
)),
|
||||
_10k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(
|
||||
OVER_AMOUNT_THRESHOLDS._10k_sats,
|
||||
)),
|
||||
_100k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(
|
||||
OVER_AMOUNT_THRESHOLDS._100k_sats,
|
||||
)),
|
||||
_1m_sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1m_sats)),
|
||||
_10m_sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10m_sats)),
|
||||
_1m_sats: Filter::Amount(AmountFilter::GreaterOrEqual(
|
||||
OVER_AMOUNT_THRESHOLDS._1m_sats,
|
||||
)),
|
||||
_10m_sats: Filter::Amount(AmountFilter::GreaterOrEqual(
|
||||
OVER_AMOUNT_THRESHOLDS._10m_sats,
|
||||
)),
|
||||
_1btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1btc)),
|
||||
_10btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10btc)),
|
||||
_100btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._100btc)),
|
||||
_1k_btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1k_btc)),
|
||||
_10k_btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10k_btc)),
|
||||
_10k_btc: Filter::Amount(AmountFilter::GreaterOrEqual(
|
||||
OVER_AMOUNT_THRESHOLDS._10k_btc,
|
||||
)),
|
||||
};
|
||||
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
|
||||
@@ -16,10 +16,26 @@ pub const PROFIT_NAMES: Profit<CohortName> = Profit {
|
||||
_70pct: CohortName::new("utxos_over_70pct_in_profit", ">=70%", "Over 70% in Profit"),
|
||||
_80pct: CohortName::new("utxos_over_80pct_in_profit", ">=80%", "Over 80% in Profit"),
|
||||
_90pct: CohortName::new("utxos_over_90pct_in_profit", ">=90%", "Over 90% in Profit"),
|
||||
_100pct: CohortName::new("utxos_over_100pct_in_profit", ">=100%", "Over 100% in Profit"),
|
||||
_200pct: CohortName::new("utxos_over_200pct_in_profit", ">=200%", "Over 200% in Profit"),
|
||||
_300pct: CohortName::new("utxos_over_300pct_in_profit", ">=300%", "Over 300% in Profit"),
|
||||
_500pct: CohortName::new("utxos_over_500pct_in_profit", ">=500%", "Over 500% in Profit"),
|
||||
_100pct: CohortName::new(
|
||||
"utxos_over_100pct_in_profit",
|
||||
">=100%",
|
||||
"Over 100% in Profit",
|
||||
),
|
||||
_200pct: CohortName::new(
|
||||
"utxos_over_200pct_in_profit",
|
||||
">=200%",
|
||||
"Over 200% in Profit",
|
||||
),
|
||||
_300pct: CohortName::new(
|
||||
"utxos_over_300pct_in_profit",
|
||||
">=300%",
|
||||
"Over 300% in Profit",
|
||||
),
|
||||
_500pct: CohortName::new(
|
||||
"utxos_over_500pct_in_profit",
|
||||
">=500%",
|
||||
"Over 500% in Profit",
|
||||
),
|
||||
};
|
||||
|
||||
/// Number of profit thresholds.
|
||||
@@ -192,6 +208,6 @@ impl<T> Profit<T> {
|
||||
.into_iter()
|
||||
.rev()
|
||||
.enumerate()
|
||||
.map(move |(n, threshold)| (threshold, &ranges[..n + 1]))
|
||||
.map(move |(n, threshold)| (threshold, &ranges[..n + 2]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,31 +83,131 @@ pub fn compute_profitability_boundaries(spot: Cents) -> [Cents; PROFITABILITY_BO
|
||||
|
||||
/// Profitability range names (25 ranges, from most profitable to most in loss)
|
||||
pub const PROFITABILITY_RANGE_NAMES: ProfitabilityRange<CohortName> = ProfitabilityRange {
|
||||
over_1000pct_in_profit: CohortName::new("utxos_over_1000pct_in_profit", "+>1000%", "Over 1000% in Profit"),
|
||||
_500pct_to_1000pct_in_profit: CohortName::new("utxos_500pct_to_1000pct_in_profit", "+500-1000%", "500-1000% in Profit"),
|
||||
_300pct_to_500pct_in_profit: CohortName::new("utxos_300pct_to_500pct_in_profit", "+300-500%", "300-500% in Profit"),
|
||||
_200pct_to_300pct_in_profit: CohortName::new("utxos_200pct_to_300pct_in_profit", "+200-300%", "200-300% in Profit"),
|
||||
_100pct_to_200pct_in_profit: CohortName::new("utxos_100pct_to_200pct_in_profit", "+100-200%", "100-200% in Profit"),
|
||||
_90pct_to_100pct_in_profit: CohortName::new("utxos_90pct_to_100pct_in_profit", "+90-100%", "90-100% in Profit"),
|
||||
_80pct_to_90pct_in_profit: CohortName::new("utxos_80pct_to_90pct_in_profit", "+80-90%", "80-90% in Profit"),
|
||||
_70pct_to_80pct_in_profit: CohortName::new("utxos_70pct_to_80pct_in_profit", "+70-80%", "70-80% in Profit"),
|
||||
_60pct_to_70pct_in_profit: CohortName::new("utxos_60pct_to_70pct_in_profit", "+60-70%", "60-70% in Profit"),
|
||||
_50pct_to_60pct_in_profit: CohortName::new("utxos_50pct_to_60pct_in_profit", "+50-60%", "50-60% in Profit"),
|
||||
_40pct_to_50pct_in_profit: CohortName::new("utxos_40pct_to_50pct_in_profit", "+40-50%", "40-50% in Profit"),
|
||||
_30pct_to_40pct_in_profit: CohortName::new("utxos_30pct_to_40pct_in_profit", "+30-40%", "30-40% in Profit"),
|
||||
_20pct_to_30pct_in_profit: CohortName::new("utxos_20pct_to_30pct_in_profit", "+20-30%", "20-30% in Profit"),
|
||||
_10pct_to_20pct_in_profit: CohortName::new("utxos_10pct_to_20pct_in_profit", "+10-20%", "10-20% in Profit"),
|
||||
_0pct_to_10pct_in_profit: CohortName::new("utxos_0pct_to_10pct_in_profit", "+0-10%", "0-10% in Profit"),
|
||||
_0pct_to_10pct_in_loss: CohortName::new("utxos_0pct_to_10pct_in_loss", "-0-10%", "0-10% in Loss"),
|
||||
_10pct_to_20pct_in_loss: CohortName::new("utxos_10pct_to_20pct_in_loss", "-10-20%", "10-20% in Loss"),
|
||||
_20pct_to_30pct_in_loss: CohortName::new("utxos_20pct_to_30pct_in_loss", "-20-30%", "20-30% in Loss"),
|
||||
_30pct_to_40pct_in_loss: CohortName::new("utxos_30pct_to_40pct_in_loss", "-30-40%", "30-40% in Loss"),
|
||||
_40pct_to_50pct_in_loss: CohortName::new("utxos_40pct_to_50pct_in_loss", "-40-50%", "40-50% in Loss"),
|
||||
_50pct_to_60pct_in_loss: CohortName::new("utxos_50pct_to_60pct_in_loss", "-50-60%", "50-60% in Loss"),
|
||||
_60pct_to_70pct_in_loss: CohortName::new("utxos_60pct_to_70pct_in_loss", "-60-70%", "60-70% in Loss"),
|
||||
_70pct_to_80pct_in_loss: CohortName::new("utxos_70pct_to_80pct_in_loss", "-70-80%", "70-80% in Loss"),
|
||||
_80pct_to_90pct_in_loss: CohortName::new("utxos_80pct_to_90pct_in_loss", "-80-90%", "80-90% in Loss"),
|
||||
_90pct_to_100pct_in_loss: CohortName::new("utxos_90pct_to_100pct_in_loss", "-90-100%", "90-100% in Loss"),
|
||||
over_1000pct_in_profit: CohortName::new(
|
||||
"utxos_over_1000pct_in_profit",
|
||||
"+>1000%",
|
||||
"Over 1000% in Profit",
|
||||
),
|
||||
_500pct_to_1000pct_in_profit: CohortName::new(
|
||||
"utxos_500pct_to_1000pct_in_profit",
|
||||
"+500-1000%",
|
||||
"500-1000% in Profit",
|
||||
),
|
||||
_300pct_to_500pct_in_profit: CohortName::new(
|
||||
"utxos_300pct_to_500pct_in_profit",
|
||||
"+300-500%",
|
||||
"300-500% in Profit",
|
||||
),
|
||||
_200pct_to_300pct_in_profit: CohortName::new(
|
||||
"utxos_200pct_to_300pct_in_profit",
|
||||
"+200-300%",
|
||||
"200-300% in Profit",
|
||||
),
|
||||
_100pct_to_200pct_in_profit: CohortName::new(
|
||||
"utxos_100pct_to_200pct_in_profit",
|
||||
"+100-200%",
|
||||
"100-200% in Profit",
|
||||
),
|
||||
_90pct_to_100pct_in_profit: CohortName::new(
|
||||
"utxos_90pct_to_100pct_in_profit",
|
||||
"+90-100%",
|
||||
"90-100% in Profit",
|
||||
),
|
||||
_80pct_to_90pct_in_profit: CohortName::new(
|
||||
"utxos_80pct_to_90pct_in_profit",
|
||||
"+80-90%",
|
||||
"80-90% in Profit",
|
||||
),
|
||||
_70pct_to_80pct_in_profit: CohortName::new(
|
||||
"utxos_70pct_to_80pct_in_profit",
|
||||
"+70-80%",
|
||||
"70-80% in Profit",
|
||||
),
|
||||
_60pct_to_70pct_in_profit: CohortName::new(
|
||||
"utxos_60pct_to_70pct_in_profit",
|
||||
"+60-70%",
|
||||
"60-70% in Profit",
|
||||
),
|
||||
_50pct_to_60pct_in_profit: CohortName::new(
|
||||
"utxos_50pct_to_60pct_in_profit",
|
||||
"+50-60%",
|
||||
"50-60% in Profit",
|
||||
),
|
||||
_40pct_to_50pct_in_profit: CohortName::new(
|
||||
"utxos_40pct_to_50pct_in_profit",
|
||||
"+40-50%",
|
||||
"40-50% in Profit",
|
||||
),
|
||||
_30pct_to_40pct_in_profit: CohortName::new(
|
||||
"utxos_30pct_to_40pct_in_profit",
|
||||
"+30-40%",
|
||||
"30-40% in Profit",
|
||||
),
|
||||
_20pct_to_30pct_in_profit: CohortName::new(
|
||||
"utxos_20pct_to_30pct_in_profit",
|
||||
"+20-30%",
|
||||
"20-30% in Profit",
|
||||
),
|
||||
_10pct_to_20pct_in_profit: CohortName::new(
|
||||
"utxos_10pct_to_20pct_in_profit",
|
||||
"+10-20%",
|
||||
"10-20% in Profit",
|
||||
),
|
||||
_0pct_to_10pct_in_profit: CohortName::new(
|
||||
"utxos_0pct_to_10pct_in_profit",
|
||||
"+0-10%",
|
||||
"0-10% in Profit",
|
||||
),
|
||||
_0pct_to_10pct_in_loss: CohortName::new(
|
||||
"utxos_0pct_to_10pct_in_loss",
|
||||
"-0-10%",
|
||||
"0-10% in Loss",
|
||||
),
|
||||
_10pct_to_20pct_in_loss: CohortName::new(
|
||||
"utxos_10pct_to_20pct_in_loss",
|
||||
"-10-20%",
|
||||
"10-20% in Loss",
|
||||
),
|
||||
_20pct_to_30pct_in_loss: CohortName::new(
|
||||
"utxos_20pct_to_30pct_in_loss",
|
||||
"-20-30%",
|
||||
"20-30% in Loss",
|
||||
),
|
||||
_30pct_to_40pct_in_loss: CohortName::new(
|
||||
"utxos_30pct_to_40pct_in_loss",
|
||||
"-30-40%",
|
||||
"30-40% in Loss",
|
||||
),
|
||||
_40pct_to_50pct_in_loss: CohortName::new(
|
||||
"utxos_40pct_to_50pct_in_loss",
|
||||
"-40-50%",
|
||||
"40-50% in Loss",
|
||||
),
|
||||
_50pct_to_60pct_in_loss: CohortName::new(
|
||||
"utxos_50pct_to_60pct_in_loss",
|
||||
"-50-60%",
|
||||
"50-60% in Loss",
|
||||
),
|
||||
_60pct_to_70pct_in_loss: CohortName::new(
|
||||
"utxos_60pct_to_70pct_in_loss",
|
||||
"-60-70%",
|
||||
"60-70% in Loss",
|
||||
),
|
||||
_70pct_to_80pct_in_loss: CohortName::new(
|
||||
"utxos_70pct_to_80pct_in_loss",
|
||||
"-70-80%",
|
||||
"70-80% in Loss",
|
||||
),
|
||||
_80pct_to_90pct_in_loss: CohortName::new(
|
||||
"utxos_80pct_to_90pct_in_loss",
|
||||
"-80-90%",
|
||||
"80-90% in Loss",
|
||||
),
|
||||
_90pct_to_100pct_in_loss: CohortName::new(
|
||||
"utxos_90pct_to_100pct_in_loss",
|
||||
"-90-100%",
|
||||
"90-100% in Loss",
|
||||
),
|
||||
};
|
||||
|
||||
impl ProfitabilityRange<CohortName> {
|
||||
|
||||
@@ -2,8 +2,8 @@ use brk_traversable::Traversable;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::{
|
||||
AgeRange, AmountRange, ByEpoch, OverAmount, UnderAmount, UnderAge, OverAge,
|
||||
Class, SpendableType, ByTerm, Filter,
|
||||
AgeRange, AmountRange, ByEpoch, ByTerm, Class, Filter, OverAge, OverAmount, SpendableType,
|
||||
UnderAge, UnderAmount,
|
||||
};
|
||||
|
||||
#[derive(Default, Clone, Traversable)]
|
||||
|
||||
@@ -14,11 +14,8 @@ brk_error = { workspace = true, features = ["vecdb"] }
|
||||
brk_cohort = { workspace = true }
|
||||
brk_indexer = { workspace = true }
|
||||
brk_oracle = { workspace = true }
|
||||
brk_iterator = { workspace = true }
|
||||
brk_logger = { workspace = true }
|
||||
brk_reader = { workspace = true }
|
||||
brk_rpc = { workspace = true, features = ["corepc"] }
|
||||
brk_store = { workspace = true }
|
||||
brk_traversable = { workspace = true }
|
||||
brk_types = { workspace = true }
|
||||
derive_more = { workspace = true }
|
||||
@@ -33,6 +30,7 @@ smallvec = { workspace = true }
|
||||
vecdb = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
brk_reader = { workspace = true }
|
||||
brk_alloc = { workspace = true }
|
||||
brk_bencher = { workspace = true }
|
||||
color-eyre = { workspace = true }
|
||||
|
||||
@@ -8,7 +8,6 @@ use std::{
|
||||
use brk_alloc::Mimalloc;
|
||||
use brk_computer::Computer;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_iterator::Blocks;
|
||||
use brk_reader::Reader;
|
||||
use brk_rpc::{Auth, Client};
|
||||
use vecdb::Exit;
|
||||
@@ -31,8 +30,6 @@ pub fn main() -> color_eyre::Result<()> {
|
||||
|
||||
let reader = Reader::new(bitcoin_dir.join("blocks"), &client);
|
||||
|
||||
let blocks = Blocks::new(&client, &reader);
|
||||
|
||||
let mut indexer = Indexer::forced_import(&outputs_dir)?;
|
||||
|
||||
let exit = Exit::new();
|
||||
@@ -42,7 +39,7 @@ pub fn main() -> color_eyre::Result<()> {
|
||||
let chain_height = client.get_last_height()?;
|
||||
let indexed_height = indexer.vecs.starting_height();
|
||||
if u32::from(chain_height).saturating_sub(u32::from(indexed_height)) > 1000 {
|
||||
indexer.checked_index(&blocks, &client, &exit)?;
|
||||
indexer.checked_index(&reader, &client, &exit)?;
|
||||
drop(indexer);
|
||||
Mimalloc::collect();
|
||||
indexer = Indexer::forced_import(&outputs_dir)?;
|
||||
@@ -52,11 +49,11 @@ pub fn main() -> color_eyre::Result<()> {
|
||||
|
||||
loop {
|
||||
let i = Instant::now();
|
||||
let starting_indexes = indexer.checked_index(&blocks, &client, &exit)?;
|
||||
let starting_indexes = indexer.checked_index(&reader, &client, &exit)?;
|
||||
|
||||
Mimalloc::collect();
|
||||
|
||||
computer.compute(&indexer, starting_indexes, &reader, &exit)?;
|
||||
computer.compute(&indexer, starting_indexes, &exit)?;
|
||||
dbg!(i.elapsed());
|
||||
sleep(Duration::from_secs(10));
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ use brk_bencher::Bencher;
|
||||
use brk_computer::Computer;
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_iterator::Blocks;
|
||||
use brk_reader::Reader;
|
||||
use brk_rpc::{Auth, Client};
|
||||
use tracing::{debug, info};
|
||||
@@ -28,8 +27,6 @@ pub fn main() -> Result<()> {
|
||||
|
||||
let reader = Reader::new(bitcoin_dir.join("blocks"), &client);
|
||||
|
||||
let blocks = Blocks::new(&client, &reader);
|
||||
|
||||
let mut indexer = Indexer::forced_import(&outputs_dir)?;
|
||||
|
||||
let mut computer = Computer::forced_import(&outputs_benches_dir, &indexer)?;
|
||||
@@ -47,13 +44,13 @@ pub fn main() -> Result<()> {
|
||||
});
|
||||
|
||||
let i = Instant::now();
|
||||
let starting_indexes = indexer.index(&blocks, &client, &exit)?;
|
||||
let starting_indexes = indexer.index(&reader, &client, &exit)?;
|
||||
info!("Done in {:?}", i.elapsed());
|
||||
|
||||
Mimalloc::collect();
|
||||
|
||||
let i = Instant::now();
|
||||
computer.compute(&indexer, starting_indexes, &reader, &exit)?;
|
||||
computer.compute(&indexer, starting_indexes, &exit)?;
|
||||
info!("Done in {:?}", i.elapsed());
|
||||
|
||||
// We want to benchmark the drop too
|
||||
|
||||
@@ -9,7 +9,6 @@ use brk_alloc::Mimalloc;
|
||||
use brk_bencher::Bencher;
|
||||
use brk_computer::Computer;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_iterator::Blocks;
|
||||
use brk_reader::Reader;
|
||||
use brk_rpc::{Auth, Client};
|
||||
use tracing::{debug, info};
|
||||
@@ -45,15 +44,13 @@ pub fn main() -> color_eyre::Result<()> {
|
||||
|
||||
let reader = Reader::new(bitcoin_dir.join("blocks"), &client);
|
||||
|
||||
let blocks = Blocks::new(&client, &reader);
|
||||
|
||||
let mut indexer = Indexer::forced_import(&outputs_dir)?;
|
||||
|
||||
// Pre-run indexer if too far behind, then drop and reimport to reduce memory
|
||||
let chain_height = client.get_last_height()?;
|
||||
let indexed_height = indexer.vecs.starting_height();
|
||||
if chain_height.saturating_sub(*indexed_height) > 1000 {
|
||||
indexer.index(&blocks, &client, &exit)?;
|
||||
indexer.index(&reader, &client, &exit)?;
|
||||
drop(indexer);
|
||||
Mimalloc::collect();
|
||||
indexer = Indexer::forced_import(&outputs_dir)?;
|
||||
@@ -63,13 +60,13 @@ pub fn main() -> color_eyre::Result<()> {
|
||||
|
||||
loop {
|
||||
let i = Instant::now();
|
||||
let starting_indexes = indexer.index(&blocks, &client, &exit)?;
|
||||
let starting_indexes = indexer.index(&reader, &client, &exit)?;
|
||||
info!("Done in {:?}", i.elapsed());
|
||||
|
||||
Mimalloc::collect();
|
||||
|
||||
let i = Instant::now();
|
||||
computer.compute(&indexer, starting_indexes, &reader, &exit)?;
|
||||
computer.compute(&indexer, starting_indexes, &exit)?;
|
||||
info!("Done in {:?}", i.elapsed());
|
||||
|
||||
sleep(Duration::from_secs(60));
|
||||
|
||||
@@ -17,12 +17,10 @@ impl Vecs {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Sequential: time → lookback (dependency chain)
|
||||
self.time
|
||||
.timestamp
|
||||
.compute(indexer, indexes, starting_indexes, exit)?;
|
||||
self.lookback
|
||||
.compute(&self.time, starting_indexes, exit)?;
|
||||
self.db.sync_bg_tasks()?;
|
||||
|
||||
// lookback depends on indexes.timestamp.monotonic
|
||||
self.lookback.compute(indexes, starting_indexes, exit)?;
|
||||
|
||||
// Parallel: remaining sub-modules are independent of each other.
|
||||
// size depends on lookback (already computed above).
|
||||
@@ -40,8 +38,7 @@ impl Vecs {
|
||||
let r1 = s.spawn(|| count.compute(indexer, starting_indexes, exit));
|
||||
let r2 = s.spawn(|| interval.compute(indexer, starting_indexes, exit));
|
||||
let r3 = s.spawn(|| weight.compute(indexer, starting_indexes, exit));
|
||||
let r4 =
|
||||
s.spawn(|| difficulty.compute(indexer, indexes, starting_indexes, exit));
|
||||
let r4 = s.spawn(|| difficulty.compute(indexer, indexes, starting_indexes, exit));
|
||||
let r5 = s.spawn(|| halving.compute(indexes, starting_indexes, exit));
|
||||
size.compute(indexer, &*lookback, starting_indexes, exit)?;
|
||||
r1.join().unwrap()?;
|
||||
@@ -52,8 +49,11 @@ impl Vecs {
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let _lock = exit.lock();
|
||||
self.db.compact()?;
|
||||
let exit = exit.clone();
|
||||
self.db.run_bg(move |db| {
|
||||
let _lock = exit.lock();
|
||||
db.compact_deferred_default()
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ use super::Vecs;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
BlockCountTarget24h, BlockCountTarget1w, BlockCountTarget1m, BlockCountTarget1y,
|
||||
CachedWindowStarts, PerBlockCumulativeRolling, ConstantVecs, Windows,
|
||||
BlockCountTarget1m, BlockCountTarget1w, BlockCountTarget1y, BlockCountTarget24h,
|
||||
CachedWindowStarts, ConstantVecs, PerBlockCumulativeRolling, Windows,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -20,10 +20,26 @@ impl Vecs {
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
target: Windows {
|
||||
_24h: ConstantVecs::new::<BlockCountTarget24h>("block_count_target_24h", version, indexes),
|
||||
_1w: ConstantVecs::new::<BlockCountTarget1w>("block_count_target_1w", version, indexes),
|
||||
_1m: ConstantVecs::new::<BlockCountTarget1m>("block_count_target_1m", version, indexes),
|
||||
_1y: ConstantVecs::new::<BlockCountTarget1y>("block_count_target_1y", version, indexes),
|
||||
_24h: ConstantVecs::new::<BlockCountTarget24h>(
|
||||
"block_count_target_24h",
|
||||
version,
|
||||
indexes,
|
||||
),
|
||||
_1w: ConstantVecs::new::<BlockCountTarget1w>(
|
||||
"block_count_target_1w",
|
||||
version,
|
||||
indexes,
|
||||
),
|
||||
_1m: ConstantVecs::new::<BlockCountTarget1m>(
|
||||
"block_count_target_1m",
|
||||
version,
|
||||
indexes,
|
||||
),
|
||||
_1y: ConstantVecs::new::<BlockCountTarget1y>(
|
||||
"block_count_target_1y",
|
||||
version,
|
||||
indexes,
|
||||
),
|
||||
},
|
||||
total: PerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
|
||||
@@ -2,7 +2,7 @@ use brk_traversable::Traversable;
|
||||
use brk_types::{StoredU32, StoredU64};
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::{PerBlockCumulativeRolling, ConstantVecs, Windows};
|
||||
use crate::internal::{ConstantVecs, PerBlockCumulativeRolling, Windows};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
|
||||
@@ -27,12 +27,8 @@ impl Vecs {
|
||||
indexes,
|
||||
);
|
||||
|
||||
let blocks_to_retarget = PerBlock::forced_import(
|
||||
db,
|
||||
"blocks_to_retarget",
|
||||
version + v2,
|
||||
indexes,
|
||||
)?;
|
||||
let blocks_to_retarget =
|
||||
PerBlock::forced_import(db, "blocks_to_retarget", version + v2, indexes)?;
|
||||
|
||||
let days_to_retarget = LazyPerBlock::from_computed::<BlocksToDaysF32>(
|
||||
"days_to_retarget",
|
||||
|
||||
@@ -2,7 +2,7 @@ use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPointsSigned32, Epoch, StoredF32, StoredF64, StoredU32};
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::{LazyPerBlock, PerBlock, Resolutions, PercentPerBlock};
|
||||
use crate::internal::{LazyPerBlock, PerBlock, PercentPerBlock, Resolutions};
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub value: Resolutions<StoredF64>,
|
||||
|
||||
@@ -16,9 +16,8 @@ impl Vecs {
|
||||
) -> Result<Self> {
|
||||
let v2 = Version::TWO;
|
||||
|
||||
let blocks_to_halving = PerBlock::forced_import(
|
||||
db, "blocks_to_halving", version + v2, indexes,
|
||||
)?;
|
||||
let blocks_to_halving =
|
||||
PerBlock::forced_import(db, "blocks_to_halving", version + v2, indexes)?;
|
||||
|
||||
let days_to_halving = LazyPerBlock::from_computed::<BlocksToDaysF32>(
|
||||
"days_to_halving",
|
||||
|
||||
@@ -10,8 +10,7 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
CountVecs, DifficultyVecs, HalvingVecs, IntervalVecs, LookbackVecs, SizeVecs, TimeVecs, Vecs,
|
||||
WeightVecs,
|
||||
CountVecs, DifficultyVecs, HalvingVecs, IntervalVecs, LookbackVecs, SizeVecs, Vecs, WeightVecs,
|
||||
};
|
||||
|
||||
impl Vecs {
|
||||
@@ -30,7 +29,6 @@ impl Vecs {
|
||||
let interval = IntervalVecs::forced_import(&db, version, indexes, cached_starts)?;
|
||||
let size = SizeVecs::forced_import(&db, version, indexes, cached_starts)?;
|
||||
let weight = WeightVecs::forced_import(&db, version, indexes, cached_starts, &size)?;
|
||||
let time = TimeVecs::forced_import(&db, version, indexes)?;
|
||||
let difficulty = DifficultyVecs::forced_import(&db, version, indexer, indexes)?;
|
||||
let halving = HalvingVecs::forced_import(&db, version, indexes)?;
|
||||
|
||||
@@ -41,7 +39,6 @@ impl Vecs {
|
||||
interval,
|
||||
size,
|
||||
weight,
|
||||
time,
|
||||
difficulty,
|
||||
halving,
|
||||
};
|
||||
|
||||
@@ -13,27 +13,26 @@ impl Vecs {
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let mut prev_timestamp = None;
|
||||
self.0
|
||||
.compute(starting_indexes.height, exit, |vec| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.blocks.timestamp,
|
||||
|(h, timestamp, ..)| {
|
||||
let interval = if let Some(prev_h) = h.decremented() {
|
||||
let prev = prev_timestamp.unwrap_or_else(|| {
|
||||
indexer.vecs.blocks.timestamp.collect_one(prev_h).unwrap()
|
||||
});
|
||||
timestamp.checked_sub(prev).unwrap_or(Timestamp::ZERO)
|
||||
} else {
|
||||
Timestamp::ZERO
|
||||
};
|
||||
prev_timestamp = Some(timestamp);
|
||||
(h, interval)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
self.0.compute(starting_indexes.height, exit, |vec| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.blocks.timestamp,
|
||||
|(h, timestamp, ..)| {
|
||||
let interval = if let Some(prev_h) = h.decremented() {
|
||||
let prev = prev_timestamp.unwrap_or_else(|| {
|
||||
indexer.vecs.blocks.timestamp.collect_one(prev_h).unwrap()
|
||||
});
|
||||
timestamp.checked_sub(prev).unwrap_or(Timestamp::ZERO)
|
||||
} else {
|
||||
Timestamp::ZERO
|
||||
};
|
||||
prev_timestamp = Some(timestamp);
|
||||
(h, interval)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ use brk_types::Version;
|
||||
use vecdb::Database;
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{indexes, internal::{CachedWindowStarts, PerBlockRollingAverage}};
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{CachedWindowStarts, PerBlockRollingAverage},
|
||||
};
|
||||
|
||||
impl Vecs {
|
||||
pub(crate) fn forced_import(
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Indexes, Timestamp, Version};
|
||||
use vecdb::{AnyVec, CachedVec, Cursor, Database, EagerVec, Exit, ImportableVec, PcoVec, ReadableVec, Rw, StorageMode, VecIndex};
|
||||
use vecdb::{
|
||||
AnyVec, CachedVec, Cursor, Database, EagerVec, Exit, ImportableVec, PcoVec, ReadableVec, Rw,
|
||||
StorageMode, VecIndex,
|
||||
};
|
||||
|
||||
use crate::internal::{CachedWindowStarts, Windows, WindowStarts};
|
||||
|
||||
use super::time;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{CachedWindowStarts, WindowStarts, Windows},
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
@@ -111,10 +115,49 @@ impl Vecs {
|
||||
|
||||
Ok(Self {
|
||||
cached_window_starts,
|
||||
_1h, _24h, _3d, _1w, _8d, _9d, _12d, _13d, _2w, _21d, _26d,
|
||||
_1m, _34d, _55d, _2m, _9w, _12w, _89d, _3m, _14w, _111d, _144d,
|
||||
_6m, _26w, _200d, _9m, _350d, _12m, _1y, _14m, _2y, _26m, _3y,
|
||||
_200w, _4y, _5y, _6y, _8y, _9y, _10y, _12y, _14y, _26y,
|
||||
_1h,
|
||||
_24h,
|
||||
_3d,
|
||||
_1w,
|
||||
_8d,
|
||||
_9d,
|
||||
_12d,
|
||||
_13d,
|
||||
_2w,
|
||||
_21d,
|
||||
_26d,
|
||||
_1m,
|
||||
_34d,
|
||||
_55d,
|
||||
_2m,
|
||||
_9w,
|
||||
_12w,
|
||||
_89d,
|
||||
_3m,
|
||||
_14w,
|
||||
_111d,
|
||||
_144d,
|
||||
_6m,
|
||||
_26w,
|
||||
_200d,
|
||||
_9m,
|
||||
_350d,
|
||||
_12m,
|
||||
_1y,
|
||||
_14m,
|
||||
_2y,
|
||||
_26m,
|
||||
_3y,
|
||||
_200w,
|
||||
_4y,
|
||||
_5y,
|
||||
_6y,
|
||||
_8y,
|
||||
_9y,
|
||||
_10y,
|
||||
_12y,
|
||||
_14y,
|
||||
_26y,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -127,7 +170,6 @@ impl Vecs {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn start_vec(&self, days: usize) -> &EagerVec<PcoVec<Height, Height>> {
|
||||
match days {
|
||||
1 => &self._24h,
|
||||
@@ -178,80 +220,60 @@ impl Vecs {
|
||||
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
time: &time::Vecs,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_rolling_start_hours(time, starting_indexes, exit, 1, |s| {
|
||||
&mut s._1h
|
||||
})?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 1, |s| &mut s._24h)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 3, |s| &mut s._3d)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 7, |s| &mut s._1w)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 8, |s| &mut s._8d)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 9, |s| &mut s._9d)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 12, |s| &mut s._12d)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 13, |s| &mut s._13d)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 14, |s| &mut s._2w)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 21, |s| &mut s._21d)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 26, |s| &mut s._26d)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 30, |s| &mut s._1m)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 34, |s| &mut s._34d)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 55, |s| &mut s._55d)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 60, |s| &mut s._2m)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 63, |s| &mut s._9w)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 84, |s| &mut s._12w)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 89, |s| &mut s._89d)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 90, |s| &mut s._3m)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 98, |s| &mut s._14w)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 111, |s| {
|
||||
&mut s._111d
|
||||
})?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 144, |s| {
|
||||
&mut s._144d
|
||||
})?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 180, |s| &mut s._6m)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 182, |s| &mut s._26w)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 200, |s| {
|
||||
&mut s._200d
|
||||
})?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 270, |s| &mut s._9m)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 350, |s| {
|
||||
&mut s._350d
|
||||
})?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 360, |s| &mut s._12m)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 365, |s| &mut s._1y)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 420, |s| &mut s._14m)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 730, |s| &mut s._2y)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 780, |s| &mut s._26m)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 1095, |s| &mut s._3y)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 1400, |s| {
|
||||
&mut s._200w
|
||||
})?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 1460, |s| &mut s._4y)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 1825, |s| &mut s._5y)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 2190, |s| &mut s._6y)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 2920, |s| &mut s._8y)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 3285, |s| &mut s._9y)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 3650, |s| {
|
||||
&mut s._10y
|
||||
})?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 4380, |s| {
|
||||
&mut s._12y
|
||||
})?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 5110, |s| {
|
||||
&mut s._14y
|
||||
})?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 9490, |s| {
|
||||
&mut s._26y
|
||||
})?;
|
||||
self.compute_rolling_start_hours(indexes, starting_indexes, exit, 1, |s| &mut s._1h)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 1, |s| &mut s._24h)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 3, |s| &mut s._3d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 7, |s| &mut s._1w)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 8, |s| &mut s._8d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 9, |s| &mut s._9d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 12, |s| &mut s._12d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 13, |s| &mut s._13d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 14, |s| &mut s._2w)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 21, |s| &mut s._21d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 26, |s| &mut s._26d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 30, |s| &mut s._1m)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 34, |s| &mut s._34d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 55, |s| &mut s._55d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 60, |s| &mut s._2m)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 63, |s| &mut s._9w)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 84, |s| &mut s._12w)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 89, |s| &mut s._89d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 90, |s| &mut s._3m)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 98, |s| &mut s._14w)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 111, |s| &mut s._111d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 144, |s| &mut s._144d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 180, |s| &mut s._6m)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 182, |s| &mut s._26w)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 200, |s| &mut s._200d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 270, |s| &mut s._9m)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 350, |s| &mut s._350d)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 360, |s| &mut s._12m)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 365, |s| &mut s._1y)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 420, |s| &mut s._14m)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 730, |s| &mut s._2y)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 780, |s| &mut s._26m)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 1095, |s| &mut s._3y)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 1400, |s| &mut s._200w)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 1460, |s| &mut s._4y)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 1825, |s| &mut s._5y)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 2190, |s| &mut s._6y)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 2920, |s| &mut s._8y)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 3285, |s| &mut s._9y)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 3650, |s| &mut s._10y)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 4380, |s| &mut s._12y)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 5110, |s| &mut s._14y)?;
|
||||
self.compute_rolling_start(indexes, starting_indexes, exit, 9490, |s| &mut s._26y)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compute_rolling_start<F>(
|
||||
&mut self,
|
||||
time: &time::Vecs,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
days: usize,
|
||||
@@ -260,14 +282,18 @@ impl Vecs {
|
||||
where
|
||||
F: FnOnce(&mut Self) -> &mut EagerVec<PcoVec<Height, Height>>,
|
||||
{
|
||||
self.compute_rolling_start_inner(time, starting_indexes, exit, get_field, |t, prev_ts| {
|
||||
t.difference_in_days_between(prev_ts) >= days
|
||||
})
|
||||
self.compute_rolling_start_inner(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
get_field,
|
||||
|t, prev_ts| t.difference_in_days_between(prev_ts) >= days,
|
||||
)
|
||||
}
|
||||
|
||||
fn compute_rolling_start_hours<F>(
|
||||
&mut self,
|
||||
time: &time::Vecs,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
hours: usize,
|
||||
@@ -276,14 +302,18 @@ impl Vecs {
|
||||
where
|
||||
F: FnOnce(&mut Self) -> &mut EagerVec<PcoVec<Height, Height>>,
|
||||
{
|
||||
self.compute_rolling_start_inner(time, starting_indexes, exit, get_field, |t, prev_ts| {
|
||||
t.difference_in_hours_between(prev_ts) >= hours
|
||||
})
|
||||
self.compute_rolling_start_inner(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
get_field,
|
||||
|t, prev_ts| t.difference_in_hours_between(prev_ts) >= hours,
|
||||
)
|
||||
}
|
||||
|
||||
fn compute_rolling_start_inner<F, D>(
|
||||
&mut self,
|
||||
time: &time::Vecs,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
get_field: F,
|
||||
@@ -300,12 +330,12 @@ impl Vecs {
|
||||
} else {
|
||||
Height::ZERO
|
||||
};
|
||||
let mut cursor = Cursor::new(&time.timestamp_monotonic);
|
||||
let mut cursor = Cursor::new(&indexes.timestamp.monotonic);
|
||||
cursor.advance(prev.to_usize());
|
||||
let mut prev_ts = cursor.next().unwrap();
|
||||
Ok(field.compute_transform(
|
||||
starting_indexes.height,
|
||||
&time.timestamp_monotonic,
|
||||
&indexes.timestamp.monotonic,
|
||||
|(h, t, ..)| {
|
||||
while expired(t, prev_ts) {
|
||||
prev.increment();
|
||||
|
||||
@@ -4,7 +4,6 @@ pub mod halving;
|
||||
pub mod interval;
|
||||
pub mod lookback;
|
||||
pub mod size;
|
||||
pub mod time;
|
||||
pub mod weight;
|
||||
|
||||
mod compute;
|
||||
@@ -19,7 +18,6 @@ pub use halving::Vecs as HalvingVecs;
|
||||
pub use interval::Vecs as IntervalVecs;
|
||||
pub use lookback::Vecs as LookbackVecs;
|
||||
pub use size::Vecs as SizeVecs;
|
||||
pub use time::Vecs as TimeVecs;
|
||||
pub use weight::Vecs as WeightVecs;
|
||||
|
||||
pub const DB_NAME: &str = "blocks";
|
||||
@@ -37,7 +35,7 @@ pub(crate) const ONE_TERA_HASH: f64 = 1_000_000_000_000.0;
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
#[traversable(skip)]
|
||||
pub(crate) db: Database,
|
||||
pub db: Database,
|
||||
|
||||
pub count: CountVecs<M>,
|
||||
pub lookback: LookbackVecs<M>,
|
||||
@@ -46,7 +44,6 @@ pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub size: SizeVecs<M>,
|
||||
#[traversable(flatten)]
|
||||
pub weight: WeightVecs<M>,
|
||||
pub time: TimeVecs<M>,
|
||||
pub difficulty: DifficultyVecs<M>,
|
||||
pub halving: HalvingVecs<M>,
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use vecdb::{Exit, ReadableVec};
|
||||
|
||||
use super::Vecs;
|
||||
|
||||
impl Vecs {
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
starting_height: brk_types::Height,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let mut prev_timestamp_monotonic = None;
|
||||
self.timestamp_monotonic.compute_transform(
|
||||
starting_height,
|
||||
&indexer.vecs.blocks.timestamp,
|
||||
|(h, timestamp, this)| {
|
||||
if prev_timestamp_monotonic.is_none()
|
||||
&& let Some(prev_h) = h.decremented()
|
||||
{
|
||||
prev_timestamp_monotonic.replace(this.collect_one(prev_h).unwrap());
|
||||
}
|
||||
let timestamp_monotonic =
|
||||
prev_timestamp_monotonic.map_or(timestamp, |prev_d| prev_d.max(timestamp));
|
||||
prev_timestamp_monotonic.replace(timestamp_monotonic);
|
||||
(h, timestamp_monotonic)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_types::{Date, Height, Version};
|
||||
use vecdb::{Database, EagerVec, ImportableVec, LazyVecFrom1, ReadableCloneableVec};
|
||||
|
||||
use super::{TimestampIndexes, Vecs};
|
||||
use crate::indexes;
|
||||
|
||||
impl Vecs {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let timestamp_monotonic = EagerVec::forced_import(db, "timestamp_monotonic", version)?;
|
||||
|
||||
Ok(Self {
|
||||
date: LazyVecFrom1::init(
|
||||
"date",
|
||||
version,
|
||||
timestamp_monotonic.read_only_boxed_clone(),
|
||||
|_height: Height, timestamp| Date::from(timestamp),
|
||||
),
|
||||
timestamp_monotonic,
|
||||
timestamp: TimestampIndexes::forced_import(db, version, indexes)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TimestampIndexes {
|
||||
fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
|
||||
macro_rules! period {
|
||||
($field:ident) => {
|
||||
LazyVecFrom1::init(
|
||||
"timestamp",
|
||||
version,
|
||||
indexes.$field.first_height.read_only_boxed_clone(),
|
||||
|idx, _: Height| idx.to_timestamp(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! epoch {
|
||||
($field:ident) => {
|
||||
ImportableVec::forced_import(db, "timestamp", version)?
|
||||
};
|
||||
}
|
||||
|
||||
Ok(Self(crate::internal::PerResolution {
|
||||
minute10: period!(minute10),
|
||||
minute30: period!(minute30),
|
||||
hour1: period!(hour1),
|
||||
hour4: period!(hour4),
|
||||
hour12: period!(hour12),
|
||||
day1: period!(day1),
|
||||
day3: period!(day3),
|
||||
week1: period!(week1),
|
||||
month1: period!(month1),
|
||||
month3: period!(month3),
|
||||
month6: period!(month6),
|
||||
year1: period!(year1),
|
||||
year10: period!(year10),
|
||||
halving: epoch!(halving),
|
||||
epoch: epoch!(difficulty),
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
mod compute;
|
||||
mod import;
|
||||
mod vecs;
|
||||
|
||||
pub use vecs::{TimestampIndexes, Vecs};
|
||||
@@ -1,80 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
Date, Day1, Day3, Epoch, Halving, Height, Hour1, Hour4, Hour12, Indexes,
|
||||
Minute10, Minute30, Month1, Month3, Month6, Timestamp, Week1, Year1, Year10,
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{EagerVec, Exit, LazyVecFrom1, PcoVec, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{indexes, internal::PerResolution};
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub date: LazyVecFrom1<Height, Date, Height, Timestamp>,
|
||||
pub timestamp_monotonic: M::Stored<EagerVec<PcoVec<Height, Timestamp>>>,
|
||||
pub timestamp: TimestampIndexes<M>,
|
||||
}
|
||||
|
||||
/// Per-period timestamp indexes.
|
||||
///
|
||||
/// Time-based periods (minute10–year10) are lazy: `idx.to_timestamp()` is a pure
|
||||
/// function of the index, so no storage or decompression is needed.
|
||||
/// Epoch-based periods (halving, difficulty) are eager: their timestamps
|
||||
/// come from block data via `compute_indirect_sequential`.
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
#[traversable(transparent)]
|
||||
pub struct TimestampIndexes<M: StorageMode = Rw>(
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub PerResolution<
|
||||
LazyVecFrom1<Minute10, Timestamp, Minute10, Height>,
|
||||
LazyVecFrom1<Minute30, Timestamp, Minute30, Height>,
|
||||
LazyVecFrom1<Hour1, Timestamp, Hour1, Height>,
|
||||
LazyVecFrom1<Hour4, Timestamp, Hour4, Height>,
|
||||
LazyVecFrom1<Hour12, Timestamp, Hour12, Height>,
|
||||
LazyVecFrom1<Day1, Timestamp, Day1, Height>,
|
||||
LazyVecFrom1<Day3, Timestamp, Day3, Height>,
|
||||
LazyVecFrom1<Week1, Timestamp, Week1, Height>,
|
||||
LazyVecFrom1<Month1, Timestamp, Month1, Height>,
|
||||
LazyVecFrom1<Month3, Timestamp, Month3, Height>,
|
||||
LazyVecFrom1<Month6, Timestamp, Month6, Height>,
|
||||
LazyVecFrom1<Year1, Timestamp, Year1, Height>,
|
||||
LazyVecFrom1<Year10, Timestamp, Year10, Height>,
|
||||
M::Stored<EagerVec<PcoVec<Halving, Timestamp>>>,
|
||||
M::Stored<EagerVec<PcoVec<Epoch, Timestamp>>>,
|
||||
>,
|
||||
);
|
||||
|
||||
impl TimestampIndexes {
|
||||
/// Compute epoch timestamps via indirect lookup from block timestamps.
|
||||
/// Time-based periods are lazy (idx.to_timestamp()) and need no compute.
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
indexer: &brk_indexer::Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let prev_height = starting_indexes.height.decremented().unwrap_or_default();
|
||||
self.halving.compute_indirect_sequential(
|
||||
indexes
|
||||
.height
|
||||
.halving
|
||||
.collect_one(prev_height)
|
||||
.unwrap_or_default(),
|
||||
&indexes.halving.first_height,
|
||||
&indexer.vecs.blocks.timestamp,
|
||||
exit,
|
||||
)?;
|
||||
self.epoch.compute_indirect_sequential(
|
||||
indexes
|
||||
.height
|
||||
.epoch
|
||||
.collect_one(prev_height)
|
||||
.unwrap_or_default(),
|
||||
&indexes.epoch.first_height,
|
||||
&indexer.vecs.blocks.timestamp,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -28,10 +28,18 @@ impl Vecs {
|
||||
|
||||
Ok(Self {
|
||||
coinblocks_created: PerBlockCumulativeRolling::forced_import(
|
||||
db, "coinblocks_created", version, indexes, cached_starts,
|
||||
db,
|
||||
"coinblocks_created",
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
)?,
|
||||
coinblocks_stored: PerBlockCumulativeRolling::forced_import(
|
||||
db, "coinblocks_stored", version, indexes, cached_starts,
|
||||
db,
|
||||
"coinblocks_stored",
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
)?,
|
||||
liveliness,
|
||||
vaultedness,
|
||||
|
||||
@@ -17,6 +17,8 @@ impl Vecs {
|
||||
distribution: &distribution::Vecs,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.db.sync_bg_tasks()?;
|
||||
|
||||
// Activity computes first (liveliness, vaultedness, etc.)
|
||||
self.activity
|
||||
.compute(starting_indexes, distribution, exit)?;
|
||||
@@ -80,8 +82,11 @@ impl Vecs {
|
||||
r3?;
|
||||
r4?;
|
||||
|
||||
let _lock = exit.lock();
|
||||
self.db.compact()?;
|
||||
let exit = exit.clone();
|
||||
self.db.run_bg(move |db| {
|
||||
let _lock = exit.lock();
|
||||
db.compact_deferred_default()
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,11 +22,8 @@ impl Vecs {
|
||||
let circulating_supply = &all_metrics.supply.total.btc.height;
|
||||
let realized_price = &all_metrics.realized.price.cents.height;
|
||||
|
||||
self.vaulted.compute_all(
|
||||
prices,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v| {
|
||||
self.vaulted
|
||||
.compute_all(prices, starting_indexes, exit, |v| {
|
||||
Ok(v.compute_transform2(
|
||||
starting_indexes.height,
|
||||
realized_price,
|
||||
@@ -36,14 +33,10 @@ impl Vecs {
|
||||
},
|
||||
exit,
|
||||
)?)
|
||||
},
|
||||
)?;
|
||||
})?;
|
||||
|
||||
self.active.compute_all(
|
||||
prices,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v| {
|
||||
self.active
|
||||
.compute_all(prices, starting_indexes, exit, |v| {
|
||||
Ok(v.compute_transform2(
|
||||
starting_indexes.height,
|
||||
realized_price,
|
||||
@@ -53,14 +46,10 @@ impl Vecs {
|
||||
},
|
||||
exit,
|
||||
)?)
|
||||
},
|
||||
)?;
|
||||
})?;
|
||||
|
||||
self.true_market_mean.compute_all(
|
||||
prices,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v| {
|
||||
self.true_market_mean
|
||||
.compute_all(prices, starting_indexes, exit, |v| {
|
||||
Ok(v.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&cap.investor.cents.height,
|
||||
@@ -70,14 +59,10 @@ impl Vecs {
|
||||
},
|
||||
exit,
|
||||
)?)
|
||||
},
|
||||
)?;
|
||||
})?;
|
||||
|
||||
self.cointime.compute_all(
|
||||
prices,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v| {
|
||||
self.cointime
|
||||
.compute_all(prices, starting_indexes, exit, |v| {
|
||||
Ok(v.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&cap.cointime.cents.height,
|
||||
@@ -87,8 +72,7 @@ impl Vecs {
|
||||
},
|
||||
exit,
|
||||
)?)
|
||||
},
|
||||
)?;
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -3,10 +3,7 @@ use brk_types::Version;
|
||||
use vecdb::Database;
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::PriceWithRatioExtendedPerBlock,
|
||||
};
|
||||
use crate::{indexes, internal::PriceWithRatioExtendedPerBlock};
|
||||
|
||||
impl Vecs {
|
||||
pub(crate) fn forced_import(
|
||||
|
||||
@@ -23,7 +23,7 @@ impl Vecs {
|
||||
|
||||
self.hodl_bank.compute_cumulative_transformed_binary(
|
||||
starting_indexes.height,
|
||||
&prices.spot.usd.height,
|
||||
&prices.cached_spot_usd,
|
||||
&self.vocdd_median_1y,
|
||||
|price, median| StoredF64::from(f64::from(price) - f64::from(median)),
|
||||
exit,
|
||||
@@ -31,7 +31,7 @@ impl Vecs {
|
||||
|
||||
self.value.height.compute_divide(
|
||||
starting_indexes.height,
|
||||
&prices.spot.usd.height,
|
||||
&prices.cached_spot_usd,
|
||||
&self.hodl_bank,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -38,7 +38,8 @@ impl Vecs {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.vaulted.compute(prices, starting_indexes.height, exit)?;
|
||||
self.vaulted
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
self.active.compute(prices, starting_indexes.height, exit)?;
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -12,12 +12,7 @@ impl Vecs {
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
vaulted: AmountPerBlock::forced_import(
|
||||
db,
|
||||
"vaulted_supply",
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
vaulted: AmountPerBlock::forced_import(db, "vaulted_supply", version, indexes)?,
|
||||
active: AmountPerBlock::forced_import(db, "active_supply", version, indexes)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,59 +24,56 @@ impl Vecs {
|
||||
.compute(starting_indexes.height, exit, |vec| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
&prices.spot.usd.height,
|
||||
&prices.cached_spot_usd,
|
||||
&coinblocks_destroyed.block,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.created
|
||||
.compute(starting_indexes.height, exit, |vec| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
&prices.spot.usd.height,
|
||||
&activity.coinblocks_created.block,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
self.created.compute(starting_indexes.height, exit, |vec| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
&prices.cached_spot_usd,
|
||||
&activity.coinblocks_created.block,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.stored
|
||||
.compute(starting_indexes.height, exit, |vec| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
&prices.spot.usd.height,
|
||||
&activity.coinblocks_stored.block,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
self.stored.compute(starting_indexes.height, exit, |vec| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
&prices.cached_spot_usd,
|
||||
&activity.coinblocks_stored.block,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// VOCDD: Value of Coin Days Destroyed = price × (CDD / circulating_supply)
|
||||
// Supply-adjusted to account for growing supply over time
|
||||
// This is a key input for Reserve Risk / HODL Bank calculation
|
||||
self.vocdd
|
||||
.compute(starting_indexes.height, exit, |vec| {
|
||||
vec.compute_transform3(
|
||||
starting_indexes.height,
|
||||
&prices.spot.usd.height,
|
||||
&coindays_destroyed.block,
|
||||
circulating_supply,
|
||||
|(i, price, cdd, supply, _): (_, Dollars, StoredF64, Bitcoin, _)| {
|
||||
let supply_f64 = f64::from(supply);
|
||||
if supply_f64 == 0.0 {
|
||||
(i, StoredF64::from(0.0))
|
||||
} else {
|
||||
// VOCDD = price × (CDD / supply)
|
||||
let vocdd = f64::from(price) * f64::from(cdd) / supply_f64;
|
||||
(i, StoredF64::from(vocdd))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
self.vocdd.compute(starting_indexes.height, exit, |vec| {
|
||||
vec.compute_transform3(
|
||||
starting_indexes.height,
|
||||
&prices.cached_spot_usd,
|
||||
&coindays_destroyed.block,
|
||||
circulating_supply,
|
||||
|(i, price, cdd, supply, _): (_, Dollars, StoredF64, Bitcoin, _)| {
|
||||
let supply_f64 = f64::from(supply);
|
||||
if supply_f64 == 0.0 {
|
||||
(i, StoredF64::from(0.0))
|
||||
} else {
|
||||
// VOCDD = price × (CDD / supply)
|
||||
let vocdd = f64::from(price) * f64::from(cdd) / supply_f64;
|
||||
(i, StoredF64::from(vocdd))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -148,11 +148,7 @@ impl ActivityCountVecs {
|
||||
self.both.block.push(counts.both.into());
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()> {
|
||||
self.reactivated.compute_rest(max_from, exit)?;
|
||||
self.sending.compute_rest(max_from, exit)?;
|
||||
self.receiving.compute_rest(max_from, exit)?;
|
||||
@@ -180,8 +176,8 @@ impl AddrTypeToActivityCountVecs {
|
||||
indexes: &indexes::Vecs,
|
||||
cached_starts: &CachedWindowStarts,
|
||||
) -> Result<Self> {
|
||||
Ok(Self::from(
|
||||
ByAddrType::<ActivityCountVecs>::new_with_name(|type_name| {
|
||||
Ok(Self::from(ByAddrType::<ActivityCountVecs>::new_with_name(
|
||||
|type_name| {
|
||||
ActivityCountVecs::forced_import(
|
||||
db,
|
||||
&format!("{type_name}_{name}"),
|
||||
@@ -189,8 +185,8 @@ impl AddrTypeToActivityCountVecs {
|
||||
indexes,
|
||||
cached_starts,
|
||||
)
|
||||
})?,
|
||||
))
|
||||
},
|
||||
)?))
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_len(&self) -> usize {
|
||||
@@ -221,11 +217,7 @@ impl AddrTypeToActivityCountVecs {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()> {
|
||||
for type_vecs in self.0.values_mut() {
|
||||
type_vecs.compute_rest(max_from, exit)?;
|
||||
}
|
||||
@@ -259,7 +251,11 @@ impl AddrActivityVecs {
|
||||
Ok(Self {
|
||||
all: ActivityCountVecs::forced_import(db, name, version, indexes, cached_starts)?,
|
||||
by_addr_type: AddrTypeToActivityCountVecs::forced_import(
|
||||
db, name, version, indexes, cached_starts,
|
||||
db,
|
||||
name,
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
@@ -284,11 +280,7 @@ impl AddrActivityVecs {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()> {
|
||||
self.all.compute_rest(max_from, exit)?;
|
||||
self.by_addr_type.compute_rest(max_from, exit)?;
|
||||
Ok(())
|
||||
|
||||
@@ -12,9 +12,7 @@ use vecdb::{
|
||||
use crate::{indexes, internal::PerBlock};
|
||||
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct AddrCountVecs<M: StorageMode = Rw>(
|
||||
#[traversable(flatten)] pub PerBlock<StoredU64, M>,
|
||||
);
|
||||
pub struct AddrCountVecs<M: StorageMode = Rw>(#[traversable(flatten)] pub PerBlock<StoredU64, M>);
|
||||
|
||||
impl AddrCountVecs {
|
||||
pub(crate) fn forced_import(
|
||||
@@ -23,9 +21,7 @@ impl AddrCountVecs {
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self(PerBlock::forced_import(
|
||||
db, name, version, indexes,
|
||||
)?))
|
||||
Ok(Self(PerBlock::forced_import(db, name, version, indexes)?))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,42 +53,17 @@ impl From<(&AddrTypeToAddrCountVecs, Height)> for AddrTypeToAddrCount {
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2pkh: groups
|
||||
.p2pkh
|
||||
.height
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2sh: groups
|
||||
.p2sh
|
||||
.height
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2pkh: groups.p2pkh.height.collect_one(prev_height).unwrap().into(),
|
||||
p2sh: groups.p2sh.height.collect_one(prev_height).unwrap().into(),
|
||||
p2wpkh: groups
|
||||
.p2wpkh
|
||||
.height
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2wsh: groups
|
||||
.p2wsh
|
||||
.height
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2tr: groups
|
||||
.p2tr
|
||||
.height
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2a: groups
|
||||
.p2a
|
||||
.height
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2wsh: groups.p2wsh.height.collect_one(prev_height).unwrap().into(),
|
||||
p2tr: groups.p2tr.height.collect_one(prev_height).unwrap().into(),
|
||||
p2a: groups.p2a.height.collect_one(prev_height).unwrap().into(),
|
||||
})
|
||||
} else {
|
||||
Default::default()
|
||||
@@ -177,7 +148,10 @@ impl AddrCountsVecs {
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_len(&self) -> usize {
|
||||
self.all.height.len().min(self.by_addr_type.min_stateful_len())
|
||||
self.all
|
||||
.height
|
||||
.len()
|
||||
.min(self.by_addr_type.min_stateful_len())
|
||||
}
|
||||
|
||||
pub(crate) fn par_iter_height_mut(
|
||||
@@ -199,11 +173,7 @@ impl AddrCountsVecs {
|
||||
self.by_addr_type.push_height(addr_counts);
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
pub(crate) fn compute_rest(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
let sources = self.by_addr_type.by_height();
|
||||
self.all
|
||||
.height
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
EmptyAddrData, EmptyAddrIndex, FundedAddrData, FundedAddrIndex, Height,
|
||||
};
|
||||
use brk_types::{EmptyAddrData, EmptyAddrIndex, FundedAddrData, FundedAddrIndex, Height};
|
||||
use rayon::prelude::*;
|
||||
use vecdb::{AnyStoredVec, BytesVec, Rw, Stamp, StorageMode, WritableVec};
|
||||
|
||||
|
||||
@@ -45,9 +45,6 @@ impl DeltaVecs {
|
||||
)
|
||||
});
|
||||
|
||||
Self {
|
||||
all,
|
||||
by_addr_type,
|
||||
}
|
||||
Self { all, by_addr_type }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ use brk_error::{Error, Result};
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
AnyAddrIndex, Height, OutputType, P2AAddrIndex, P2PK33AddrIndex, P2PK65AddrIndex,
|
||||
P2PKHAddrIndex, P2SHAddrIndex, P2TRAddrIndex, P2WPKHAddrIndex, P2WSHAddrIndex,
|
||||
TypeIndex, Version,
|
||||
P2PKHAddrIndex, P2SHAddrIndex, P2TRAddrIndex, P2WPKHAddrIndex, P2WSHAddrIndex, TypeIndex,
|
||||
Version,
|
||||
};
|
||||
use rayon::prelude::*;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
@@ -44,10 +44,7 @@ impl NewAddrCountVecs {
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
all,
|
||||
by_addr_type,
|
||||
})
|
||||
Ok(Self { all, by_addr_type })
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
|
||||
@@ -24,20 +24,11 @@ impl TotalAddrCountVecs {
|
||||
) -> Result<Self> {
|
||||
let all = PerBlock::forced_import(db, "total_addr_count", version, indexes)?;
|
||||
|
||||
let by_addr_type: ByAddrType<PerBlock<StoredU64>> =
|
||||
ByAddrType::new_with_name(|name| {
|
||||
PerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_total_addr_count"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
let by_addr_type: ByAddrType<PerBlock<StoredU64>> = ByAddrType::new_with_name(|name| {
|
||||
PerBlock::forced_import(db, &format!("{name}_total_addr_count"), version, indexes)
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
all,
|
||||
by_addr_type,
|
||||
})
|
||||
Ok(Self { all, by_addr_type })
|
||||
}
|
||||
|
||||
/// Eagerly compute total = addr_count + empty_addr_count.
|
||||
|
||||
@@ -103,9 +103,7 @@ pub(crate) fn load_uncached_addr_data(
|
||||
// Check if this is a new address (type_index >= first for this height)
|
||||
let first = *first_addr_indexes.get(addr_type).unwrap();
|
||||
if first <= type_index {
|
||||
return Ok(Some(WithAddrDataSource::New(
|
||||
FundedAddrData::default(),
|
||||
)));
|
||||
return Ok(Some(WithAddrDataSource::New(FundedAddrData::default())));
|
||||
}
|
||||
|
||||
// Skip if already in cache
|
||||
|
||||
@@ -26,10 +26,7 @@ impl<'a> AddrLookup<'a> {
|
||||
&mut self,
|
||||
output_type: OutputType,
|
||||
type_index: TypeIndex,
|
||||
) -> (
|
||||
&mut WithAddrDataSource<FundedAddrData>,
|
||||
TrackingStatus,
|
||||
) {
|
||||
) -> (&mut WithAddrDataSource<FundedAddrData>, TrackingStatus) {
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
let map = self.funded.get_mut(output_type).unwrap();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use brk_error::Result;
|
||||
use brk_types::{
|
||||
AnyAddrIndex, EmptyAddrData, EmptyAddrIndex, FundedAddrData, FundedAddrIndex,
|
||||
OutputType, TypeIndex,
|
||||
AnyAddrIndex, EmptyAddrData, EmptyAddrIndex, FundedAddrData, FundedAddrIndex, OutputType,
|
||||
TypeIndex,
|
||||
};
|
||||
use vecdb::AnyVec;
|
||||
|
||||
|
||||
@@ -26,7 +26,11 @@ pub(crate) fn process_received(
|
||||
empty_addr_count: &mut ByAddrType<u64>,
|
||||
activity_counts: &mut AddrTypeToActivityCounts,
|
||||
) {
|
||||
let max_type_len = received_data.iter().map(|(_, v)| v.len()).max().unwrap_or(0);
|
||||
let max_type_len = received_data
|
||||
.iter()
|
||||
.map(|(_, v)| v.len())
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
let mut aggregated: FxHashMap<TypeIndex, AggregatedReceive> =
|
||||
FxHashMap::with_capacity_and_hasher(max_type_len, Default::default());
|
||||
|
||||
|
||||
@@ -41,10 +41,7 @@ pub(crate) fn update_tx_counts(
|
||||
.get_mut(&type_index)
|
||||
{
|
||||
addr_data.tx_count += tx_count;
|
||||
} else if let Some(addr_data) = empty_cache
|
||||
.get_mut(addr_type)
|
||||
.unwrap()
|
||||
.get_mut(&type_index)
|
||||
} else if let Some(addr_data) = empty_cache.get_mut(addr_type).unwrap().get_mut(&type_index)
|
||||
{
|
||||
addr_data.tx_count += tx_count;
|
||||
}
|
||||
|
||||
@@ -90,9 +90,7 @@ pub(crate) fn process_inputs(
|
||||
};
|
||||
|
||||
let items: Vec<_> = if input_count < 128 {
|
||||
(0..input_count)
|
||||
.map(map_fn)
|
||||
.collect::<Result<Vec<_>>>()?
|
||||
(0..input_count).map(map_fn).collect::<Result<Vec<_>>>()?
|
||||
} else {
|
||||
(0..input_count)
|
||||
.into_par_iter()
|
||||
@@ -109,10 +107,9 @@ pub(crate) fn process_inputs(
|
||||
Default::default(),
|
||||
);
|
||||
let mut sent_data = HeightToAddrTypeToVec::with_capacity(estimated_unique_heights);
|
||||
let mut addr_data =
|
||||
AddrTypeToTypeIndexMap::<WithAddrDataSource<FundedAddrData>>::with_capacity(
|
||||
estimated_per_type,
|
||||
);
|
||||
let mut addr_data = AddrTypeToTypeIndexMap::<WithAddrDataSource<FundedAddrData>>::with_capacity(
|
||||
estimated_per_type,
|
||||
);
|
||||
let mut tx_index_vecs =
|
||||
AddrTypeToTypeIndexMap::<SmallVec<[TxIndex; 4]>>::with_capacity(estimated_per_type);
|
||||
|
||||
|
||||
@@ -5,9 +5,7 @@ use rayon::prelude::*;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::distribution::{
|
||||
addr::{
|
||||
AddrTypeToTypeIndexMap, AddrTypeToVec, AddrsDataVecs, AnyAddrIndexesVecs,
|
||||
},
|
||||
addr::{AddrTypeToTypeIndexMap, AddrTypeToVec, AddrsDataVecs, AnyAddrIndexesVecs},
|
||||
compute::{TxOutData, VecsReaders},
|
||||
state::Transacted,
|
||||
};
|
||||
@@ -79,9 +77,7 @@ pub(crate) fn process_outputs(
|
||||
};
|
||||
|
||||
let items: Vec<_> = if output_count < 128 {
|
||||
(0..output_count)
|
||||
.map(map_fn)
|
||||
.collect::<Result<Vec<_>>>()?
|
||||
(0..output_count).map(map_fn).collect::<Result<Vec<_>>>()?
|
||||
} else {
|
||||
(0..output_count)
|
||||
.into_par_iter()
|
||||
@@ -93,10 +89,9 @@ pub(crate) fn process_outputs(
|
||||
let estimated_per_type = (output_count / 8).max(8);
|
||||
let mut transacted = Transacted::default();
|
||||
let mut received_data = AddrTypeToVec::with_capacity(estimated_per_type);
|
||||
let mut addr_data =
|
||||
AddrTypeToTypeIndexMap::<WithAddrDataSource<FundedAddrData>>::with_capacity(
|
||||
estimated_per_type,
|
||||
);
|
||||
let mut addr_data = AddrTypeToTypeIndexMap::<WithAddrDataSource<FundedAddrData>>::with_capacity(
|
||||
estimated_per_type,
|
||||
);
|
||||
let mut tx_index_vecs =
|
||||
AddrTypeToTypeIndexMap::<SmallVec<[TxIndex; 4]>>::with_capacity(estimated_per_type);
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_cohort::{
|
||||
AddrGroups, AmountRange, OverAmount, UnderAmount, Filter, Filtered,
|
||||
};
|
||||
use brk_cohort::{AddrGroups, AmountRange, Filter, Filtered, OverAmount, UnderAmount};
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Indexes, StoredU64, Version};
|
||||
|
||||
@@ -161,9 +161,7 @@ impl DynCohortVecs for AddrCohortVecs {
|
||||
}
|
||||
|
||||
if let Some(state) = self.state.as_ref() {
|
||||
self.addr_count
|
||||
.height
|
||||
.push(state.addr_count.into());
|
||||
self.addr_count.height.push(state.addr_count.into());
|
||||
self.metrics.supply.push_state(&state.inner);
|
||||
self.metrics.outputs.push_state(&state.inner);
|
||||
self.metrics.activity.push_state(&state.inner);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use brk_types::{CostBasisSnapshot, Cents, Height, Timestamp};
|
||||
use brk_types::{Cents, CostBasisSnapshot, Height, Timestamp};
|
||||
use vecdb::Rw;
|
||||
|
||||
use crate::distribution::state::Transacted;
|
||||
@@ -34,10 +34,16 @@ impl UTXOCohorts<Rw> {
|
||||
.unwrap()
|
||||
.receive_utxo_snapshot(&supply_state, &snapshot);
|
||||
if let Some(v) = self.epoch.mut_vec_from_height(height) {
|
||||
v.state.as_mut().unwrap().receive_utxo_snapshot(&supply_state, &snapshot);
|
||||
v.state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.receive_utxo_snapshot(&supply_state, &snapshot);
|
||||
}
|
||||
if let Some(v) = self.class.mut_vec_from_timestamp(timestamp) {
|
||||
v.state.as_mut().unwrap().receive_utxo_snapshot(&supply_state, &snapshot);
|
||||
v.state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.receive_utxo_snapshot(&supply_state, &snapshot);
|
||||
}
|
||||
|
||||
// Update output type cohorts (skip types with no outputs this block)
|
||||
|
||||
@@ -64,10 +64,16 @@ impl UTXOCohorts<Rw> {
|
||||
.unwrap()
|
||||
.send_utxo_precomputed(&sent.spendable_supply, &pre);
|
||||
if let Some(v) = self.epoch.mut_vec_from_height(receive_height) {
|
||||
v.state.as_mut().unwrap().send_utxo_precomputed(&sent.spendable_supply, &pre);
|
||||
v.state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.send_utxo_precomputed(&sent.spendable_supply, &pre);
|
||||
}
|
||||
if let Some(v) = self.class.mut_vec_from_timestamp(block_state.timestamp) {
|
||||
v.state.as_mut().unwrap().send_utxo_precomputed(&sent.spendable_supply, &pre);
|
||||
v.state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.send_utxo_precomputed(&sent.spendable_supply, &pre);
|
||||
}
|
||||
} else if sent.spendable_supply.utxo_count > 0 {
|
||||
// Zero-value UTXOs: just subtract supply
|
||||
|
||||
@@ -67,9 +67,7 @@ impl UTXOCohorts<Rw> {
|
||||
idx
|
||||
} else {
|
||||
let mut idx = cached[boundary_idx];
|
||||
while idx < chain_state.len()
|
||||
&& *chain_state[idx].timestamp <= lower_timestamp
|
||||
{
|
||||
while idx < chain_state.len() && *chain_state[idx].timestamp <= lower_timestamp {
|
||||
idx += 1;
|
||||
}
|
||||
cached[boundary_idx] = idx;
|
||||
@@ -84,8 +82,7 @@ impl UTXOCohorts<Rw> {
|
||||
|
||||
// Move supply from younger cohort to older cohort
|
||||
for block_state in &chain_state[start_idx..end_idx] {
|
||||
let snapshot =
|
||||
CostBasisSnapshot::from_utxo(block_state.price, &block_state.supply);
|
||||
let snapshot = CostBasisSnapshot::from_utxo(block_state.price, &block_state.supply);
|
||||
if let Some(state) = age_cohorts[boundary_idx].as_mut() {
|
||||
state.decrement_snapshot(&snapshot);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ use brk_error::Result;
|
||||
use brk_types::{Cents, Height, Indexes, Version};
|
||||
use vecdb::{Exit, ReadableVec};
|
||||
|
||||
use crate::{distribution::{cohorts::traits::DynCohortVecs, metrics::CoreCohortMetrics}, prices};
|
||||
use crate::{
|
||||
distribution::{cohorts::traits::DynCohortVecs, metrics::CoreCohortMetrics},
|
||||
prices,
|
||||
};
|
||||
|
||||
use super::UTXOCohortVecs;
|
||||
|
||||
@@ -45,12 +48,8 @@ impl DynCohortVecs for UTXOCohortVecs<CoreCohortMetrics> {
|
||||
if let Some(state) = self.state.as_mut() {
|
||||
state.apply_pending();
|
||||
let unrealized_state = state.compute_unrealized_state(height_price);
|
||||
self.metrics
|
||||
.unrealized
|
||||
.push_state(&unrealized_state);
|
||||
self.metrics
|
||||
.supply
|
||||
.push_profitability(&unrealized_state);
|
||||
self.metrics.unrealized.push_state(&unrealized_state);
|
||||
self.metrics.supply.push_profitability(&unrealized_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@ use brk_error::Result;
|
||||
use brk_types::{Cents, Height, Indexes, Version};
|
||||
use vecdb::{Exit, ReadableVec};
|
||||
|
||||
use crate::{distribution::cohorts::traits::DynCohortVecs, distribution::metrics::TypeCohortMetrics, prices};
|
||||
use crate::{
|
||||
distribution::cohorts::traits::DynCohortVecs, distribution::metrics::TypeCohortMetrics, prices,
|
||||
};
|
||||
|
||||
use super::UTXOCohortVecs;
|
||||
|
||||
@@ -45,12 +47,8 @@ impl DynCohortVecs for UTXOCohortVecs<TypeCohortMetrics> {
|
||||
if let Some(state) = self.state.as_mut() {
|
||||
state.apply_pending();
|
||||
let unrealized_state = state.compute_unrealized_state(height_price);
|
||||
self.metrics
|
||||
.unrealized
|
||||
.push_state(&unrealized_state);
|
||||
self.metrics
|
||||
.supply
|
||||
.push_profitability(&unrealized_state);
|
||||
self.metrics.unrealized.push_state(&unrealized_state);
|
||||
self.metrics.supply.push_profitability(&unrealized_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use brk_types::{
|
||||
use rayon::prelude::*;
|
||||
use rustc_hash::FxHashSet;
|
||||
use tracing::{debug, info};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableVec, VecIndex, WritableVec};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableVec, VecIndex, WritableVec, unlikely};
|
||||
|
||||
use crate::{
|
||||
distribution::{
|
||||
@@ -144,42 +144,50 @@ pub(crate) fn process_blocks(
|
||||
let first_p2a_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2a.first_index
|
||||
.p2a
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2pk33_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2pk33.first_index
|
||||
.p2pk33
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2pk65_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2pk65.first_index
|
||||
.p2pk65
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2pkh_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2pkh.first_index
|
||||
.p2pkh
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2sh_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2sh.first_index
|
||||
.p2sh
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2tr_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2tr.first_index
|
||||
.p2tr
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2wpkh_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2wpkh.first_index
|
||||
.p2wpkh
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2wsh_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2wsh.first_index
|
||||
.p2wsh
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
|
||||
// Track running totals - recover from previous height if resuming
|
||||
@@ -187,10 +195,8 @@ pub(crate) fn process_blocks(
|
||||
let (mut addr_counts, mut empty_addr_counts) = if starting_height > Height::ZERO {
|
||||
let addr_counts =
|
||||
AddrTypeToAddrCount::from((&vecs.addrs.funded.by_addr_type, starting_height));
|
||||
let empty_addr_counts = AddrTypeToAddrCount::from((
|
||||
&vecs.addrs.empty.by_addr_type,
|
||||
starting_height,
|
||||
));
|
||||
let empty_addr_counts =
|
||||
AddrTypeToAddrCount::from((&vecs.addrs.empty.by_addr_type, starting_height));
|
||||
(addr_counts, empty_addr_counts)
|
||||
} else {
|
||||
(
|
||||
@@ -237,7 +243,11 @@ pub(crate) fn process_blocks(
|
||||
for height in starting_height.to_usize()..=last_height.to_usize() {
|
||||
let height = Height::from(height);
|
||||
|
||||
info!("Processing chain at {}...", height);
|
||||
if unlikely(height.is_multiple_of(100)) {
|
||||
info!("Processing chain at {}...", height);
|
||||
} else {
|
||||
debug!("Processing chain at {}...", height);
|
||||
}
|
||||
|
||||
// Get block metadata from pre-collected vecs
|
||||
let offset = height.to_usize() - start_usize;
|
||||
@@ -274,12 +284,18 @@ pub(crate) fn process_blocks(
|
||||
// processing closures so outputs and inputs collection overlap each other
|
||||
// and tick-tock, instead of running sequentially before the join.
|
||||
let (matured, oi_result) = rayon::join(
|
||||
|| vecs.utxo_cohorts.tick_tock_next_block(chain_state, timestamp),
|
||||
|| {
|
||||
vecs.utxo_cohorts
|
||||
.tick_tock_next_block(chain_state, timestamp)
|
||||
},
|
||||
|| -> Result<_> {
|
||||
let (outputs_result, inputs_result) = rayon::join(
|
||||
|| {
|
||||
let txout_index_to_tx_index = txout_to_tx_index_buf
|
||||
.build(first_tx_index, tx_count, tx_index_to_output_count);
|
||||
let txout_index_to_tx_index = txout_to_tx_index_buf.build(
|
||||
first_tx_index,
|
||||
tx_count,
|
||||
tx_index_to_output_count,
|
||||
);
|
||||
let txout_data_vec =
|
||||
txout_iters.collect_block_outputs(first_txout_index, output_count);
|
||||
process_outputs(
|
||||
@@ -294,14 +310,21 @@ pub(crate) fn process_blocks(
|
||||
},
|
||||
|| -> Result<_> {
|
||||
if input_count > 1 {
|
||||
let txin_index_to_tx_index = txin_to_tx_index_buf
|
||||
.build(first_tx_index, tx_count, tx_index_to_input_count);
|
||||
let (input_values, input_prev_heights, input_output_types, input_type_indexes) =
|
||||
txin_iters.collect_block_inputs(
|
||||
first_txin_index + 1,
|
||||
input_count - 1,
|
||||
height,
|
||||
);
|
||||
let txin_index_to_tx_index = txin_to_tx_index_buf.build(
|
||||
first_tx_index,
|
||||
tx_count,
|
||||
tx_index_to_input_count,
|
||||
);
|
||||
let (
|
||||
input_values,
|
||||
input_prev_heights,
|
||||
input_output_types,
|
||||
input_type_indexes,
|
||||
) = txin_iters.collect_block_inputs(
|
||||
first_txin_index + 1,
|
||||
input_count - 1,
|
||||
height,
|
||||
);
|
||||
process_inputs(
|
||||
input_count - 1,
|
||||
&txin_index_to_tx_index[1..],
|
||||
@@ -380,9 +403,9 @@ pub(crate) fn process_blocks(
|
||||
blocks_old as u128 * u64::from(sent.spendable_supply.value) as u128
|
||||
})
|
||||
.sum();
|
||||
vecs.coinblocks_destroyed.block.push(
|
||||
StoredF64::from(total_satblocks as f64 / Sats::ONE_BTC_U128 as f64),
|
||||
);
|
||||
vecs.coinblocks_destroyed.block.push(StoredF64::from(
|
||||
total_satblocks as f64 / Sats::ONE_BTC_U128 as f64,
|
||||
));
|
||||
}
|
||||
|
||||
// Record maturation (sats crossing age boundaries)
|
||||
@@ -451,9 +474,11 @@ pub(crate) fn process_blocks(
|
||||
vecs.utxo_cohorts.update_fenwick_from_pending();
|
||||
|
||||
// Push to height-indexed vectors
|
||||
vecs.addrs.funded
|
||||
vecs.addrs
|
||||
.funded
|
||||
.push_height(addr_counts.sum(), &addr_counts);
|
||||
vecs.addrs.empty
|
||||
vecs.addrs
|
||||
.empty
|
||||
.push_height(empty_addr_counts.sum(), &empty_addr_counts);
|
||||
vecs.addrs.activity.push_height(&activity_counts);
|
||||
|
||||
@@ -467,11 +492,8 @@ pub(crate) fn process_blocks(
|
||||
block_price,
|
||||
);
|
||||
|
||||
vecs.utxo_cohorts.push_aggregate_percentiles(
|
||||
block_price,
|
||||
date_opt,
|
||||
&vecs.states_path,
|
||||
)?;
|
||||
vecs.utxo_cohorts
|
||||
.push_aggregate_percentiles(block_price, date_opt, &vecs.states_path)?;
|
||||
|
||||
// Periodic checkpoint flush
|
||||
if height != last_height
|
||||
@@ -534,20 +556,16 @@ fn push_cohort_states(
|
||||
// Phase 1: push + unrealized (no reset yet — states still needed for aggregation)
|
||||
rayon::join(
|
||||
|| {
|
||||
utxo_cohorts
|
||||
.par_iter_separate_mut()
|
||||
.for_each(|v| {
|
||||
v.push_state(height);
|
||||
v.push_unrealized_state(height_price);
|
||||
})
|
||||
utxo_cohorts.par_iter_separate_mut().for_each(|v| {
|
||||
v.push_state(height);
|
||||
v.push_unrealized_state(height_price);
|
||||
})
|
||||
},
|
||||
|| {
|
||||
addr_cohorts
|
||||
.par_iter_separate_mut()
|
||||
.for_each(|v| {
|
||||
v.push_state(height);
|
||||
v.push_unrealized_state(height_price);
|
||||
})
|
||||
addr_cohorts.par_iter_separate_mut().for_each(|v| {
|
||||
v.push_state(height);
|
||||
v.push_unrealized_state(height_price);
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -116,11 +116,10 @@ impl<'a> TxInReaders<'a> {
|
||||
current_height: Height,
|
||||
) -> (&[Sats], &[Height], &[OutputType], &[TypeIndex]) {
|
||||
let end = first_txin_index + input_count;
|
||||
self.txins.spent.value.collect_range_into_at(
|
||||
first_txin_index,
|
||||
end,
|
||||
&mut self.values_buf,
|
||||
);
|
||||
self.txins
|
||||
.spent
|
||||
.value
|
||||
.collect_range_into_at(first_txin_index, end, &mut self.values_buf);
|
||||
self.indexer.vecs.inputs.outpoint.collect_range_into_at(
|
||||
first_txin_index,
|
||||
end,
|
||||
@@ -138,8 +137,8 @@ impl<'a> TxInReaders<'a> {
|
||||
);
|
||||
|
||||
self.prev_heights_buf.clear();
|
||||
self.prev_heights_buf.extend(
|
||||
self.outpoints_buf.iter().map(|outpoint| {
|
||||
self.prev_heights_buf
|
||||
.extend(self.outpoints_buf.iter().map(|outpoint| {
|
||||
if outpoint.is_coinbase() {
|
||||
current_height
|
||||
} else {
|
||||
@@ -147,8 +146,7 @@ impl<'a> TxInReaders<'a> {
|
||||
.get(outpoint.tx_index())
|
||||
.unwrap_or(current_height)
|
||||
}
|
||||
}),
|
||||
);
|
||||
}));
|
||||
|
||||
(
|
||||
&self.values_buf,
|
||||
@@ -166,10 +164,7 @@ pub struct VecsReaders {
|
||||
}
|
||||
|
||||
impl VecsReaders {
|
||||
pub(crate) fn new(
|
||||
any_addr_indexes: &AnyAddrIndexesVecs,
|
||||
addrs_data: &AddrsDataVecs,
|
||||
) -> Self {
|
||||
pub(crate) fn new(any_addr_indexes: &AnyAddrIndexesVecs, addrs_data: &AddrsDataVecs) -> Self {
|
||||
Self {
|
||||
addr_type_index_to_any_addr_index: ByAddrType {
|
||||
p2a: any_addr_indexes.p2a.create_reader(),
|
||||
|
||||
@@ -185,10 +185,7 @@ fn rollback_states(
|
||||
heights.insert(chain_height);
|
||||
|
||||
let Ok(stamps) = addr_indexes_rollbacks else {
|
||||
warn!(
|
||||
"addr_indexes rollback failed: {:?}",
|
||||
addr_indexes_rollbacks
|
||||
);
|
||||
warn!("addr_indexes rollback failed: {:?}", addr_indexes_rollbacks);
|
||||
return Height::ZERO;
|
||||
};
|
||||
for (i, s) in stamps.iter().enumerate() {
|
||||
|
||||
@@ -5,7 +5,10 @@ use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::{metrics::ImportConfig, state::{CohortState, CostBasisOps, RealizedOps}},
|
||||
distribution::{
|
||||
metrics::ImportConfig,
|
||||
state::{CohortState, CostBasisOps, RealizedOps},
|
||||
},
|
||||
internal::{AmountPerBlockCumulativeRolling, PerBlockCumulativeRolling},
|
||||
prices,
|
||||
};
|
||||
@@ -46,19 +49,18 @@ impl ActivityCore {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn push_state(
|
||||
&mut self,
|
||||
state: &CohortState<impl RealizedOps, impl CostBasisOps>,
|
||||
) {
|
||||
pub(crate) fn push_state(&mut self, state: &CohortState<impl RealizedOps, impl CostBasisOps>) {
|
||||
self.minimal.push_state(state);
|
||||
self.coindays_destroyed.block.push(
|
||||
StoredF64::from(Bitcoin::from(state.satdays_destroyed)),
|
||||
);
|
||||
self.coindays_destroyed
|
||||
.block
|
||||
.push(StoredF64::from(Bitcoin::from(state.satdays_destroyed)));
|
||||
self.transfer_volume_in_profit
|
||||
.block.sats
|
||||
.block
|
||||
.sats
|
||||
.push(state.realized.sent_in_profit());
|
||||
self.transfer_volume_in_loss
|
||||
.block.sats
|
||||
.block
|
||||
.sats
|
||||
.push(state.realized.sent_in_loss());
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,10 @@ use vecdb::{AnyStoredVec, Exit, ReadableCloneableVec, Rw, StorageMode};
|
||||
use crate::internal::{Identity, LazyPerBlock, PerBlock, Windows};
|
||||
|
||||
use crate::{
|
||||
distribution::{metrics::ImportConfig, state::{CohortState, CostBasisOps, RealizedOps}},
|
||||
distribution::{
|
||||
metrics::ImportConfig,
|
||||
state::{CohortState, CostBasisOps, RealizedOps},
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
@@ -33,7 +36,12 @@ impl ActivityFull {
|
||||
let coinyears_destroyed = LazyPerBlock::from_height_source::<Identity<StoredF64>>(
|
||||
&cfg.name("coinyears_destroyed"),
|
||||
cfg.version + v1,
|
||||
inner.coindays_destroyed.sum._1y.height.read_only_boxed_clone(),
|
||||
inner
|
||||
.coindays_destroyed
|
||||
.sum
|
||||
._1y
|
||||
.height
|
||||
.read_only_boxed_clone(),
|
||||
cfg.indexes,
|
||||
);
|
||||
|
||||
@@ -89,7 +97,8 @@ impl ActivityFull {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.inner.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
self.inner
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
|
||||
for ((dormancy, cdd_sum), tv_sum) in self
|
||||
.dormancy
|
||||
|
||||
@@ -4,7 +4,10 @@ use brk_types::{Indexes, Version};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::{metrics::ImportConfig, state::{CohortState, CostBasisOps, RealizedOps}},
|
||||
distribution::{
|
||||
metrics::ImportConfig,
|
||||
state::{CohortState, CostBasisOps, RealizedOps},
|
||||
},
|
||||
internal::AmountPerBlockCumulativeRolling,
|
||||
prices,
|
||||
};
|
||||
@@ -23,16 +26,11 @@ impl ActivityMinimal {
|
||||
}
|
||||
|
||||
pub(crate) fn min_len(&self) -> usize {
|
||||
self.transfer_volume
|
||||
.block.sats
|
||||
.len()
|
||||
self.transfer_volume.block.sats.len()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn push_state(
|
||||
&mut self,
|
||||
state: &CohortState<impl RealizedOps, impl CostBasisOps>,
|
||||
) {
|
||||
pub(crate) fn push_state(&mut self, state: &CohortState<impl RealizedOps, impl CostBasisOps>) {
|
||||
self.transfer_volume.block.sats.push(state.sent);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,7 @@ pub trait ActivityLike: Send + Sync {
|
||||
fn as_core(&self) -> &ActivityCore;
|
||||
fn as_core_mut(&mut self) -> &mut ActivityCore;
|
||||
fn min_len(&self) -> usize;
|
||||
fn push_state<R: RealizedOps>(
|
||||
&mut self,
|
||||
state: &CohortState<R, impl CostBasisOps>,
|
||||
);
|
||||
fn push_state<R: RealizedOps>(&mut self, state: &CohortState<R, impl CostBasisOps>);
|
||||
fn validate_computed_versions(&mut self, base_version: Version) -> Result<()>;
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
@@ -39,37 +36,69 @@ pub trait ActivityLike: Send + Sync {
|
||||
}
|
||||
|
||||
impl ActivityLike for ActivityCore {
|
||||
fn as_core(&self) -> &ActivityCore { self }
|
||||
fn as_core_mut(&mut self) -> &mut ActivityCore { self }
|
||||
fn min_len(&self) -> usize { self.min_len() }
|
||||
fn as_core(&self) -> &ActivityCore {
|
||||
self
|
||||
}
|
||||
fn as_core_mut(&mut self) -> &mut ActivityCore {
|
||||
self
|
||||
}
|
||||
fn min_len(&self) -> usize {
|
||||
self.min_len()
|
||||
}
|
||||
fn push_state<R: RealizedOps>(&mut self, state: &CohortState<R, impl CostBasisOps>) {
|
||||
self.push_state(state);
|
||||
}
|
||||
fn validate_computed_versions(&mut self, base_version: Version) -> Result<()> {
|
||||
self.validate_computed_versions(base_version)
|
||||
}
|
||||
fn compute_from_stateful(&mut self, starting_indexes: &Indexes, others: &[&ActivityCore], exit: &Exit) -> Result<()> {
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&ActivityCore],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_from_stateful(starting_indexes, others, exit)
|
||||
}
|
||||
fn compute_rest_part1(&mut self, prices: &prices::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
fn compute_rest_part1(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_rest_part1(prices, starting_indexes, exit)
|
||||
}
|
||||
}
|
||||
|
||||
impl ActivityLike for ActivityFull {
|
||||
fn as_core(&self) -> &ActivityCore { &self.inner }
|
||||
fn as_core_mut(&mut self) -> &mut ActivityCore { &mut self.inner }
|
||||
fn min_len(&self) -> usize { self.full_min_len() }
|
||||
fn as_core(&self) -> &ActivityCore {
|
||||
&self.inner
|
||||
}
|
||||
fn as_core_mut(&mut self) -> &mut ActivityCore {
|
||||
&mut self.inner
|
||||
}
|
||||
fn min_len(&self) -> usize {
|
||||
self.full_min_len()
|
||||
}
|
||||
fn push_state<R: RealizedOps>(&mut self, state: &CohortState<R, impl CostBasisOps>) {
|
||||
self.full_push_state(state);
|
||||
}
|
||||
fn validate_computed_versions(&mut self, base_version: Version) -> Result<()> {
|
||||
self.inner.validate_computed_versions(base_version)
|
||||
}
|
||||
fn compute_from_stateful(&mut self, starting_indexes: &Indexes, others: &[&ActivityCore], exit: &Exit) -> Result<()> {
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&ActivityCore],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_from_stateful(starting_indexes, others, exit)
|
||||
}
|
||||
fn compute_rest_part1(&mut self, prices: &prices::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
fn compute_rest_part1(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_rest_part1(prices, starting_indexes, exit)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use brk_cohort::Filter;
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
Cents, Dollars, Height, Indexes, Version,
|
||||
};
|
||||
use brk_types::{Cents, Dollars, Height, Indexes, Version};
|
||||
use vecdb::AnyStoredVec;
|
||||
use vecdb::{Exit, ReadOnlyClone, ReadableVec, Rw, StorageMode};
|
||||
|
||||
@@ -121,7 +119,7 @@ impl AllCohortMetrics {
|
||||
|
||||
self.unrealized.compute(
|
||||
starting_indexes.height,
|
||||
&prices.spot.cents.height,
|
||||
&prices.cached_spot_cents,
|
||||
&self.realized.price.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
@@ -136,15 +134,12 @@ impl AllCohortMetrics {
|
||||
)?;
|
||||
|
||||
let all_utxo_count = self.outputs.unspent_count.height.read_only_clone();
|
||||
self.outputs.compute_part2(
|
||||
starting_indexes.height,
|
||||
&all_utxo_count,
|
||||
exit,
|
||||
)?;
|
||||
self.outputs
|
||||
.compute_part2(starting_indexes.height, &all_utxo_count, exit)?;
|
||||
|
||||
self.cost_basis.compute_prices(
|
||||
starting_indexes,
|
||||
&prices.spot.cents.height,
|
||||
&prices.cached_spot_cents,
|
||||
&self.unrealized.invested_capital.in_profit.cents.height,
|
||||
&self.unrealized.invested_capital.in_loss.cents.height,
|
||||
&self.supply.in_profit.sats.height,
|
||||
@@ -154,11 +149,8 @@ impl AllCohortMetrics {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.unrealized.compute_sentiment(
|
||||
starting_indexes,
|
||||
&prices.spot.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.unrealized
|
||||
.compute_sentiment(starting_indexes, &prices.cached_spot_cents, exit)?;
|
||||
|
||||
self.relative.compute(
|
||||
starting_indexes.height,
|
||||
|
||||
@@ -82,21 +82,17 @@ impl BasicCohortMetrics {
|
||||
|
||||
self.unrealized.compute(
|
||||
starting_indexes.height,
|
||||
&prices.spot.cents.height,
|
||||
&prices.cached_spot_cents,
|
||||
&self.realized.price.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.relative.compute(
|
||||
starting_indexes.height,
|
||||
&self.supply,
|
||||
all_supply_sats,
|
||||
exit,
|
||||
)?;
|
||||
self.relative
|
||||
.compute(starting_indexes.height, &self.supply, all_supply_sats, exit)?;
|
||||
|
||||
self.outputs.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
self.outputs
|
||||
.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -92,7 +92,10 @@ impl CoreCohortMetrics {
|
||||
)?;
|
||||
self.unrealized.compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others.iter().map(|v| v.unrealized_core()).collect::<Vec<_>>(),
|
||||
&others
|
||||
.iter()
|
||||
.map(|v| v.unrealized_core())
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -105,16 +108,14 @@ impl CoreCohortMetrics {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.supply
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
self.supply.compute(prices, starting_indexes.height, exit)?;
|
||||
|
||||
self.outputs.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
self.activity
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
|
||||
self.realized
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
self.realized.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.unrealized.compute_rest(starting_indexes, exit)?;
|
||||
|
||||
@@ -139,19 +140,16 @@ impl CoreCohortMetrics {
|
||||
|
||||
self.unrealized.compute(
|
||||
starting_indexes.height,
|
||||
&prices.spot.cents.height,
|
||||
&prices.cached_spot_cents,
|
||||
&self.realized.price.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.relative.compute(
|
||||
starting_indexes.height,
|
||||
&self.supply,
|
||||
all_supply_sats,
|
||||
exit,
|
||||
)?;
|
||||
self.relative
|
||||
.compute(starting_indexes.height, &self.supply, all_supply_sats, exit)?;
|
||||
|
||||
self.outputs.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
self.outputs
|
||||
.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -108,14 +108,14 @@ impl ExtendedCohortMetrics {
|
||||
|
||||
self.unrealized.compute(
|
||||
starting_indexes.height,
|
||||
&prices.spot.cents.height,
|
||||
&prices.cached_spot_cents,
|
||||
&self.realized.price.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.cost_basis.compute_prices(
|
||||
starting_indexes,
|
||||
&prices.spot.cents.height,
|
||||
&prices.cached_spot_cents,
|
||||
&self.unrealized.invested_capital.in_profit.cents.height,
|
||||
&self.unrealized.invested_capital.in_loss.cents.height,
|
||||
&self.supply.in_profit.sats.height,
|
||||
@@ -126,7 +126,7 @@ impl ExtendedCohortMetrics {
|
||||
)?;
|
||||
|
||||
self.unrealized
|
||||
.compute_sentiment(starting_indexes, &prices.spot.cents.height, exit)?;
|
||||
.compute_sentiment(starting_indexes, &prices.cached_spot_cents, exit)?;
|
||||
|
||||
self.relative.compute(
|
||||
starting_indexes.height,
|
||||
|
||||
@@ -104,8 +104,7 @@ impl MinimalCohortMetrics {
|
||||
self.outputs.compute_rest(starting_indexes.height, exit)?;
|
||||
self.activity
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
self.realized
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
self.realized.compute_rest_part1(starting_indexes, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -125,12 +124,13 @@ impl MinimalCohortMetrics {
|
||||
|
||||
self.unrealized.compute(
|
||||
starting_indexes.height,
|
||||
&prices.spot.cents.height,
|
||||
&prices.cached_spot_cents,
|
||||
&self.realized.price.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.outputs.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
self.outputs
|
||||
.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -66,8 +66,7 @@ impl TypeCohortMetrics {
|
||||
self.outputs.compute_rest(starting_indexes.height, exit)?;
|
||||
self.activity
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
self.realized
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
self.realized.compute_rest_part1(starting_indexes, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -87,12 +86,13 @@ impl TypeCohortMetrics {
|
||||
|
||||
self.unrealized.compute(
|
||||
starting_indexes.height,
|
||||
&prices.spot.cents.height,
|
||||
&prices.cached_spot_cents,
|
||||
&self.realized.price.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.outputs.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
self.outputs
|
||||
.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@ use brk_types::CentsSquaredSats;
|
||||
use brk_types::{BasisPoints16, Cents, Height, Indexes, Sats, Version};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableVec, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::internal::{
|
||||
PERCENTILES_LEN, PerBlock, PercentPerBlock, PercentilesVecs, Price,
|
||||
};
|
||||
use crate::internal::{PERCENTILES_LEN, PerBlock, PercentPerBlock, PercentilesVecs, Price};
|
||||
|
||||
use super::ImportConfig;
|
||||
|
||||
@@ -33,12 +31,32 @@ impl CostBasis {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
in_profit: CostBasisSide {
|
||||
per_coin: Price::forced_import(cfg.db, &cfg.name("cost_basis_in_profit_per_coin"), cfg.version + Version::ONE, cfg.indexes)?,
|
||||
per_dollar: Price::forced_import(cfg.db, &cfg.name("cost_basis_in_profit_per_dollar"), cfg.version + Version::ONE, cfg.indexes)?,
|
||||
per_coin: Price::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("cost_basis_in_profit_per_coin"),
|
||||
cfg.version + Version::ONE,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
per_dollar: Price::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("cost_basis_in_profit_per_dollar"),
|
||||
cfg.version + Version::ONE,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
},
|
||||
in_loss: CostBasisSide {
|
||||
per_coin: Price::forced_import(cfg.db, &cfg.name("cost_basis_in_loss_per_coin"), cfg.version + Version::ONE, cfg.indexes)?,
|
||||
per_dollar: Price::forced_import(cfg.db, &cfg.name("cost_basis_in_loss_per_dollar"), cfg.version + Version::ONE, cfg.indexes)?,
|
||||
per_coin: Price::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("cost_basis_in_loss_per_coin"),
|
||||
cfg.version + Version::ONE,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
per_dollar: Price::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("cost_basis_in_loss_per_dollar"),
|
||||
cfg.version + Version::ONE,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
},
|
||||
min: cfg.import("cost_basis_min", Version::ZERO)?,
|
||||
max: cfg.import("cost_basis_max", Version::ZERO)?,
|
||||
|
||||
@@ -51,7 +51,12 @@ macro_rules! impl_cohort_accessors {
|
||||
fn unrealized_mut(&mut self) -> &mut Self::UnrealizedVecs {
|
||||
&mut self.unrealized
|
||||
}
|
||||
fn supply_and_unrealized_mut(&mut self) -> (&$crate::distribution::metrics::SupplyCore, &mut Self::UnrealizedVecs) {
|
||||
fn supply_and_unrealized_mut(
|
||||
&mut self,
|
||||
) -> (
|
||||
&$crate::distribution::metrics::SupplyCore,
|
||||
&mut Self::UnrealizedVecs,
|
||||
) {
|
||||
(&*self.supply, &mut self.unrealized)
|
||||
}
|
||||
};
|
||||
@@ -94,7 +99,12 @@ macro_rules! impl_cohort_accessors_inner {
|
||||
fn unrealized_mut(&mut self) -> &mut Self::UnrealizedVecs {
|
||||
&mut self.inner.unrealized
|
||||
}
|
||||
fn supply_and_unrealized_mut(&mut self) -> (&$crate::distribution::metrics::SupplyCore, &mut Self::UnrealizedVecs) {
|
||||
fn supply_and_unrealized_mut(
|
||||
&mut self,
|
||||
) -> (
|
||||
&$crate::distribution::metrics::SupplyCore,
|
||||
&mut Self::UnrealizedVecs,
|
||||
) {
|
||||
(&*self.inner.supply, &mut self.inner.unrealized)
|
||||
}
|
||||
};
|
||||
@@ -125,8 +135,7 @@ pub use realized::{
|
||||
pub use relative::{RelativeForAll, RelativeToAll, RelativeWithExtended};
|
||||
pub use supply::{SupplyBase, SupplyCore};
|
||||
pub use unrealized::{
|
||||
UnrealizedBasic, UnrealizedCore, UnrealizedFull, UnrealizedLike,
|
||||
UnrealizedMinimal,
|
||||
UnrealizedBasic, UnrealizedCore, UnrealizedFull, UnrealizedLike, UnrealizedMinimal,
|
||||
};
|
||||
|
||||
use brk_cohort::Filter;
|
||||
@@ -250,10 +259,7 @@ pub trait CohortMetricsBase:
|
||||
.min(self.unrealized().min_stateful_len())
|
||||
}
|
||||
|
||||
fn push_state(
|
||||
&mut self,
|
||||
state: &CohortState<RealizedState, CostBasisData<WithCapital>>,
|
||||
) {
|
||||
fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) {
|
||||
self.supply_mut().push_state(state);
|
||||
self.outputs_mut().push_state(state);
|
||||
self.activity_mut().push_state(state);
|
||||
|
||||
@@ -6,7 +6,9 @@ use vecdb::{AnyStoredVec, AnyVec, Database, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{AmountPerBlock, AmountPerBlockWithDeltas, CachedWindowStarts, PerBlock, RatioPerBlock},
|
||||
internal::{
|
||||
AmountPerBlock, AmountPerBlockWithDeltas, CachedWindowStarts, PerBlock, RatioPerBlock,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
@@ -124,7 +126,7 @@ impl ProfitabilityBucket {
|
||||
|
||||
self.unrealized_pnl.all.height.compute_transform3(
|
||||
max_from,
|
||||
&prices.spot.cents.height,
|
||||
&prices.cached_spot_cents,
|
||||
&self.realized_cap.all.height,
|
||||
&self.supply.all.sats.height,
|
||||
|(i, spot, cap, supply, ..)| {
|
||||
@@ -137,7 +139,7 @@ impl ProfitabilityBucket {
|
||||
)?;
|
||||
self.unrealized_pnl.sth.height.compute_transform3(
|
||||
max_from,
|
||||
&prices.spot.cents.height,
|
||||
&prices.cached_spot_cents,
|
||||
&self.realized_cap.sth.height,
|
||||
&self.supply.sth.sats.height,
|
||||
|(i, spot, cap, supply, ..)| {
|
||||
@@ -151,7 +153,7 @@ impl ProfitabilityBucket {
|
||||
|
||||
self.nupl.bps.height.compute_transform3(
|
||||
max_from,
|
||||
&prices.spot.cents.height,
|
||||
&prices.cached_spot_cents,
|
||||
&self.realized_cap.all.height,
|
||||
&self.supply.all.sats.height,
|
||||
|(i, spot, cap_dollars, supply_sats, ..)| {
|
||||
@@ -183,22 +185,34 @@ impl ProfitabilityBucket {
|
||||
|
||||
self.supply.all.sats.height.compute_sum_of_others(
|
||||
max_from,
|
||||
&sources.iter().map(|s| &s.supply.all.sats.height).collect::<Vec<_>>(),
|
||||
&sources
|
||||
.iter()
|
||||
.map(|s| &s.supply.all.sats.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.supply.sth.sats.height.compute_sum_of_others(
|
||||
max_from,
|
||||
&sources.iter().map(|s| &s.supply.sth.sats.height).collect::<Vec<_>>(),
|
||||
&sources
|
||||
.iter()
|
||||
.map(|s| &s.supply.sth.sats.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.realized_cap.all.height.compute_sum_of_others(
|
||||
max_from,
|
||||
&sources.iter().map(|s| &s.realized_cap.all.height).collect::<Vec<_>>(),
|
||||
&sources
|
||||
.iter()
|
||||
.map(|s| &s.realized_cap.all.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.realized_cap.sth.height.compute_sum_of_others(
|
||||
max_from,
|
||||
&sources.iter().map(|s| &s.realized_cap.sth.height).collect::<Vec<_>>(),
|
||||
&sources
|
||||
.iter()
|
||||
.map(|s| &s.realized_cap.sth.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -259,7 +273,7 @@ impl ProfitabilityMetrics {
|
||||
ProfitabilityBucket::forced_import(db, name, version, indexes, cached_starts)
|
||||
})?;
|
||||
|
||||
let aggregate_version = version + Version::ONE;
|
||||
let aggregate_version = version + Version::TWO;
|
||||
|
||||
let profit = Profit::try_new(|name| {
|
||||
ProfitabilityBucket::forced_import(db, name, aggregate_version, indexes, cached_starts)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Dollars, Height, Indexes, StoredF64, Version};
|
||||
use brk_types::{
|
||||
BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Dollars, Height, Indexes, StoredF64, Version,
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{
|
||||
AnyStoredVec, Exit, LazyVecFrom1, ReadableCloneableVec, ReadableVec, Rw, StorageMode,
|
||||
@@ -42,7 +44,8 @@ pub struct RealizedCore<M: StorageMode = Rw> {
|
||||
|
||||
#[traversable(wrap = "loss", rename = "negative")]
|
||||
pub neg_loss: NegRealizedLoss,
|
||||
pub net_pnl: FiatPerBlockCumulativeWithSumsAndDeltas<CentsSigned, CentsSigned, BasisPointsSigned32, M>,
|
||||
pub net_pnl:
|
||||
FiatPerBlockCumulativeWithSumsAndDeltas<CentsSigned, CentsSigned, BasisPointsSigned32, M>,
|
||||
pub sopr: RealizedSoprCore<M>,
|
||||
}
|
||||
|
||||
@@ -107,7 +110,10 @@ impl RealizedCore {
|
||||
#[inline(always)]
|
||||
pub(crate) fn push_state(&mut self, state: &CohortState<impl RealizedOps, impl CostBasisOps>) {
|
||||
self.minimal.push_state(state);
|
||||
self.sopr.value_destroyed.block.push(state.realized.value_destroyed());
|
||||
self.sopr
|
||||
.value_destroyed
|
||||
.block
|
||||
.push(state.realized.value_destroyed());
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
@@ -135,8 +141,7 @@ impl RealizedCore {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.minimal
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
self.minimal.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.sopr
|
||||
.value_destroyed
|
||||
@@ -169,8 +174,7 @@ impl RealizedCore {
|
||||
self.minimal
|
||||
.compute_rest_part2(prices, starting_indexes, height_to_supply, exit)?;
|
||||
|
||||
self.net_pnl
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.net_pnl.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
self.sopr
|
||||
.ratio
|
||||
|
||||
@@ -178,7 +178,8 @@ impl RealizedFull {
|
||||
.push(state.realized.investor_cap_raw());
|
||||
self.peak_regret
|
||||
.value
|
||||
.block.cents
|
||||
.block
|
||||
.cents
|
||||
.push(state.realized.peak_regret());
|
||||
}
|
||||
|
||||
@@ -218,10 +219,7 @@ impl RealizedFull {
|
||||
};
|
||||
self.investor.price.cents.height.push(investor_price);
|
||||
|
||||
self.peak_regret
|
||||
.value
|
||||
.block.cents
|
||||
.push(accum.peak_regret());
|
||||
self.peak_regret.value.block.cents.push(accum.peak_regret());
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
BasisPoints32, BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Height, Indexes, Sats, StoredF32,
|
||||
Version,
|
||||
};
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, Exit, ReadableVec, Rw, StorageMode, WritableVec,
|
||||
BasisPoints32, BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Height, Indexes, Sats,
|
||||
StoredF32, Version,
|
||||
};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableVec, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::state::{CohortState, CostBasisOps, RealizedOps},
|
||||
internal::{
|
||||
FiatPerBlockCumulativeWithSums,
|
||||
FiatPerBlockWithDeltas, Identity, LazyPerBlock, PriceWithRatioPerBlock,
|
||||
FiatPerBlockCumulativeWithSums, FiatPerBlockWithDeltas, Identity, LazyPerBlock,
|
||||
PriceWithRatioPerBlock,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -111,23 +109,24 @@ impl RealizedMinimal {
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let cap = &self.cap.cents.height;
|
||||
self.price.compute_all(prices, starting_indexes, exit, |v| {
|
||||
Ok(v.compute_transform2(
|
||||
starting_indexes.height,
|
||||
cap,
|
||||
height_to_supply,
|
||||
|(i, cap_cents, supply, ..)| {
|
||||
let cap = cap_cents.as_u128();
|
||||
let supply_sats = Sats::from(supply).as_u128();
|
||||
if supply_sats == 0 {
|
||||
(i, Cents::ZERO)
|
||||
} else {
|
||||
(i, Cents::from(cap * Sats::ONE_BTC_U128 / supply_sats))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)?)
|
||||
})?;
|
||||
self.price
|
||||
.compute_all(prices, starting_indexes, exit, |v| {
|
||||
Ok(v.compute_transform2(
|
||||
starting_indexes.height,
|
||||
cap,
|
||||
height_to_supply,
|
||||
|(i, cap_cents, supply, ..)| {
|
||||
let cap = cap_cents.as_u128();
|
||||
let supply_sats = Sats::from(supply).as_u128();
|
||||
if supply_sats == 0 {
|
||||
(i, Cents::ZERO)
|
||||
} else {
|
||||
(i, Cents::from(cap * Sats::ONE_BTC_U128 / supply_sats))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)?)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ mod core;
|
||||
mod full;
|
||||
mod minimal;
|
||||
|
||||
pub use adjusted::AdjustedSopr;
|
||||
pub use self::core::RealizedCore;
|
||||
pub use adjusted::AdjustedSopr;
|
||||
pub use full::{RealizedFull, RealizedFullAccum};
|
||||
pub use minimal::RealizedMinimal;
|
||||
|
||||
@@ -12,7 +12,7 @@ use brk_error::Result;
|
||||
use brk_types::Indexes;
|
||||
use vecdb::Exit;
|
||||
|
||||
use crate::distribution::state::{WithCapital, CohortState, CostBasisData, RealizedState};
|
||||
use crate::distribution::state::{CohortState, CostBasisData, RealizedState, WithCapital};
|
||||
|
||||
pub trait RealizedLike: Send + Sync {
|
||||
fn as_core(&self) -> &RealizedCore;
|
||||
@@ -29,9 +29,15 @@ pub trait RealizedLike: Send + Sync {
|
||||
}
|
||||
|
||||
impl RealizedLike for RealizedCore {
|
||||
fn as_core(&self) -> &RealizedCore { self }
|
||||
fn as_core_mut(&mut self) -> &mut RealizedCore { self }
|
||||
fn min_stateful_len(&self) -> usize { self.min_stateful_len() }
|
||||
fn as_core(&self) -> &RealizedCore {
|
||||
self
|
||||
}
|
||||
fn as_core_mut(&mut self) -> &mut RealizedCore {
|
||||
self
|
||||
}
|
||||
fn min_stateful_len(&self) -> usize {
|
||||
self.min_stateful_len()
|
||||
}
|
||||
#[inline(always)]
|
||||
fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) {
|
||||
self.push_state(state)
|
||||
@@ -39,15 +45,26 @@ impl RealizedLike for RealizedCore {
|
||||
fn compute_rest_part1(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(starting_indexes, exit)
|
||||
}
|
||||
fn compute_from_stateful(&mut self, starting_indexes: &Indexes, others: &[&RealizedCore], exit: &Exit) -> Result<()> {
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&RealizedCore],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_from_stateful(starting_indexes, others, exit)
|
||||
}
|
||||
}
|
||||
|
||||
impl RealizedLike for RealizedFull {
|
||||
fn as_core(&self) -> &RealizedCore { &self.core }
|
||||
fn as_core_mut(&mut self) -> &mut RealizedCore { &mut self.core }
|
||||
fn min_stateful_len(&self) -> usize { self.min_stateful_len() }
|
||||
fn as_core(&self) -> &RealizedCore {
|
||||
&self.core
|
||||
}
|
||||
fn as_core_mut(&mut self) -> &mut RealizedCore {
|
||||
&mut self.core
|
||||
}
|
||||
fn min_stateful_len(&self) -> usize {
|
||||
self.min_stateful_len()
|
||||
}
|
||||
#[inline(always)]
|
||||
fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) {
|
||||
self.push_state(state)
|
||||
@@ -55,7 +72,12 @@ impl RealizedLike for RealizedFull {
|
||||
fn compute_rest_part1(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(starting_indexes, exit)
|
||||
}
|
||||
fn compute_from_stateful(&mut self, starting_indexes: &Indexes, others: &[&RealizedCore], exit: &Exit) -> Result<()> {
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&RealizedCore],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_from_stateful(starting_indexes, others, exit)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@ impl RelativeExtendedOwnMarketCap {
|
||||
let v2 = Version::new(2);
|
||||
|
||||
Ok(Self {
|
||||
unrealized_profit_to_own_mcap: cfg
|
||||
.import("unrealized_profit_to_own_mcap", v2)?,
|
||||
unrealized_profit_to_own_mcap: cfg.import("unrealized_profit_to_own_mcap", v2)?,
|
||||
unrealized_loss_to_own_mcap: cfg
|
||||
.import("unrealized_loss_to_own_mcap", Version::new(3))?,
|
||||
net_unrealized_pnl_to_own_mcap: cfg
|
||||
|
||||
@@ -16,7 +16,6 @@ pub struct RelativeExtendedOwnPnl<M: StorageMode = Rw> {
|
||||
pub unrealized_loss_to_own_gross_pnl: PercentPerBlock<BasisPoints16, M>,
|
||||
#[traversable(wrap = "unrealized/net_pnl", rename = "to_own_gross_pnl")]
|
||||
pub net_unrealized_pnl_to_own_gross_pnl: PercentPerBlock<BasisPointsSigned32, M>,
|
||||
|
||||
}
|
||||
|
||||
impl RelativeExtendedOwnPnl {
|
||||
@@ -26,8 +25,7 @@ impl RelativeExtendedOwnPnl {
|
||||
Ok(Self {
|
||||
unrealized_profit_to_own_gross_pnl: cfg
|
||||
.import("unrealized_profit_to_own_gross_pnl", v1)?,
|
||||
unrealized_loss_to_own_gross_pnl: cfg
|
||||
.import("unrealized_loss_to_own_gross_pnl", v1)?,
|
||||
unrealized_loss_to_own_gross_pnl: cfg.import("unrealized_loss_to_own_gross_pnl", v1)?,
|
||||
net_unrealized_pnl_to_own_gross_pnl: cfg
|
||||
.import("net_unrealized_pnl_to_own_gross_pnl", Version::new(3))?,
|
||||
})
|
||||
|
||||
@@ -6,7 +6,7 @@ use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, SupplyCore, UnrealizedFull};
|
||||
|
||||
use super::{RelativeFull, RelativeExtendedOwnPnl};
|
||||
use super::{RelativeExtendedOwnPnl, RelativeFull};
|
||||
|
||||
/// Relative metrics for the "all" cohort (base + own_pnl, NO rel_to_all).
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
@@ -35,15 +35,14 @@ impl RelativeForAll {
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.base.compute(
|
||||
self.base
|
||||
.compute(max_from, supply, &unrealized.inner.basic, market_cap, exit)?;
|
||||
self.extended_own_pnl.compute(
|
||||
max_from,
|
||||
supply,
|
||||
&unrealized.inner.basic,
|
||||
market_cap,
|
||||
&unrealized.inner,
|
||||
&unrealized.gross_pnl.usd.height,
|
||||
exit,
|
||||
)?;
|
||||
self.extended_own_pnl
|
||||
.compute(max_from, &unrealized.inner, &unrealized.gross_pnl.usd.height, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,13 +28,10 @@ impl RelativeFull {
|
||||
let v2 = Version::new(2);
|
||||
|
||||
Ok(Self {
|
||||
supply_in_profit_to_own: cfg
|
||||
.import("supply_in_profit_to_own", v1)?,
|
||||
supply_in_profit_to_own: cfg.import("supply_in_profit_to_own", v1)?,
|
||||
supply_in_loss_to_own: cfg.import("supply_in_loss_to_own", v1)?,
|
||||
unrealized_profit_to_mcap: cfg
|
||||
.import("unrealized_profit_to_mcap", v2)?,
|
||||
unrealized_loss_to_mcap: cfg
|
||||
.import("unrealized_loss_to_mcap", v2)?,
|
||||
unrealized_profit_to_mcap: cfg.import("unrealized_profit_to_mcap", v2)?,
|
||||
unrealized_loss_to_mcap: cfg.import("unrealized_loss_to_mcap", v2)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user