Compare commits

..

17 Commits

Author SHA1 Message Date
nym21 3d8b33ae94 release: v0.0.96 2025-09-03 18:21:17 +02:00
nym21 565ecbd436 cargo: update 2025-09-03 18:20:58 +02:00
nym21 3359dfcc29 global: snapshot 2025-09-03 18:17:25 +02:00
nym21 1c2afd14dd global: fixes of Parser::new 2025-09-01 20:34:27 +02:00
nym21 fe5343c1d6 global: tiny snapshot 2025-09-01 20:21:51 +02:00
nym21 08cfefc02a zed: add project settings to improve search 2025-08-31 17:05:28 +02:00
nym21 f6d9332c48 bitview: fix screenshot in ios 2025-08-31 16:17:50 +02:00
nym21 cc6913c854 bitview: initial history support 2025-08-31 14:50:36 +02:00
nym21 8c75fbd0a4 server: fix urls in readme 2025-08-31 12:21:11 +02:00
nym21 0de6d62409 bitview: simplify options tree 2025-08-31 11:07:54 +02:00
nym21 5ba7ce5b7c bitview: small fixes 2025-08-30 12:11:15 +02:00
nym21 e106d30852 global: snapshot 2025-08-29 22:49:26 +02:00
nym21 30affc884b release: v0.0.95 2025-08-28 12:43:49 +02:00
nym21 745717ea49 global: added unrealized relative datasets 2025-08-28 12:43:28 +02:00
nym21 4efd98b758 release: v0.0.94 2025-08-28 00:31:36 +02:00
nym21 36640e3710 global: added datasets 2025-08-28 00:31:14 +02:00
nym21 311c4fd29d website: rename default to bitview 2025-08-27 11:52:22 +02:00
172 changed files with 5717 additions and 9911 deletions
+1 -4
View File
@@ -5,6 +5,7 @@
target
websites/dist
vecid-to-indexes.js
/ids.txt
# Copies
*\ copy*
@@ -12,10 +13,6 @@ vecid-to-indexes.js
# Ignored
_*
# Editors
.vscode
.zed
# Logs
.log
+20
View File
@@ -0,0 +1,20 @@
{
"file_scan_exclusions": [
// default
"**/.git",
"**/.svn",
"**/.hg",
"**/.jj",
"**/CVS",
"**/.DS_Store",
"**/Thumbs.db",
"**/.classpath",
"**/.settings",
// custom
"**/lean-qr/*/index.mjs",
"uFuzzy.mjs",
"lightweight-charts.standalone.production.mjs",
"**/modern-screenshot/*/index.mjs",
"**/solidjs-signals/*/dist/prod.js"
]
}
Generated
+109 -125
View File
@@ -166,20 +166,15 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "async-compression"
version = "0.4.28"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6448dfb3960f0b038e88c781ead1e7eb7929dfc3a71a1336ec9086c00f6d1e75"
checksum = "977eb15ea9efd848bb8a4a1a2500347ed7f0bf794edf0dc3ddcf439f43d36b23"
dependencies = [
"brotli",
"compression-codecs",
"compression-core",
"flate2",
"futures-core",
"memchr",
"pin-project-lite",
"tokio",
"zstd",
"zstd-safe",
]
[[package]]
@@ -456,9 +451,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.9.3"
version = "2.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
dependencies = [
"serde",
]
@@ -487,7 +482,7 @@ dependencies = [
[[package]]
name = "brk"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"brk_bundler",
"brk_cli",
@@ -506,7 +501,7 @@ dependencies = [
[[package]]
name = "brk_bundler"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"brk_rolldown",
"log",
@@ -517,7 +512,7 @@ dependencies = [
[[package]]
name = "brk_cli"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"bitcoincore-rpc",
"brk_bundler",
@@ -542,7 +537,7 @@ dependencies = [
[[package]]
name = "brk_computer"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"bitcoin",
"bitcoincore-rpc",
@@ -564,7 +559,7 @@ dependencies = [
[[package]]
name = "brk_error"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"bitcoincore-rpc",
"fjall",
@@ -577,7 +572,7 @@ dependencies = [
[[package]]
name = "brk_fetcher"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"brk_error",
"brk_logger",
@@ -589,7 +584,7 @@ dependencies = [
[[package]]
name = "brk_indexer"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"bitcoin",
"bitcoincore-rpc",
@@ -606,13 +601,14 @@ dependencies = [
[[package]]
name = "brk_interface"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"brk_computer",
"brk_error",
"brk_indexer",
"brk_structs",
"derive_deref",
"nucleo-matcher",
"schemars 1.0.4",
"serde",
"serde_json",
@@ -623,7 +619,7 @@ dependencies = [
[[package]]
name = "brk_logger"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"env_logger",
"jiff",
@@ -633,7 +629,7 @@ dependencies = [
[[package]]
name = "brk_mcp"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"axum",
"brk_interface",
@@ -643,7 +639,7 @@ dependencies = [
[[package]]
name = "brk_parser"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"bitcoin",
"bitcoincore-rpc",
@@ -708,7 +704,7 @@ dependencies = [
"anyhow",
"append-only-vec",
"arcstr",
"bitflags 2.9.3",
"bitflags 2.9.4",
"brk_rolldown_common",
"brk_rolldown_debug",
"brk_rolldown_ecmascript",
@@ -757,7 +753,7 @@ checksum = "23cd66173b33436aaec126f64e8f1d0938539d2eb934e88c633cf6181f7e4c53"
dependencies = [
"anyhow",
"arcstr",
"bitflags 2.9.3",
"bitflags 2.9.4",
"brk_rolldown_ecmascript",
"brk_rolldown_error",
"brk_rolldown_fs",
@@ -839,7 +835,7 @@ checksum = "9fd007c612609bcf46e3dca4f9f3c79d16dc1f0bdf7cd0047bfe752fbc6fbecc"
dependencies = [
"anyhow",
"arcstr",
"bitflags 2.9.3",
"bitflags 2.9.4",
"brk_rolldown_utils",
"derive_more",
"heck",
@@ -870,7 +866,7 @@ dependencies = [
"anyhow",
"arcstr",
"async-trait",
"bitflags 2.9.3",
"bitflags 2.9.4",
"brk_rolldown_common",
"brk_rolldown_debug",
"brk_rolldown_ecmascript",
@@ -1021,7 +1017,7 @@ dependencies = [
[[package]]
name = "brk_server"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"axum",
"bitcoincore-rpc",
@@ -1045,7 +1041,7 @@ dependencies = [
[[package]]
name = "brk_store"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"brk_error",
"brk_structs",
@@ -1068,7 +1064,7 @@ dependencies = [
[[package]]
name = "brk_structs"
version = "0.0.93"
version = "0.0.96"
dependencies = [
"bitcoin",
"bitcoincore-rpc",
@@ -1149,10 +1145,11 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.34"
version = "1.2.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc"
checksum = "590f9024a68a8c40351881787f1934dc11afd69090f5edb6831464694d836ea3"
dependencies = [
"find-msvc-tools",
"jobserver",
"libc",
"shlex",
@@ -1198,18 +1195,18 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.46"
version = "4.5.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57"
checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.5.46"
version = "4.5.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41"
checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6"
dependencies = [
"anstream",
"anstyle",
@@ -1219,9 +1216,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.45"
version = "4.5.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c"
dependencies = [
"heck",
"proc-macro2",
@@ -1306,25 +1303,23 @@ checksum = "ea0095f6103c2a8b44acd6fd15960c801dafebf02e21940360833e0673f48ba7"
[[package]]
name = "compression-codecs"
version = "0.4.28"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46cc6539bf1c592cff488b9f253b30bc0ec50d15407c2cf45e27bd8f308d5905"
checksum = "485abf41ac0c8047c07c87c72c8fb3eb5197f6e9d7ded615dfd1a00ae00a0f64"
dependencies = [
"brotli",
"compression-core",
"flate2",
"futures-core",
"memchr",
"pin-project-lite",
"zstd",
"zstd-safe",
]
[[package]]
name = "compression-core"
version = "0.4.28"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2957e823c15bde7ecf1e8b64e537aa03a6be5fda0e2334e99887669e75b12e01"
checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb"
[[package]]
name = "concurrent_lru"
@@ -1558,9 +1553,9 @@ dependencies = [
[[package]]
name = "deranged"
version = "0.4.0"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc"
dependencies = [
"powerfmt",
"serde",
@@ -1771,6 +1766,12 @@ dependencies = [
"windows-sys 0.60.2",
]
[[package]]
name = "find-msvc-tools"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e178e4fba8a2726903f6ba98a6d221e76f9c12c650d5dc0e6afdc50677b49650"
[[package]]
name = "fixedbitset"
version = "0.5.7"
@@ -1954,7 +1955,7 @@ dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasi 0.14.2+wasi-0.2.4",
"wasi 0.14.3+wasi-0.2.4",
]
[[package]]
@@ -2292,7 +2293,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"inotify-sys",
"libc",
]
@@ -2321,7 +2322,7 @@ version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"cfg-if",
"libc",
]
@@ -2467,16 +2468,16 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"libc",
"redox_syscall",
]
[[package]]
name = "libz-rs-sys"
version = "0.5.1"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "172a788537a2221661b480fee8dc5f96c580eb34fa88764d3205dc356c7e4221"
checksum = "840db8cf39d9ec4dd794376f38acc40d0fc65eec2a8f484f7fd375b84602becd"
dependencies = [
"zlib-rs",
]
@@ -2616,7 +2617,7 @@ version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"cfg-if",
"cfg_aliases",
"libc",
@@ -2643,7 +2644,7 @@ version = "8.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"fsevent-sys",
"inotify",
"kqueue",
@@ -2663,12 +2664,21 @@ checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d"
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
version = "0.50.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399"
dependencies = [
"overload",
"winapi",
"windows-sys 0.52.0",
]
[[package]]
name = "nucleo-matcher"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf33f538733d1a5a3494b836ba913207f14d9d4a1d3cd67030c5061bdd2cac85"
dependencies = [
"memchr",
"unicode-segmentation",
]
[[package]]
@@ -2732,12 +2742,6 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "owo-colors"
version = "4.2.2"
@@ -2830,7 +2834,7 @@ version = "0.81.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989b81258ce151e23adee6f1393f7c0fb7e10e3a6c6c001f71bbaff4081c72a4"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"oxc_allocator",
"oxc_ast_macros",
"oxc_data_structures",
@@ -2871,7 +2875,7 @@ version = "0.81.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5361ef66f38635d9671596d83abf44bcdbc3e39dbff303f3517828b86ad60e8f"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"itertools",
"nonmax",
"oxc_index",
@@ -2886,7 +2890,7 @@ version = "0.81.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fde8fc6f7337632fce3e9e51c150f57fb0ef234524c6947f63e8009e1ea613cf"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"cow-utils",
"dragonbox_ecma",
"nonmax",
@@ -2964,7 +2968,7 @@ version = "0.81.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83d8c311d64fa0bf8cab1bde3f7760cd828e71ed483ca0878799f1f72542cb4d"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"oxc_allocator",
"oxc_ast",
"oxc_ast_visit",
@@ -3019,7 +3023,7 @@ version = "0.81.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70253728183a5a92d1ba964d9952201e0269ebd07c4917c4553283d564225bab"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"cow-utils",
"memchr",
"num-bigint",
@@ -3042,7 +3046,7 @@ version = "0.81.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de5bb2ed6646bb7815126e0f36787c349e13561fed2c05f95b27a1f82dd066c4"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"oxc_allocator",
"oxc_ast_macros",
"oxc_diagnostics",
@@ -3127,7 +3131,7 @@ version = "0.81.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72d9d80d47d2eee5c1e6dbcdf1841b42afc4f1cd1f63701fc346162616dac52f"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"cow-utils",
"dragonbox_ecma",
"nonmax",
@@ -3442,9 +3446,9 @@ dependencies = [
[[package]]
name = "potential_utf"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a"
dependencies = [
"zerovec",
]
@@ -3635,7 +3639,7 @@ version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
]
[[package]]
@@ -3749,7 +3753,7 @@ version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
"errno",
"libc",
"linux-raw-sys",
@@ -3898,9 +3902,9 @@ checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc"
[[package]]
name = "seqdb"
version = "0.2.5"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c54ab988c96efa9d275ca2b12bf2d3c6adec993b8e82ea31a88c984abdaa14fa"
checksum = "ade192d6f8a1e58c43428c8e194016124f20744f75cb14e2fcc0c79309fe4f91"
dependencies = [
"libc",
"log",
@@ -4304,12 +4308,11 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.41"
version = "0.3.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031"
dependencies = [
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde",
@@ -4319,15 +4322,15 @@ dependencies = [
[[package]]
name = "time-core"
version = "0.1.4"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
[[package]]
name = "time-macros"
version = "0.2.22"
version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
dependencies = [
"num-conv",
"time-core",
@@ -4458,7 +4461,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
dependencies = [
"async-compression",
"bitflags 2.9.3",
"bitflags 2.9.4",
"bytes",
"futures-core",
"http",
@@ -4560,9 +4563,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
version = "0.3.19"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
dependencies = [
"nu-ansi-term",
"serde",
@@ -4630,6 +4633,12 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
[[package]]
name = "unicode-segmentation"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "unicode-width"
version = "0.2.1"
@@ -4686,9 +4695,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.18.0"
version = "1.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
dependencies = [
"getrandom 0.3.3",
"js-sys",
@@ -4726,9 +4735,9 @@ checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23"
[[package]]
name = "vecdb"
version = "0.2.5"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e5c4ec34c376be3a41435eeb7672d0ea0e9c1d60c5d1d90218912588f91abea"
checksum = "5c3e103eeb634851690d815a886ba8fe1ab21d2f520d915c411979bc76de8419"
dependencies = [
"ctrlc",
"log",
@@ -4746,9 +4755,9 @@ dependencies = [
[[package]]
name = "vecdb_derive"
version = "0.2.5"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "778c4874c05822465e28cae6a7dead593a73124ec80afb85b85adae5ac883368"
checksum = "6bdf71ae8eeaf2f187cee599e8e34a49bf6fd0536977bd009d94be35e3801754"
dependencies = [
"quote",
"syn 2.0.106",
@@ -4799,11 +4808,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasi"
version = "0.14.2+wasi-0.2.4"
version = "0.14.3+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95"
dependencies = [
"wit-bindgen-rt",
"wit-bindgen",
]
[[package]]
@@ -4870,22 +4879,6 @@ version = "0.25.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.10"
@@ -4895,12 +4888,6 @@ dependencies = [
"windows-sys 0.60.2",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.61.2"
@@ -5123,13 +5110,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
name = "wit-bindgen"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
dependencies = [
"bitflags 2.9.3",
]
checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814"
[[package]]
name = "writeable"
@@ -5249,9 +5233,9 @@ dependencies = [
[[package]]
name = "zip"
version = "4.5.0"
version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8835eb39822904d39cb19465de1159e05d371973f0c6df3a365ad50565ddc8b9"
checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1"
dependencies = [
"arbitrary",
"crc32fast",
@@ -5263,9 +5247,9 @@ dependencies = [
[[package]]
name = "zlib-rs"
version = "0.5.1"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a"
checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2"
[[package]]
name = "zopfli"
+15 -15
View File
@@ -4,7 +4,7 @@ members = ["crates/*"]
package.description = "The Bitcoin Research Kit is a suite of tools designed to extract, compute and display data stored on a Bitcoin Core node"
package.license = "MIT"
package.edition = "2024"
package.version = "0.0.93"
package.version = "0.0.96"
package.homepage = "https://bitcoinresearchkit.org"
package.repository = "https://github.com/bitcoinresearchkit/brk"
package.readme = "README.md"
@@ -26,19 +26,19 @@ inherits = "release"
axum = "0.8.4"
bitcoin = { version = "0.32.7", features = ["serde"] }
bitcoincore-rpc = "0.19.0"
brk_bundler = { version = "0.0.93", path = "crates/brk_bundler" }
brk_cli = { version = "0.0.93", path = "crates/brk_cli" }
brk_computer = { version = "0.0.93", path = "crates/brk_computer" }
brk_error = { version = "0.0.93", path = "crates/brk_error" }
brk_fetcher = { version = "0.0.93", path = "crates/brk_fetcher" }
brk_indexer = { version = "0.0.93", path = "crates/brk_indexer" }
brk_interface = { version = "0.0.93", path = "crates/brk_interface" }
brk_logger = { version = "0.0.93", path = "crates/brk_logger" }
brk_mcp = { version = "0.0.93", path = "crates/brk_mcp" }
brk_parser = { version = "0.0.93", path = "crates/brk_parser" }
brk_server = { version = "0.0.93", path = "crates/brk_server" }
brk_store = { version = "0.0.93", path = "crates/brk_store" }
brk_structs = { version = "0.0.93", path = "crates/brk_structs" }
brk_bundler = { version = "0.0.96", path = "crates/brk_bundler" }
brk_cli = { version = "0.0.96", path = "crates/brk_cli" }
brk_computer = { version = "0.0.96", path = "crates/brk_computer" }
brk_error = { version = "0.0.96", path = "crates/brk_error" }
brk_fetcher = { version = "0.0.96", path = "crates/brk_fetcher" }
brk_indexer = { version = "0.0.96", path = "crates/brk_indexer" }
brk_interface = { version = "0.0.96", path = "crates/brk_interface" }
brk_logger = { version = "0.0.96", path = "crates/brk_logger" }
brk_mcp = { version = "0.0.96", path = "crates/brk_mcp" }
brk_parser = { version = "0.0.96", path = "crates/brk_parser" }
brk_server = { version = "0.0.96", path = "crates/brk_server" }
brk_store = { version = "0.0.96", path = "crates/brk_store" }
brk_structs = { version = "0.0.96", path = "crates/brk_structs" }
byteview = "=0.6.1"
derive_deref = "1.1.1"
fjall = "2.11.2"
@@ -53,7 +53,7 @@ serde_derive = "1.0.219"
serde_json = { version = "1.0.143", features = ["float_roundtrip"] }
tokio = { version = "1.47.1", features = ["rt-multi-thread"] }
# vecdb = { path = "../seqdb/crates/vecdb", features = ["derive"]}
vecdb = { version = "0.2.5", features = ["derive"]}
vecdb = { version = "0.2.9", features = ["derive"]}
zerocopy = "0.8.26"
zerocopy-derive = "0.8.26"
+4 -9
View File
@@ -17,7 +17,7 @@
<a href="https://deps.rs/crate/brk">
<img src="https://deps.rs/crate/brk/latest/status.svg" alt="Dependency status">
</a>
<a href="https://discord.gg/HaR3wpH3nr">
<a href="https://discord.gg/WACpShCB7M">
<img src="https://img.shields.io/discord/1350431684562124850?label=discord" alt="Discord" />
</a>
<a href="https://primal.net/p/nprofile1qqsfw5dacngjlahye34krvgz7u0yghhjgk7gxzl5ptm9v6n2y3sn03sqxu2e6">
@@ -31,10 +31,9 @@ In other words it's an alternative to [Glassnode](https://glassnode.com), [mempo
The toolkit can be used in various ways to accommodate as many needs as possible:
- **[Website](https://bitcoinresearchkit.org)** \
- **[Website](https://bitview.space)** \
Everyone is welcome to visit the official instance and showcase of the suite's capabilities. \
It has a wide range of functionalities including charts, tables and simulations which you can visit for free and without the need for an account. \
Also available at: [brekit.org](https://brekit.org) // [kibo.money](https://kibo.money) // [satonomics.xyz](https://satonomics.xyz)
It has a wide range of functionalities including charts, tables and simulations which you can visit for free and without the need for an account.
- **[API](https://github.com/bitcoinresearchkit/brk/tree/main/crates/brk_server#brk-server)** \
Researchers and developers are free to use BRK's public API with ![Datasets variant count](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fbitcoinresearchkit.org%2Fapi%2Fvecs%2Fvec-count&query=%24&style=flat&label=%20&color=white) dataset variants at their disposal. \
Just like the website, it's entirely free, with no authentication or rate-limiting.
@@ -62,7 +61,7 @@ If you'd like to have your own instance hosted for you please contact [hosting@b
- Updates delivered at your convenience
- Direct communication for feature requests and support
- Bitcoin Core or Knots with desired version
- Optional subdomains: `*.bitcoinresearchkit.org`, `*.brekit.org`, `*.kibo.money` and `*.satonomics.xyz`
- Optional subdomains
- Logo featured in the Readme if desired
Pricing: `0.01 BTC / month` *or* `0.1 BTC / year`
@@ -93,7 +92,3 @@ Heartfelt thanks go out to every donor on [Nostr](https://primal.net/p/npub1jagm
## Donate
[`bc1q09 8zsm89 m7kgyz e338vf ejhpdt 92ua9p 3peuve`](bitcoin:bc1q098zsm89m7kgyze338vfejhpdt92ua9p3peuve)
[`lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkxmmww3jkuar8d35kgetj8yuq363hv4`](lightning:lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkxmmww3jkuar8d35kgetj8yuq363hv4)
[Geyser Fund](https://geyser.fund/project/brk)
+1 -1
View File
@@ -12,7 +12,7 @@
- **add rollback of states (in stateful)**
- add costs basis by percentile (percentile cost basis) back
- add support for per index computation
- fix min feerate which is always ZERO due to coinbase transaction
- fix min fee_rate which is always ZERO due to coinbase transaction
- before computing multiple sources check their length, panic if not equal
- add oracle price dataset (https://utxo.live/oracle/UTXOracle.py)
- add address counts relative to all datasets
+7 -7
View File
@@ -64,7 +64,7 @@ brk = { version = "0.0.88", features = ["parser", "indexer", "computer"] }
use brk::{parser, indexer, computer};
// Core data pipeline only
let parser = parser::Parser::new(blocks_dir, output_dir, rpc);
let parser = parser::Parser::new(blocks_dir, Some(output_dir), rpc);
let mut indexer = indexer::Indexer::forced_import(output_dir)?;
let mut computer = computer::Computer::forced_import(output_dir, &indexer, None)?;
```
@@ -81,7 +81,7 @@ use brk::{structs, parser};
// Just parsing and types
let height = structs::Height::new(800_000);
let parser = parser::Parser::new(blocks_dir, output_dir, rpc);
let parser = parser::Parser::new(blocks_dir, Some(output_dir), rpc);
```
## Feature Flags
@@ -113,7 +113,7 @@ use brk::*;
// Full data pipeline setup
let config = cli::Config::load()?;
let rpc = /* Bitcoin Core RPC client */;
let parser = parser::Parser::new(config.blocks_dir, config.output_dir, rpc);
let parser = parser::Parser::new(config.blocks_dir, Some(config.output_dir), rpc);
let mut indexer = indexer::Indexer::forced_import(&config.output_dir)?;
let mut computer = computer::Computer::forced_import(&config.output_dir, &indexer, None)?;
let interface = interface::Interface::build(&indexer, &computer);
@@ -152,15 +152,15 @@ use brk::{structs, parser, error};
// Custom application with BRK components
fn analyze_blocks() -> error::Result<()> {
let parser = parser::Parser::new(blocks_dir, output_dir, rpc);
let parser = parser::Parser::new(blocks_dir, Some(output_dir), rpc);
parser.parse(None, None)
.iter()
.take(1000) // First 1000 blocks
.for_each(|(height, block, hash)| {
println!("Block {}: {} transactions", height, block.txdata.len());
});
Ok(())
}
```
@@ -194,4 +194,4 @@ For specific dependency information, see individual crate READMEs.
---
*This README was generated by Claude Code*
*This README was generated by Claude Code*
+3 -3
View File
@@ -20,15 +20,15 @@ brk_logger = { workspace = true }
brk_parser = { workspace = true }
brk_server = { workspace = true }
vecdb = { workspace = true }
clap = { version = "4.5.46", features = ["string"] }
clap_derive = "4.5.45"
clap = { version = "4.5.47", features = ["string"] }
clap_derive = "4.5.47"
color-eyre = "0.6.5"
log = { workspace = true }
minreq = { workspace = true }
serde = { workspace = true }
tokio = { workspace = true }
toml = "0.9.5"
zip = { version = "4.5.0", default-features = false, features = ["deflate"] }
zip = { version = "4.6.1", default-features = false, features = ["deflate"] }
[[bin]]
name = "brk"
+1 -1
View File
@@ -284,7 +284,7 @@ Finally, you can run the program with '-h' for help."
}
pub fn website(&self) -> Website {
self.website.unwrap_or(Website::Default)
self.website.unwrap_or(Website::Bitview)
}
pub fn fetch(&self) -> bool {
+2 -1
View File
@@ -13,6 +13,7 @@ use brk_bundler::bundle;
use brk_computer::Computer;
use brk_indexer::Indexer;
use brk_interface::Interface;
use brk_parser::Parser;
use brk_server::{Server, VERSION};
use log::info;
use vecdb::Exit;
@@ -46,7 +47,7 @@ pub fn run() -> color_eyre::Result<()> {
let exit = Exit::new();
exit.set_ctrlc_handler();
let parser = brk_parser::Parser::new(config.blocksdir(), config.brkdir(), rpc);
let parser = Parser::new(config.blocksdir(), Some(config.brkdir()), rpc);
let mut indexer = Indexer::forced_import(&config.brkdir())?;
+2 -2
View File
@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, ValueEnum)]
pub enum Website {
None,
Default,
Bitview,
Custom,
}
@@ -20,7 +20,7 @@ impl Website {
pub fn to_folder_name(self) -> &'static str {
match self {
Self::Custom => "custom",
Self::Default => "default",
Self::Bitview => "bitview",
Self::None => unreachable!(),
}
}
+5 -1
View File
@@ -34,7 +34,11 @@ pub fn main() -> Result<()> {
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
// let outputs_dir = Path::new("../../_outputs");
let parser = Parser::new(bitcoin_dir.join("blocks"), outputs_dir.to_path_buf(), rpc);
let parser = Parser::new(
bitcoin_dir.join("blocks"),
Some(outputs_dir.to_path_buf()),
rpc,
);
let mut indexer = Indexer::forced_import(&outputs_dir)?;
-264
View File
@@ -1,264 +0,0 @@
use std::path::Path;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_structs::{
CheckedSub, DifficultyEpoch, HalvingEpoch, Height, StoredU32, StoredU64, Timestamp, Version,
Weight,
};
use vecdb::{AnyCollectableVec, Database, EagerVec, Exit, PAGE_SIZE, VecIterator};
use crate::grouped::Source;
use super::{
Indexes,
grouped::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, VecBuilderOptions},
indexes,
};
const VERSION: Version = Version::ZERO;
#[derive(Clone)]
pub struct Vecs {
db: Database,
pub height_to_interval: EagerVec<Height, Timestamp>,
pub height_to_vbytes: EagerVec<Height, StoredU64>,
pub difficultyepoch_to_timestamp: EagerVec<DifficultyEpoch, Timestamp>,
pub halvingepoch_to_timestamp: EagerVec<HalvingEpoch, Timestamp>,
pub timeindexes_to_timestamp: ComputedVecsFromDateIndex<Timestamp>,
pub indexes_to_block_count: ComputedVecsFromHeight<StoredU32>,
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
pub indexes_to_block_size: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_block_vbytes: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_block_weight: ComputedVecsFromHeight<Weight>,
}
impl Vecs {
pub fn forced_import(parent: &Path, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let db = Database::open(&parent.join("blocks"))?;
db.set_min_len(PAGE_SIZE * 1_000_000)?;
Ok(Self {
height_to_interval: EagerVec::forced_import_compressed(
&db,
"interval",
version + VERSION + Version::ZERO,
)?,
timeindexes_to_timestamp: ComputedVecsFromDateIndex::forced_import(
&db,
"timestamp",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_first(),
)?,
indexes_to_block_interval: ComputedVecsFromHeight::forced_import(
&db,
"block_interval",
Source::None,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default()
.add_percentiles()
.add_minmax()
.add_average(),
)?,
indexes_to_block_count: ComputedVecsFromHeight::forced_import(
&db,
"block_count",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_sum().add_cumulative(),
)?,
indexes_to_block_weight: ComputedVecsFromHeight::forced_import(
&db,
"block_weight",
Source::None,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_sum().add_cumulative(),
)?,
indexes_to_block_size: ComputedVecsFromHeight::forced_import(
&db,
"block_size",
Source::None,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_sum().add_cumulative(),
)?,
height_to_vbytes: EagerVec::forced_import_compressed(
&db,
"vbytes",
version + VERSION + Version::ZERO,
)?,
indexes_to_block_vbytes: ComputedVecsFromHeight::forced_import(
&db,
"block_vbytes",
Source::None,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_sum().add_cumulative(),
)?,
difficultyepoch_to_timestamp: EagerVec::forced_import_compressed(
&db,
"timestamp",
version + VERSION + Version::ZERO,
)?,
halvingepoch_to_timestamp: EagerVec::forced_import_compressed(
&db,
"timestamp",
version + VERSION + Version::ZERO,
)?,
db,
})
}
pub fn compute(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.compute_(indexer, indexes, starting_indexes, exit)?;
self.db.flush_then_punch()?;
Ok(())
}
fn compute_(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.timeindexes_to_timestamp.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, indexes, starting_indexes, exit| {
vec.compute_transform(
starting_indexes.dateindex,
&indexes.dateindex_to_date,
|(di, d, ..)| (di, Timestamp::from(d)),
exit,
)?;
Ok(())
},
)?;
self.indexes_to_block_count.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, indexer, _, starting_indexes, exit| {
v.compute_range(
starting_indexes.height,
&indexer.vecs.height_to_weight,
|h| (h, StoredU32::from(1_u32)),
exit,
)?;
Ok(())
},
)?;
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
self.height_to_interval.compute_transform(
starting_indexes.height,
&indexer.vecs.height_to_timestamp,
|(height, timestamp, ..)| {
let interval = height.decremented().map_or(Timestamp::ZERO, |prev_h| {
let prev_timestamp = height_to_timestamp_iter.unwrap_get_inner(prev_h);
timestamp
.checked_sub(prev_timestamp)
.unwrap_or(Timestamp::ZERO)
});
(height, interval)
},
exit,
)?;
self.indexes_to_block_interval.compute_rest(
indexes,
starting_indexes,
exit,
Some(&self.height_to_interval),
)?;
self.indexes_to_block_weight.compute_rest(
indexes,
starting_indexes,
exit,
Some(&indexer.vecs.height_to_weight),
)?;
self.indexes_to_block_size.compute_rest(
indexes,
starting_indexes,
exit,
Some(&indexer.vecs.height_to_total_size),
)?;
self.height_to_vbytes.compute_transform(
starting_indexes.height,
&indexer.vecs.height_to_weight,
|(h, w, ..)| {
(
h,
StoredU64::from(bitcoin::Weight::from(w).to_vbytes_floor()),
)
},
exit,
)?;
self.indexes_to_block_vbytes.compute_rest(
indexes,
starting_indexes,
exit,
Some(&self.height_to_vbytes),
)?;
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
self.difficultyepoch_to_timestamp.compute_transform(
starting_indexes.difficultyepoch,
&indexes.difficultyepoch_to_first_height,
|(i, h, ..)| (i, height_to_timestamp_iter.unwrap_get_inner(h)),
exit,
)?;
self.halvingepoch_to_timestamp.compute_transform(
starting_indexes.halvingepoch,
&indexes.halvingepoch_to_first_height,
|(i, h, ..)| (i, height_to_timestamp_iter.unwrap_get_inner(h)),
exit,
)?;
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
vec![
&self.height_to_interval as &dyn AnyCollectableVec,
&self.height_to_vbytes,
&self.difficultyepoch_to_timestamp,
&self.halvingepoch_to_timestamp,
],
self.timeindexes_to_timestamp.vecs(),
self.indexes_to_block_count.vecs(),
self.indexes_to_block_interval.vecs(),
self.indexes_to_block_size.vecs(),
self.indexes_to_block_vbytes.vecs(),
self.indexes_to_block_weight.vecs(),
]
.into_iter()
.flatten()
.collect::<Vec<_>>()
}
}
@@ -3,8 +3,9 @@ use std::path::Path;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_structs::{
CheckedSub, Feerate, HalvingEpoch, Height, InputIndex, OutputIndex, Sats, StoredBool,
StoredU32, StoredU64, TxIndex, TxVersion, Version, Weight,
CheckedSub, Date, DateIndex, DifficultyEpoch, Dollars, FeeRate, HalvingEpoch, Height,
InputIndex, OutputIndex, Sats, StoredBool, StoredF32, StoredF64, StoredU32, StoredU64,
Timestamp, TxIndex, TxVersion, Version, Weight,
};
use vecdb::{
AnyCloneableIterableVec, AnyCollectableVec, AnyIterableVec, Database, EagerVec, Exit,
@@ -12,25 +13,37 @@ use vecdb::{
};
use crate::grouped::{
ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromHeight,
ComputedVecsFromTxindex, Source, VecBuilderOptions,
ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromDateIndex,
ComputedVecsFromHeight, ComputedVecsFromTxindex, Source, VecBuilderOptions,
};
use super::{Indexes, indexes, price};
const VERSION: Version = Version::ZERO;
const TARGET_BLOCKS_PER_DAY: f64 = 144.0;
#[derive(Clone)]
pub struct Vecs {
db: Database,
// pub txindex_to_is_v1: LazyVec<Txindex, bool>,
// pub txindex_to_is_v2: LazyVec<Txindex, bool>,
// pub txindex_to_is_v3: LazyVec<Txindex, bool>,
pub height_to_interval: EagerVec<Height, Timestamp>,
pub height_to_vbytes: EagerVec<Height, StoredU64>,
pub difficultyepoch_to_timestamp: EagerVec<DifficultyEpoch, Timestamp>,
pub halvingepoch_to_timestamp: EagerVec<HalvingEpoch, Timestamp>,
pub timeindexes_to_timestamp: ComputedVecsFromDateIndex<Timestamp>,
pub indexes_to_block_count: ComputedVecsFromHeight<StoredU32>,
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
pub indexes_to_block_size: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_block_vbytes: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_block_weight: ComputedVecsFromHeight<Weight>,
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
pub indexes_to_difficultyepoch: ComputedVecsFromDateIndex<DifficultyEpoch>,
pub indexes_to_halvingepoch: ComputedVecsFromDateIndex<HalvingEpoch>,
pub indexes_to_coinbase: ComputedValueVecsFromHeight,
pub indexes_to_emptyoutput_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_fee: ComputedValueVecsFromTxindex,
pub indexes_to_feerate: ComputedVecsFromTxindex<Feerate>,
pub indexes_to_fee_rate: ComputedVecsFromTxindex<FeeRate>,
/// Value == 0 when Coinbase
pub txindex_to_input_value:
LazyVecFrom3<TxIndex, Sats, TxIndex, InputIndex, TxIndex, StoredU64, InputIndex, Sats>,
@@ -65,8 +78,18 @@ pub struct Vecs {
pub txindex_to_vsize: LazyVecFrom1<TxIndex, StoredU64, TxIndex, Weight>,
pub txindex_to_weight: LazyVecFrom2<TxIndex, Weight, TxIndex, StoredU32, TxIndex, StoredU32>,
pub txindex_to_fee: EagerVec<TxIndex, Sats>,
pub txindex_to_feerate: EagerVec<TxIndex, Feerate>,
pub txindex_to_fee_rate: EagerVec<TxIndex, FeeRate>,
pub indexes_to_exact_utxo_count: ComputedVecsFromHeight<StoredU64>,
pub dateindex_to_fee_dominance: EagerVec<DateIndex, StoredF32>,
pub dateindex_to_subsidy_dominance: EagerVec<DateIndex, StoredF32>,
pub indexes_to_subsidy_usd_1y_sma: Option<ComputedVecsFromDateIndex<Dollars>>,
pub indexes_to_puell_multiple: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_hash_rate: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_hash_rate_1w_sma: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_hash_rate_1m_sma: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_hash_rate_2m_sma: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_hash_rate_1y_sma: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_difficulty_as_hash: ComputedVecsFromDateIndex<StoredF32>,
}
impl Vecs {
@@ -77,7 +100,7 @@ impl Vecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
) -> Result<Self> {
let db = Database::open(&parent.join("transactions"))?;
let db = Database::open(&parent.join("chain"))?;
db.set_min_len(PAGE_SIZE * 10_000_000)?;
let compute_dollars = price.is_some();
@@ -262,10 +285,131 @@ impl Vecs {
let txindex_to_fee =
EagerVec::forced_import_compressed(&db, "fee", version + VERSION + Version::ZERO)?;
let txindex_to_feerate =
EagerVec::forced_import_compressed(&db, "feerate", version + VERSION + Version::ZERO)?;
let txindex_to_fee_rate =
EagerVec::forced_import_compressed(&db, "fee_rate", version + VERSION + Version::ZERO)?;
Ok(Self {
let this = Self {
height_to_interval: EagerVec::forced_import_compressed(
&db,
"interval",
version + VERSION + Version::ZERO,
)?,
timeindexes_to_timestamp: ComputedVecsFromDateIndex::forced_import(
&db,
"timestamp",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_first(),
)?,
indexes_to_block_interval: ComputedVecsFromHeight::forced_import(
&db,
"block_interval",
Source::None,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default()
.add_percentiles()
.add_minmax()
.add_average(),
)?,
indexes_to_block_count: ComputedVecsFromHeight::forced_import(
&db,
"block_count",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_sum().add_cumulative(),
)?,
indexes_to_block_weight: ComputedVecsFromHeight::forced_import(
&db,
"block_weight",
Source::None,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default()
.add_sum()
.add_minmax()
.add_average()
.add_percentiles()
.add_cumulative(),
)?,
indexes_to_block_size: ComputedVecsFromHeight::forced_import(
&db,
"block_size",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default()
.add_sum()
.add_minmax()
.add_average()
.add_percentiles()
.add_cumulative(),
)?,
height_to_vbytes: EagerVec::forced_import_compressed(
&db,
"vbytes",
version + VERSION + Version::ZERO,
)?,
indexes_to_block_vbytes: ComputedVecsFromHeight::forced_import(
&db,
"block_vbytes",
Source::None,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default()
.add_sum()
.add_minmax()
.add_average()
.add_percentiles()
.add_cumulative(),
)?,
difficultyepoch_to_timestamp: EagerVec::forced_import_compressed(
&db,
"timestamp",
version + VERSION + Version::ZERO,
)?,
halvingepoch_to_timestamp: EagerVec::forced_import_compressed(
&db,
"timestamp",
version + VERSION + Version::ZERO,
)?,
dateindex_to_fee_dominance: EagerVec::forced_import_compressed(
&db,
"fee_dominance",
version + VERSION + Version::ZERO,
)?,
dateindex_to_subsidy_dominance: EagerVec::forced_import_compressed(
&db,
"subsidy_dominance",
version + VERSION + Version::ZERO,
)?,
indexes_to_difficulty: ComputedVecsFromHeight::forced_import(
&db,
"difficulty",
Source::None,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_difficultyepoch: ComputedVecsFromDateIndex::forced_import(
&db,
"difficultyepoch",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_halvingepoch: ComputedVecsFromDateIndex::forced_import(
&db,
"halvingepoch",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_tx_count: ComputedVecsFromHeight::forced_import(
&db,
"tx_count",
@@ -343,9 +487,9 @@ impl Vecs {
.add_minmax()
.add_average(),
)?,
indexes_to_feerate: ComputedVecsFromTxindex::forced_import(
indexes_to_fee_rate: ComputedVecsFromTxindex::forced_import(
&db,
"feerate",
"fee_rate",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -577,6 +721,77 @@ impl Vecs {
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_subsidy_usd_1y_sma: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
&db,
"subsidy_usd_1y_sma",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)
.unwrap()
}),
indexes_to_puell_multiple: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
&db,
"puell_multiple",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)
.unwrap()
}),
indexes_to_hash_rate: ComputedVecsFromDateIndex::forced_import(
&db,
"hash_rate",
Source::Compute,
version + VERSION + Version::ONE,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_hash_rate_1w_sma: ComputedVecsFromDateIndex::forced_import(
&db,
"hash_rate_1w_sma",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_hash_rate_1m_sma: ComputedVecsFromDateIndex::forced_import(
&db,
"hash_rate_1m_sma",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_hash_rate_2m_sma: ComputedVecsFromDateIndex::forced_import(
&db,
"hash_rate_2m_sma",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_hash_rate_1y_sma: ComputedVecsFromDateIndex::forced_import(
&db,
"hash_rate_1y_sma",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_difficulty_as_hash: ComputedVecsFromDateIndex::forced_import(
&db,
"difficulty_as_hash",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
txindex_to_is_coinbase,
inputindex_to_value,
// indexes_to_input_value,
@@ -584,12 +799,21 @@ impl Vecs {
txindex_to_input_value,
txindex_to_output_value,
txindex_to_fee,
txindex_to_feerate,
txindex_to_fee_rate,
txindex_to_vsize,
txindex_to_weight,
db,
})
};
this.db.retain_regions(
this.vecs()
.into_iter()
.flat_map(|v| v.region_names())
.collect(),
)?;
Ok(this)
}
pub fn compute(
@@ -613,6 +837,167 @@ impl Vecs {
price: Option<&price::Vecs>,
exit: &Exit,
) -> Result<()> {
self.timeindexes_to_timestamp.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, indexes, starting_indexes, exit| {
vec.compute_transform(
starting_indexes.dateindex,
&indexes.dateindex_to_date,
|(di, d, ..)| (di, Timestamp::from(d)),
exit,
)?;
Ok(())
},
)?;
self.indexes_to_block_count.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, indexer, _, starting_indexes, exit| {
v.compute_range(
starting_indexes.height,
&indexer.vecs.height_to_weight,
|h| (h, StoredU32::from(1_u32)),
exit,
)?;
Ok(())
},
)?;
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
self.height_to_interval.compute_transform(
starting_indexes.height,
&indexer.vecs.height_to_timestamp,
|(height, timestamp, ..)| {
let interval = height.decremented().map_or(Timestamp::ZERO, |prev_h| {
let prev_timestamp = height_to_timestamp_iter.unwrap_get_inner(prev_h);
timestamp
.checked_sub(prev_timestamp)
.unwrap_or(Timestamp::ZERO)
});
(height, interval)
},
exit,
)?;
self.indexes_to_block_interval.compute_rest(
indexes,
starting_indexes,
exit,
Some(&self.height_to_interval),
)?;
self.indexes_to_block_weight.compute_rest(
indexes,
starting_indexes,
exit,
Some(&indexer.vecs.height_to_weight),
)?;
self.indexes_to_block_size.compute_rest(
indexes,
starting_indexes,
exit,
Some(&indexer.vecs.height_to_total_size),
)?;
self.height_to_vbytes.compute_transform(
starting_indexes.height,
&indexer.vecs.height_to_weight,
|(h, w, ..)| {
(
h,
StoredU64::from(bitcoin::Weight::from(w).to_vbytes_floor()),
)
},
exit,
)?;
self.indexes_to_block_vbytes.compute_rest(
indexes,
starting_indexes,
exit,
Some(&self.height_to_vbytes),
)?;
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
self.difficultyepoch_to_timestamp.compute_transform(
starting_indexes.difficultyepoch,
&indexes.difficultyepoch_to_first_height,
|(i, h, ..)| (i, height_to_timestamp_iter.unwrap_get_inner(h)),
exit,
)?;
self.halvingepoch_to_timestamp.compute_transform(
starting_indexes.halvingepoch,
&indexes.halvingepoch_to_first_height,
|(i, h, ..)| (i, height_to_timestamp_iter.unwrap_get_inner(h)),
exit,
)?;
let mut height_to_difficultyepoch_iter = indexes.height_to_difficultyepoch.into_iter();
self.indexes_to_difficultyepoch.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, indexes, starting_indexes, exit| {
let mut height_count_iter = indexes.dateindex_to_height_count.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&indexes.dateindex_to_first_height,
|(di, height, ..)| {
(
di,
height_to_difficultyepoch_iter.unwrap_get_inner(
height + (*height_count_iter.unwrap_get_inner(di) - 1),
),
)
},
exit,
)?;
Ok(())
},
)?;
let mut height_to_halvingepoch_iter = indexes.height_to_halvingepoch.into_iter();
self.indexes_to_halvingepoch.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, indexes, starting_indexes, exit| {
let mut height_count_iter = indexes.dateindex_to_height_count.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&indexes.dateindex_to_first_height,
|(di, height, ..)| {
(
di,
height_to_halvingepoch_iter.unwrap_get_inner(
height + (*height_count_iter.unwrap_get_inner(di) - 1),
),
)
},
exit,
)?;
Ok(())
},
)?;
self.indexes_to_difficulty.compute_rest(
indexes,
starting_indexes,
exit,
Some(&indexer.vecs.height_to_difficulty),
)?;
self.indexes_to_tx_count.compute_all(
indexer,
indexes,
@@ -722,11 +1107,11 @@ impl Vecs {
exit,
)?;
self.txindex_to_feerate.compute_transform2(
self.txindex_to_fee_rate.compute_transform2(
starting_indexes.txindex,
&self.txindex_to_fee,
&self.txindex_to_vsize,
|(txindex, fee, vsize, ..)| (txindex, Feerate::from((fee, vsize))),
|(txindex, fee, vsize, ..)| (txindex, FeeRate::from((fee, vsize))),
exit,
)?;
@@ -739,12 +1124,12 @@ impl Vecs {
price,
)?;
self.indexes_to_feerate.compute_rest(
self.indexes_to_fee_rate.compute_rest(
indexer,
indexes,
starting_indexes,
exit,
Some(&self.txindex_to_feerate),
Some(&self.txindex_to_fee_rate),
)?;
self.indexes_to_tx_weight.compute_rest(
@@ -1085,25 +1470,241 @@ impl Vecs {
},
)?;
self.dateindex_to_fee_dominance.compute_transform2(
starting_indexes.dateindex,
self.indexes_to_fee.sats.dateindex.unwrap_sum(),
self.indexes_to_coinbase.sats.dateindex.unwrap_sum(),
|(i, fee, coinbase, ..)| {
(
i,
StoredF32::from(u64::from(fee) as f64 / u64::from(coinbase) as f64 * 100.0),
)
},
exit,
)?;
self.dateindex_to_subsidy_dominance.compute_transform2(
starting_indexes.dateindex,
self.indexes_to_subsidy.sats.dateindex.unwrap_sum(),
self.indexes_to_coinbase.sats.dateindex.unwrap_sum(),
|(i, subsidy, coinbase, ..)| {
(
i,
StoredF32::from(u64::from(subsidy) as f64 / u64::from(coinbase) as f64 * 100.0),
)
},
exit,
)?;
self.indexes_to_difficulty_as_hash.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
let multiplier = 2.0_f64.powi(32) / 600.0;
v.compute_transform(
starting_indexes.dateindex,
self.indexes_to_difficulty.dateindex.unwrap_last(),
|(i, v, ..)| (i, StoredF32::from(*v * multiplier)),
exit,
)?;
Ok(())
},
)?;
let now = Timestamp::now();
let today = Date::from(now);
self.indexes_to_hash_rate.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_transform3(
starting_indexes.dateindex,
self.indexes_to_block_count.dateindex.unwrap_sum(),
self.indexes_to_difficulty_as_hash
.dateindex
.as_ref()
.unwrap(),
&indexes.dateindex_to_date,
|(i, block_count_sum, difficulty_as_hash, date, ..)| {
let target_multiplier = if date == today {
now.day_completion()
} else {
1.0
};
(
i,
StoredF64::from(
(f64::from(block_count_sum)
/ (target_multiplier * TARGET_BLOCKS_PER_DAY))
* f64::from(difficulty_as_hash),
),
)
},
exit,
)?;
Ok(())
},
)?;
self.indexes_to_hash_rate_1w_sma.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sma(
starting_indexes.dateindex,
self.indexes_to_hash_rate.dateindex.as_ref().unwrap(),
7,
exit,
)?;
Ok(())
},
)?;
self.indexes_to_hash_rate_1m_sma.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sma(
starting_indexes.dateindex,
self.indexes_to_hash_rate.dateindex.as_ref().unwrap(),
30,
exit,
)?;
Ok(())
},
)?;
self.indexes_to_hash_rate_2m_sma.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sma(
starting_indexes.dateindex,
self.indexes_to_hash_rate.dateindex.as_ref().unwrap(),
2 * 30,
exit,
)?;
Ok(())
},
)?;
self.indexes_to_hash_rate_1y_sma.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sma(
starting_indexes.dateindex,
self.indexes_to_hash_rate.dateindex.as_ref().unwrap(),
365,
exit,
)?;
Ok(())
},
)?;
if self.indexes_to_subsidy_usd_1y_sma.is_some() {
let date_to_coinbase_usd_sum = self
.indexes_to_coinbase
.dollars
.as_ref()
.unwrap()
.dateindex
.unwrap_sum();
self.indexes_to_subsidy_usd_1y_sma
.as_mut()
.unwrap()
.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sma(
starting_indexes.dateindex,
date_to_coinbase_usd_sum,
365,
exit,
)?;
Ok(())
},
)?;
self.indexes_to_puell_multiple
.as_mut()
.unwrap()
.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_divide(
starting_indexes.dateindex,
date_to_coinbase_usd_sum,
self.indexes_to_subsidy_usd_1y_sma
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
exit,
)?;
Ok(())
},
)?;
}
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
vec![
&self.inputindex_to_value as &dyn AnyCollectableVec,
&self.height_to_interval as &dyn AnyCollectableVec,
&self.height_to_vbytes,
&self.difficultyepoch_to_timestamp,
&self.halvingepoch_to_timestamp,
&self.inputindex_to_value,
&self.txindex_to_fee,
&self.txindex_to_feerate,
&self.txindex_to_fee_rate,
&self.txindex_to_input_value,
&self.txindex_to_is_coinbase,
&self.txindex_to_output_value,
&self.txindex_to_vsize,
&self.txindex_to_weight,
&self.dateindex_to_fee_dominance,
&self.dateindex_to_subsidy_dominance,
],
self.indexes_to_hash_rate.vecs(),
self.indexes_to_hash_rate_1w_sma.vecs(),
self.indexes_to_hash_rate_1m_sma.vecs(),
self.indexes_to_hash_rate_2m_sma.vecs(),
self.indexes_to_hash_rate_1y_sma.vecs(),
self.timeindexes_to_timestamp.vecs(),
self.indexes_to_block_count.vecs(),
self.indexes_to_block_interval.vecs(),
self.indexes_to_block_size.vecs(),
self.indexes_to_block_vbytes.vecs(),
self.indexes_to_block_weight.vecs(),
self.indexes_to_difficulty.vecs(),
self.indexes_to_difficultyepoch.vecs(),
self.indexes_to_halvingepoch.vecs(),
self.indexes_to_coinbase.vecs(),
self.indexes_to_emptyoutput_count.vecs(),
self.indexes_to_fee.vecs(),
self.indexes_to_feerate.vecs(),
self.indexes_to_fee_rate.vecs(),
self.indexes_to_input_count.vecs(),
self.indexes_to_opreturn_count.vecs(),
self.indexes_to_output_count.vecs(),
@@ -1111,6 +1712,7 @@ impl Vecs {
self.indexes_to_p2ms_count.vecs(),
self.indexes_to_p2pk33_count.vecs(),
self.indexes_to_p2pk65_count.vecs(),
self.indexes_to_difficulty_as_hash.vecs(),
self.indexes_to_p2pkh_count.vecs(),
self.indexes_to_p2sh_count.vecs(),
self.indexes_to_p2tr_count.vecs(),
@@ -1126,6 +1728,12 @@ impl Vecs {
self.indexes_to_unknownoutput_count.vecs(),
self.indexes_to_exact_utxo_count.vecs(),
self.indexes_to_unclaimed_rewards.vecs(),
self.indexes_to_subsidy_usd_1y_sma
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_puell_multiple
.as_ref()
.map_or(vec![], |v| v.vecs()),
]
.into_iter()
.flatten()
+21 -12
View File
@@ -6,12 +6,12 @@ use brk_structs::{Bitcoin, CheckedSub, Dollars, StoredF64, Version};
use vecdb::{AnyCollectableVec, Database, Exit, PAGE_SIZE, VecIterator};
use super::{
Indexes,
Indexes, chain,
grouped::{
ComputedRatioVecsFromDateIndex, ComputedValueVecsFromHeight, ComputedVecsFromHeight,
Source, VecBuilderOptions,
},
indexes, price, stateful, transactions,
indexes, price, stateful,
};
const VERSION: Version = Version::ZERO;
@@ -43,7 +43,7 @@ pub struct Vecs {
pub indexes_to_cointime_price: ComputedVecsFromHeight<Dollars>,
pub indexes_to_cointime_cap: ComputedVecsFromHeight<Dollars>,
pub indexes_to_cointime_price_ratio: ComputedRatioVecsFromDateIndex,
// pub indexes_to_thermo_cap_relative_to_investor_cap: ComputedValueVecsFromHeight,
// pub indexes_to_thermo_cap_rel_to_investor_cap: ComputedValueVecsFromHeight,
}
impl Vecs {
@@ -58,7 +58,7 @@ impl Vecs {
let compute_dollars = price.is_some();
Ok(Self {
let this = Self {
indexes_to_coinblocks_created: ComputedVecsFromHeight::forced_import(
&db,
"coinblocks_created",
@@ -247,7 +247,16 @@ impl Vecs {
)?,
db,
})
};
this.db.retain_regions(
this.vecs()
.into_iter()
.flat_map(|v| v.region_names())
.collect(),
)?;
Ok(this)
}
#[allow(clippy::too_many_arguments)]
@@ -257,7 +266,7 @@ impl Vecs {
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
price: Option<&price::Vecs>,
transactions: &transactions::Vecs,
chain: &chain::Vecs,
stateful: &stateful::Vecs,
exit: &Exit,
) -> Result<()> {
@@ -266,7 +275,7 @@ impl Vecs {
indexes,
starting_indexes,
price,
transactions,
chain,
stateful,
exit,
)?;
@@ -281,7 +290,7 @@ impl Vecs {
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
price: Option<&price::Vecs>,
transactions: &transactions::Vecs,
chain: &chain::Vecs,
stateful: &stateful::Vecs,
exit: &Exit,
) -> Result<()> {
@@ -446,7 +455,7 @@ impl Vecs {
|vec, _, _, starting_indexes, exit| {
vec.compute_transform(
starting_indexes.height,
transactions
chain
.indexes_to_subsidy
.dollars
.as_ref()
@@ -597,7 +606,7 @@ impl Vecs {
// The price taken won't be correct for time based indexes
vec.compute_multiply(
starting_indexes.height,
&price.chainindexes_to_close.height,
&price.chainindexes_to_price_close.height,
indexes_to_coinblocks_destroyed.height.as_ref().unwrap(),
exit,
)?;
@@ -613,7 +622,7 @@ impl Vecs {
|vec, _, _, starting_indexes, exit| {
vec.compute_multiply(
starting_indexes.height,
&price.chainindexes_to_close.height,
&price.chainindexes_to_price_close.height,
self.indexes_to_coinblocks_created.height.as_ref().unwrap(),
exit,
)?;
@@ -629,7 +638,7 @@ impl Vecs {
|vec, _, _, starting_indexes, exit| {
vec.compute_multiply(
starting_indexes.height,
&price.chainindexes_to_close.height,
&price.chainindexes_to_price_close.height,
self.indexes_to_coinblocks_stored.height.as_ref().unwrap(),
exit,
)?;
+11 -2
View File
@@ -38,7 +38,7 @@ impl Vecs {
pub fn forced_import(parent: &Path, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let db = Database::open(&parent.join("constants"))?;
Ok(Self {
let this = Self {
constant_0: ComputedVecsFromHeight::forced_import(
&db,
"constant_0",
@@ -145,7 +145,16 @@ impl Vecs {
)?,
db,
})
};
this.db.retain_regions(
this.vecs()
.into_iter()
.flat_map(|v| v.region_names())
.collect(),
)?;
Ok(this)
}
pub fn compute(
+28 -18
View File
@@ -16,30 +16,39 @@ pub struct Vecs {
db: Database,
fetcher: Fetcher,
pub dateindex_to_ohlc_in_cents: RawVec<DateIndex, OHLCCents>,
pub height_to_ohlc_in_cents: RawVec<Height, OHLCCents>,
pub dateindex_to_price_ohlc_in_cents: RawVec<DateIndex, OHLCCents>,
pub height_to_price_ohlc_in_cents: RawVec<Height, OHLCCents>,
}
impl Vecs {
pub fn forced_import(parent: &Path, fetcher: Fetcher, version: Version) -> Result<Self> {
let db = Database::open(&parent.join("fetched"))?;
Ok(Self {
let this = Self {
fetcher,
dateindex_to_ohlc_in_cents: RawVec::forced_import(
dateindex_to_price_ohlc_in_cents: RawVec::forced_import(
&db,
"ohlc_in_cents",
"price_ohlc_in_cents",
version + Version::ZERO,
)?,
height_to_ohlc_in_cents: RawVec::forced_import(
height_to_price_ohlc_in_cents: RawVec::forced_import(
&db,
"ohlc_in_cents",
"price_ohlc_in_cents",
version + Version::ZERO,
)?,
db,
})
};
this.db.retain_regions(
this.vecs()
.into_iter()
.flat_map(|v| v.region_names())
.collect(),
)?;
Ok(this)
}
pub fn compute(
@@ -64,12 +73,12 @@ impl Vecs {
let height_to_timestamp = &indexer.vecs.height_to_timestamp;
let index = starting_indexes
.height
.min(Height::from(self.height_to_ohlc_in_cents.len()));
.min(Height::from(self.height_to_price_ohlc_in_cents.len()));
height_to_timestamp
.iter_at(index)
.try_for_each(|(i, v)| -> Result<()> {
let v = v.into_owned();
self.height_to_ohlc_in_cents.forced_push_at(
self.height_to_price_ohlc_in_cents.forced_push_at(
i,
self.fetcher
.get_height(
@@ -84,11 +93,11 @@ impl Vecs {
)?;
Ok(())
})?;
self.height_to_ohlc_in_cents.safe_flush(exit)?;
self.height_to_price_ohlc_in_cents.safe_flush(exit)?;
let index = starting_indexes
.dateindex
.min(DateIndex::from(self.dateindex_to_ohlc_in_cents.len()));
.min(DateIndex::from(self.dateindex_to_price_ohlc_in_cents.len()));
let mut prev = None;
indexes
.dateindex_to_date
@@ -98,7 +107,7 @@ impl Vecs {
if prev.is_none() {
let i = i.unwrap_to_usize();
prev.replace(if i > 0 {
self.dateindex_to_ohlc_in_cents
self.dateindex_to_price_ohlc_in_cents
.into_iter()
.unwrap_get_inner_(i - 1)
} else {
@@ -106,7 +115,8 @@ impl Vecs {
});
}
let ohlc = if i.unwrap_to_usize() + 100 >= self.dateindex_to_ohlc_in_cents.len()
let ohlc = if i.unwrap_to_usize() + 100
>= self.dateindex_to_price_ohlc_in_cents.len()
&& let Ok(mut ohlc) = self.fetcher.get_date(d)
{
let prev_open = *prev.as_ref().unwrap().close;
@@ -120,20 +130,20 @@ impl Vecs {
prev.replace(ohlc.clone());
self.dateindex_to_ohlc_in_cents
self.dateindex_to_price_ohlc_in_cents
.forced_push_at(i, ohlc, exit)?;
Ok(())
})?;
self.dateindex_to_ohlc_in_cents.safe_flush(exit)?;
self.dateindex_to_price_ohlc_in_cents.safe_flush(exit)?;
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
vec![
&self.dateindex_to_ohlc_in_cents as &dyn AnyCollectableVec,
&self.height_to_ohlc_in_cents,
&self.dateindex_to_price_ohlc_in_cents as &dyn AnyCollectableVec,
&self.height_to_price_ohlc_in_cents,
]
}
}
+101 -101
View File
@@ -19,11 +19,11 @@ where
pub average: Option<Box<EagerVec<I, T>>>,
pub sum: Option<Box<EagerVec<I, T>>>,
pub max: Option<Box<EagerVec<I, T>>>,
pub _90p: Option<Box<EagerVec<I, T>>>,
pub _75p: Option<Box<EagerVec<I, T>>>,
pub p90: Option<Box<EagerVec<I, T>>>,
pub p75: Option<Box<EagerVec<I, T>>>,
pub median: Option<Box<EagerVec<I, T>>>,
pub _25p: Option<Box<EagerVec<I, T>>>,
pub _10p: Option<Box<EagerVec<I, T>>>,
pub p25: Option<Box<EagerVec<I, T>>>,
pub p10: Option<Box<EagerVec<I, T>>>,
pub min: Option<Box<EagerVec<I, T>>>,
pub last: Option<Box<EagerVec<I, T>>>,
pub cumulative: Option<Box<EagerVec<I, T>>>,
@@ -118,7 +118,7 @@ where
Box::new(
EagerVec::forced_import(
db,
&maybe_suffix("average"),
&maybe_suffix("avg"),
version + VERSION + Version::ZERO,
format,
)
@@ -151,44 +151,44 @@ where
.unwrap(),
)
}),
_90p: options._90p.then(|| {
p90: options.p90.then(|| {
Box::new(
EagerVec::forced_import(
db,
&maybe_suffix("90p"),
&maybe_suffix("p90"),
version + VERSION + Version::ZERO,
format,
)
.unwrap(),
)
}),
_75p: options._75p.then(|| {
p75: options.p75.then(|| {
Box::new(
EagerVec::forced_import(
db,
&maybe_suffix("75p"),
&maybe_suffix("p75"),
version + VERSION + Version::ZERO,
format,
)
.unwrap(),
)
}),
_25p: options._25p.then(|| {
p25: options.p25.then(|| {
Box::new(
EagerVec::forced_import(
db,
&maybe_suffix("25p"),
&maybe_suffix("p25"),
version + VERSION + Version::ZERO,
format,
)
.unwrap(),
)
}),
_10p: options._10p.then(|| {
p10: options.p10.then(|| {
Box::new(
EagerVec::forced_import(
db,
&maybe_suffix("10p"),
&maybe_suffix("p10"),
version + VERSION + Version::ZERO,
format,
)
@@ -292,11 +292,11 @@ where
let needs_average_sum_or_cumulative =
needs_sum_or_cumulative || self.average.is_some();
let needs_sorted = self.max.is_some()
|| self._90p.is_some()
|| self._75p.is_some()
|| self.p90.is_some()
|| self.p75.is_some()
|| self.median.is_some()
|| self._25p.is_some()
|| self._10p.is_some()
|| self.p25.is_some()
|| self.p10.is_some()
|| self.min.is_some();
let needs_values = needs_sorted || needs_average_sum_or_cumulative;
@@ -333,24 +333,24 @@ where
)?;
}
if let Some(_90p) = self._90p.as_mut() {
_90p.forced_push_at(index, get_percentile(&values, 0.90), exit)?;
if let Some(p90) = self.p90.as_mut() {
p90.forced_push_at(index, get_percentile(&values, 0.90), exit)?;
}
if let Some(_75p) = self._75p.as_mut() {
_75p.forced_push_at(index, get_percentile(&values, 0.75), exit)?;
if let Some(p75) = self.p75.as_mut() {
p75.forced_push_at(index, get_percentile(&values, 0.75), exit)?;
}
if let Some(median) = self.median.as_mut() {
median.forced_push_at(index, get_percentile(&values, 0.50), exit)?;
}
if let Some(_25p) = self._25p.as_mut() {
_25p.forced_push_at(index, get_percentile(&values, 0.25), exit)?;
if let Some(p25) = self.p25.as_mut() {
p25.forced_push_at(index, get_percentile(&values, 0.25), exit)?;
}
if let Some(_10p) = self._10p.as_mut() {
_10p.forced_push_at(index, get_percentile(&values, 0.10), exit)?;
if let Some(p10) = self.p10.as_mut() {
p10.forced_push_at(index, get_percentile(&values, 0.10), exit)?;
}
if let Some(min) = self.min.as_mut() {
@@ -401,11 +401,11 @@ where
where
I2: StoredIndex + StoredRaw + CheckedSub<I2>,
{
if self._90p.is_some()
|| self._75p.is_some()
if self.p90.is_some()
|| self.p75.is_some()
|| self.median.is_some()
|| self._25p.is_some()
|| self._10p.is_some()
|| self.p25.is_some()
|| self.p10.is_some()
{
panic!("unsupported");
}
@@ -558,24 +558,24 @@ where
self.max.as_ref().unwrap()
}
#[allow(unused)]
pub fn unwrap_90p(&self) -> &EagerVec<I, T> {
self._90p.as_ref().unwrap()
pub fn unwrap_p90(&self) -> &EagerVec<I, T> {
self.p90.as_ref().unwrap()
}
#[allow(unused)]
pub fn unwrap_75p(&self) -> &EagerVec<I, T> {
self._75p.as_ref().unwrap()
pub fn unwrap_p75(&self) -> &EagerVec<I, T> {
self.p75.as_ref().unwrap()
}
#[allow(unused)]
pub fn unwrap_median(&self) -> &EagerVec<I, T> {
self.median.as_ref().unwrap()
}
#[allow(unused)]
pub fn unwrap_25p(&self) -> &EagerVec<I, T> {
self._25p.as_ref().unwrap()
pub fn unwrap_p25(&self) -> &EagerVec<I, T> {
self.p25.as_ref().unwrap()
}
#[allow(unused)]
pub fn unwrap_10p(&self) -> &EagerVec<I, T> {
self._10p.as_ref().unwrap()
pub fn unwrap_p10(&self) -> &EagerVec<I, T> {
self.p10.as_ref().unwrap()
}
pub fn unwrap_min(&self) -> &EagerVec<I, T> {
self.min.as_ref().unwrap()
@@ -615,17 +615,17 @@ where
if let Some(cumulative) = self.cumulative.as_ref() {
v.push(cumulative.as_ref());
}
if let Some(_90p) = self._90p.as_ref() {
v.push(_90p.as_ref());
if let Some(p90) = self.p90.as_ref() {
v.push(p90.as_ref());
}
if let Some(_75p) = self._75p.as_ref() {
v.push(_75p.as_ref());
if let Some(p75) = self.p75.as_ref() {
v.push(p75.as_ref());
}
if let Some(_25p) = self._25p.as_ref() {
v.push(_25p.as_ref());
if let Some(p25) = self.p25.as_ref() {
v.push(p25.as_ref());
}
if let Some(_10p) = self._10p.as_ref() {
v.push(_10p.as_ref());
if let Some(p10) = self.p10.as_ref() {
v.push(p10.as_ref());
}
v
@@ -656,17 +656,17 @@ where
if let Some(cumulative) = self.cumulative.as_mut() {
cumulative.safe_flush(exit)?;
}
if let Some(_90p) = self._90p.as_mut() {
_90p.safe_flush(exit)?;
if let Some(p90) = self.p90.as_mut() {
p90.safe_flush(exit)?;
}
if let Some(_75p) = self._75p.as_mut() {
_75p.safe_flush(exit)?;
if let Some(p75) = self.p75.as_mut() {
p75.safe_flush(exit)?;
}
if let Some(_25p) = self._25p.as_mut() {
_25p.safe_flush(exit)?;
if let Some(p25) = self.p25.as_mut() {
p25.safe_flush(exit)?;
}
if let Some(_10p) = self._10p.as_mut() {
_10p.safe_flush(exit)?;
if let Some(p10) = self.p10.as_mut() {
p10.safe_flush(exit)?;
}
Ok(())
@@ -697,17 +697,17 @@ where
if let Some(cumulative) = self.cumulative.as_mut() {
cumulative.validate_computed_version_or_reset(Version::ZERO + version)?;
}
if let Some(_90p) = self._90p.as_mut() {
_90p.validate_computed_version_or_reset(Version::ZERO + version)?;
if let Some(p90) = self.p90.as_mut() {
p90.validate_computed_version_or_reset(Version::ZERO + version)?;
}
if let Some(_75p) = self._75p.as_mut() {
_75p.validate_computed_version_or_reset(Version::ZERO + version)?;
if let Some(p75) = self.p75.as_mut() {
p75.validate_computed_version_or_reset(Version::ZERO + version)?;
}
if let Some(_25p) = self._25p.as_mut() {
_25p.validate_computed_version_or_reset(Version::ZERO + version)?;
if let Some(p25) = self.p25.as_mut() {
p25.validate_computed_version_or_reset(Version::ZERO + version)?;
}
if let Some(_10p) = self._10p.as_mut() {
_10p.validate_computed_version_or_reset(Version::ZERO + version)?;
if let Some(p10) = self.p10.as_mut() {
p10.validate_computed_version_or_reset(Version::ZERO + version)?;
}
Ok(())
@@ -719,11 +719,11 @@ pub struct VecBuilderOptions {
average: bool,
sum: bool,
max: bool,
_90p: bool,
_75p: bool,
p90: bool,
p75: bool,
median: bool,
_25p: bool,
_10p: bool,
p25: bool,
p10: bool,
min: bool,
first: bool,
last: bool,
@@ -743,24 +743,24 @@ impl VecBuilderOptions {
self.max
}
pub fn _90p(&self) -> bool {
self._90p
pub fn p90(&self) -> bool {
self.p90
}
pub fn _75p(&self) -> bool {
self._75p
pub fn p75(&self) -> bool {
self.p75
}
pub fn median(&self) -> bool {
self.median
}
pub fn _25p(&self) -> bool {
self._25p
pub fn p25(&self) -> bool {
self.p25
}
pub fn _10p(&self) -> bool {
self._10p
pub fn p10(&self) -> bool {
self.p10
}
pub fn min(&self) -> bool {
@@ -816,26 +816,26 @@ impl VecBuilderOptions {
}
#[allow(unused)]
pub fn add_90p(mut self) -> Self {
self._90p = true;
pub fn add_p90(mut self) -> Self {
self.p90 = true;
self
}
#[allow(unused)]
pub fn add_75p(mut self) -> Self {
self._75p = true;
pub fn add_p75(mut self) -> Self {
self.p75 = true;
self
}
#[allow(unused)]
pub fn add_25p(mut self) -> Self {
self._25p = true;
pub fn add_p25(mut self) -> Self {
self.p25 = true;
self
}
#[allow(unused)]
pub fn add_10p(mut self) -> Self {
self._10p = true;
pub fn add_p10(mut self) -> Self {
self.p10 = true;
self
}
@@ -875,26 +875,26 @@ impl VecBuilderOptions {
}
#[allow(unused)]
pub fn rm_90p(mut self) -> Self {
self._90p = false;
pub fn rm_p90(mut self) -> Self {
self.p90 = false;
self
}
#[allow(unused)]
pub fn rm_75p(mut self) -> Self {
self._75p = false;
pub fn rm_p75(mut self) -> Self {
self.p75 = false;
self
}
#[allow(unused)]
pub fn rm_25p(mut self) -> Self {
self._25p = false;
pub fn rm_p25(mut self) -> Self {
self.p25 = false;
self
}
#[allow(unused)]
pub fn rm_10p(mut self) -> Self {
self._10p = false;
pub fn rm_p10(mut self) -> Self {
self.p10 = false;
self
}
@@ -911,20 +911,20 @@ impl VecBuilderOptions {
}
pub fn add_percentiles(mut self) -> Self {
self._90p = true;
self._75p = true;
self.p90 = true;
self.p75 = true;
self.median = true;
self._25p = true;
self._10p = true;
self.p25 = true;
self.p10 = true;
self
}
pub fn remove_percentiles(mut self) -> Self {
self._90p = false;
self._75p = false;
self.p90 = false;
self.p75 = false;
self.median = false;
self._25p = false;
self._10p = false;
self.p25 = false;
self.p10 = false;
self
}
@@ -933,11 +933,11 @@ impl VecBuilderOptions {
self.average,
self.sum,
self.max,
self._90p,
self._75p,
self.p90,
self.p75,
self.median,
self._25p,
self._10p,
self.p25,
self.p10,
self.min,
self.first,
self.last,
@@ -142,7 +142,7 @@ where
}),
average: options.average.then(|| {
Box::new(LazyVecFrom2::init(
&maybe_suffix("average"),
&maybe_suffix("avg"),
version + VERSION + Version::ZERO,
source_extra
.average
+17 -17
View File
@@ -319,24 +319,24 @@ impl ComputedVecsFromTxindex<Bitcoin> {
exit,
)?;
}
if let Some(_90p) = self.height._90p.as_mut() {
if let Some(_90p) = self.height.p90.as_mut() {
_90p.forced_push_at(
height,
Bitcoin::from(
sats.height
.unwrap_90p()
.unwrap_p90()
.into_iter()
.unwrap_get_inner(height),
),
exit,
)?;
}
if let Some(_75p) = self.height._75p.as_mut() {
if let Some(_75p) = self.height.p75.as_mut() {
_75p.forced_push_at(
height,
Bitcoin::from(
sats.height
.unwrap_75p()
.unwrap_p75()
.into_iter()
.unwrap_get_inner(height),
),
@@ -355,24 +355,24 @@ impl ComputedVecsFromTxindex<Bitcoin> {
exit,
)?;
}
if let Some(_25p) = self.height._25p.as_mut() {
if let Some(_25p) = self.height.p25.as_mut() {
_25p.forced_push_at(
height,
Bitcoin::from(
sats.height
.unwrap_25p()
.unwrap_p25()
.into_iter()
.unwrap_get_inner(height),
),
exit,
)?;
}
if let Some(_10p) = self.height._10p.as_mut() {
if let Some(_10p) = self.height.p10.as_mut() {
_10p.forced_push_at(
height,
Bitcoin::from(
sats.height
.unwrap_10p()
.unwrap_p10()
.into_iter()
.unwrap_get_inner(height),
),
@@ -447,7 +447,7 @@ impl ComputedVecsFromTxindex<Dollars> {
let starting_index = self.height.starting_index(starting_indexes.height);
let mut close_iter = price.chainindexes_to_close.height.into_iter();
let mut close_iter = price.chainindexes_to_price_close.height.into_iter();
(starting_index.unwrap_to_usize()..indexer.vecs.height_to_weight.len())
.map(Height::from)
@@ -502,25 +502,25 @@ impl ComputedVecsFromTxindex<Dollars> {
exit,
)?;
}
if let Some(_90p) = self.height._90p.as_mut() {
if let Some(_90p) = self.height.p90.as_mut() {
_90p.forced_push_at(
height,
price
* bitcoin
.height
.unwrap_90p()
.unwrap_p90()
.into_iter()
.unwrap_get_inner(height),
exit,
)?;
}
if let Some(_75p) = self.height._75p.as_mut() {
if let Some(_75p) = self.height.p75.as_mut() {
_75p.forced_push_at(
height,
price
* bitcoin
.height
.unwrap_75p()
.unwrap_p75()
.into_iter()
.unwrap_get_inner(height),
exit,
@@ -538,25 +538,25 @@ impl ComputedVecsFromTxindex<Dollars> {
exit,
)?;
}
if let Some(_25p) = self.height._25p.as_mut() {
if let Some(_25p) = self.height.p25.as_mut() {
_25p.forced_push_at(
height,
price
* bitcoin
.height
.unwrap_25p()
.unwrap_p25()
.into_iter()
.unwrap_get_inner(height),
exit,
)?;
}
if let Some(_10p) = self.height._10p.as_mut() {
if let Some(_10p) = self.height.p10.as_mut() {
_10p.forced_push_at(
height,
price
* bitcoin
.height
.unwrap_10p()
.unwrap_p10()
.into_iter()
.unwrap_get_inner(height),
exit,
@@ -22,18 +22,18 @@ pub struct ComputedRatioVecsFromDateIndex {
pub ratio: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_1w_sma: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_1m_sma: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_p99: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_p98: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_p95: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_p5: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_p2: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_p1: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_p99_as_price: Option<ComputedVecsFromDateIndex<Dollars>>,
pub ratio_p98_as_price: Option<ComputedVecsFromDateIndex<Dollars>>,
pub ratio_p95_as_price: Option<ComputedVecsFromDateIndex<Dollars>>,
pub ratio_p5_as_price: Option<ComputedVecsFromDateIndex<Dollars>>,
pub ratio_p2_as_price: Option<ComputedVecsFromDateIndex<Dollars>>,
pub ratio_p1_as_price: Option<ComputedVecsFromDateIndex<Dollars>>,
pub ratio_pct99: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_pct98: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_pct95: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_pct5: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_pct2: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_pct1: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub ratio_pct99_in_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
pub ratio_pct98_in_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
pub ratio_pct95_in_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
pub ratio_pct5_in_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
pub ratio_pct2_in_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
pub ratio_pct1_in_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
pub ratio_sd: Option<ComputedStandardDeviationVecsFromDateIndex>,
pub ratio_4y_sd: Option<ComputedStandardDeviationVecsFromDateIndex>,
@@ -141,10 +141,10 @@ impl ComputedRatioVecsFromDateIndex {
)
.unwrap()
}),
ratio_p99: extended.then(|| {
ratio_pct99: extended.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_ratio_p99"),
&format!("{name}_ratio_pct99"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -152,10 +152,10 @@ impl ComputedRatioVecsFromDateIndex {
)
.unwrap()
}),
ratio_p98: extended.then(|| {
ratio_pct98: extended.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_ratio_p98"),
&format!("{name}_ratio_pct98"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -163,10 +163,10 @@ impl ComputedRatioVecsFromDateIndex {
)
.unwrap()
}),
ratio_p95: extended.then(|| {
ratio_pct95: extended.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_ratio_p95"),
&format!("{name}_ratio_pct95"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -174,10 +174,10 @@ impl ComputedRatioVecsFromDateIndex {
)
.unwrap()
}),
ratio_p5: extended.then(|| {
ratio_pct5: extended.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_ratio_p5"),
&format!("{name}_ratio_pct5"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -185,10 +185,10 @@ impl ComputedRatioVecsFromDateIndex {
)
.unwrap()
}),
ratio_p2: extended.then(|| {
ratio_pct2: extended.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_ratio_p2"),
&format!("{name}_ratio_pct2"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -196,10 +196,10 @@ impl ComputedRatioVecsFromDateIndex {
)
.unwrap()
}),
ratio_p1: extended.then(|| {
ratio_pct1: extended.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_ratio_p1"),
&format!("{name}_ratio_pct1"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -207,10 +207,10 @@ impl ComputedRatioVecsFromDateIndex {
)
.unwrap()
}),
ratio_p99_as_price: extended.then(|| {
ratio_pct99_in_usd: extended.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_ratio_p99_as_price"),
&format!("{name}_ratio_pct99_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -218,10 +218,10 @@ impl ComputedRatioVecsFromDateIndex {
)
.unwrap()
}),
ratio_p98_as_price: extended.then(|| {
ratio_pct98_in_usd: extended.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_ratio_p98_as_price"),
&format!("{name}_ratio_pct98_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -229,10 +229,10 @@ impl ComputedRatioVecsFromDateIndex {
)
.unwrap()
}),
ratio_p95_as_price: extended.then(|| {
ratio_pct95_in_usd: extended.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_ratio_p95_as_price"),
&format!("{name}_ratio_pct95_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -240,10 +240,10 @@ impl ComputedRatioVecsFromDateIndex {
)
.unwrap()
}),
ratio_p5_as_price: extended.then(|| {
ratio_pct5_in_usd: extended.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_ratio_p5_as_price"),
&format!("{name}_ratio_pct5_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -251,10 +251,10 @@ impl ComputedRatioVecsFromDateIndex {
)
.unwrap()
}),
ratio_p2_as_price: extended.then(|| {
ratio_pct2_in_usd: extended.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_ratio_p2_as_price"),
&format!("{name}_ratio_pct2_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -262,10 +262,10 @@ impl ComputedRatioVecsFromDateIndex {
)
.unwrap()
}),
ratio_p1_as_price: extended.then(|| {
ratio_pct1_in_usd: extended.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_ratio_p1_as_price"),
&format!("{name}_ratio_pct1_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -322,7 +322,7 @@ impl ComputedRatioVecsFromDateIndex {
exit: &Exit,
price_opt: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
) -> Result<()> {
let closes = price.timeindexes_to_close.dateindex.as_ref().unwrap();
let closes = price.timeindexes_to_price_close.dateindex.as_ref().unwrap();
let price = price_opt.unwrap_or_else(|| unsafe {
std::mem::transmute(&self.price.as_ref().unwrap().dateindex)
@@ -423,42 +423,42 @@ impl ComputedRatioVecsFromDateIndex {
.iter_at(starting_dateindex)
.try_for_each(|(index, ratio)| -> Result<()> {
if index < min_ratio_date {
self.ratio_p5
self.ratio_pct5
.as_mut()
.unwrap()
.dateindex
.as_mut()
.unwrap()
.forced_push_at(index, StoredF32::NAN, exit)?;
self.ratio_p2
self.ratio_pct2
.as_mut()
.unwrap()
.dateindex
.as_mut()
.unwrap()
.forced_push_at(index, StoredF32::NAN, exit)?;
self.ratio_p1
self.ratio_pct1
.as_mut()
.unwrap()
.dateindex
.as_mut()
.unwrap()
.forced_push_at(index, StoredF32::NAN, exit)?;
self.ratio_p95
self.ratio_pct95
.as_mut()
.unwrap()
.dateindex
.as_mut()
.unwrap()
.forced_push_at(index, StoredF32::NAN, exit)?;
self.ratio_p98
self.ratio_pct98
.as_mut()
.unwrap()
.dateindex
.as_mut()
.unwrap()
.forced_push_at(index, StoredF32::NAN, exit)?;
self.ratio_p99
self.ratio_pct99
.as_mut()
.unwrap()
.dateindex
@@ -470,42 +470,42 @@ impl ComputedRatioVecsFromDateIndex {
let pos = sorted.binary_search(&ratio).unwrap_or_else(|pos| pos);
sorted.insert(pos, ratio);
self.ratio_p1
self.ratio_pct1
.as_mut()
.unwrap()
.dateindex
.as_mut()
.unwrap()
.forced_push_at(index, get_percentile(&sorted, 0.01), exit)?;
self.ratio_p2
self.ratio_pct2
.as_mut()
.unwrap()
.dateindex
.as_mut()
.unwrap()
.forced_push_at(index, get_percentile(&sorted, 0.02), exit)?;
self.ratio_p5
self.ratio_pct5
.as_mut()
.unwrap()
.dateindex
.as_mut()
.unwrap()
.forced_push_at(index, get_percentile(&sorted, 0.05), exit)?;
self.ratio_p95
self.ratio_pct95
.as_mut()
.unwrap()
.dateindex
.as_mut()
.unwrap()
.forced_push_at(index, get_percentile(&sorted, 0.95), exit)?;
self.ratio_p98
self.ratio_pct98
.as_mut()
.unwrap()
.dateindex
.as_mut()
.unwrap()
.forced_push_at(index, get_percentile(&sorted, 0.98), exit)?;
self.ratio_p99
self.ratio_pct99
.as_mut()
.unwrap()
.dateindex
@@ -521,32 +521,32 @@ impl ComputedRatioVecsFromDateIndex {
.into_iter()
.try_for_each(|v| v.safe_flush(exit))?;
self.ratio_p1.as_mut().unwrap().compute_rest(
self.ratio_pct1.as_mut().unwrap().compute_rest(
starting_indexes,
exit,
None as Option<&EagerVec<_, _>>,
)?;
self.ratio_p2.as_mut().unwrap().compute_rest(
self.ratio_pct2.as_mut().unwrap().compute_rest(
starting_indexes,
exit,
None as Option<&EagerVec<_, _>>,
)?;
self.ratio_p5.as_mut().unwrap().compute_rest(
self.ratio_pct5.as_mut().unwrap().compute_rest(
starting_indexes,
exit,
None as Option<&EagerVec<_, _>>,
)?;
self.ratio_p95.as_mut().unwrap().compute_rest(
self.ratio_pct95.as_mut().unwrap().compute_rest(
starting_indexes,
exit,
None as Option<&EagerVec<_, _>>,
)?;
self.ratio_p98.as_mut().unwrap().compute_rest(
self.ratio_pct98.as_mut().unwrap().compute_rest(
starting_indexes,
exit,
None as Option<&EagerVec<_, _>>,
)?;
self.ratio_p99.as_mut().unwrap().compute_rest(
self.ratio_pct99.as_mut().unwrap().compute_rest(
starting_indexes,
exit,
None as Option<&EagerVec<_, _>>,
@@ -556,14 +556,14 @@ impl ComputedRatioVecsFromDateIndex {
std::mem::transmute(&self.price.as_ref().unwrap().dateindex)
});
self.ratio_p99_as_price.as_mut().unwrap().compute_all(
self.ratio_pct99_in_usd.as_mut().unwrap().compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self
.ratio_p99
.ratio_pct99
.as_ref()
.unwrap()
.dateindex
@@ -583,10 +583,10 @@ impl ComputedRatioVecsFromDateIndex {
},
)?;
let compute_as_price =
|as_price: Option<&mut ComputedVecsFromDateIndex<Dollars>>,
let compute_in_usd =
|in_usd: Option<&mut ComputedVecsFromDateIndex<Dollars>>,
source: Option<&ComputedVecsFromDateIndex<StoredF32>>| {
as_price.unwrap().compute_all(
in_usd.unwrap().compute_all(
indexer,
indexes,
starting_indexes,
@@ -607,12 +607,12 @@ impl ComputedRatioVecsFromDateIndex {
)
};
compute_as_price(self.ratio_p1_as_price.as_mut(), self.ratio_p1.as_ref())?;
compute_as_price(self.ratio_p2_as_price.as_mut(), self.ratio_p2.as_ref())?;
compute_as_price(self.ratio_p5_as_price.as_mut(), self.ratio_p5.as_ref())?;
compute_as_price(self.ratio_p95_as_price.as_mut(), self.ratio_p95.as_ref())?;
compute_as_price(self.ratio_p98_as_price.as_mut(), self.ratio_p98.as_ref())?;
compute_as_price(self.ratio_p99_as_price.as_mut(), self.ratio_p99.as_ref())?;
compute_in_usd(self.ratio_pct1_in_usd.as_mut(), self.ratio_pct1.as_ref())?;
compute_in_usd(self.ratio_pct2_in_usd.as_mut(), self.ratio_pct2.as_ref())?;
compute_in_usd(self.ratio_pct5_in_usd.as_mut(), self.ratio_pct5.as_ref())?;
compute_in_usd(self.ratio_pct95_in_usd.as_mut(), self.ratio_pct95.as_ref())?;
compute_in_usd(self.ratio_pct98_in_usd.as_mut(), self.ratio_pct98.as_ref())?;
compute_in_usd(self.ratio_pct99_in_usd.as_mut(), self.ratio_pct99.as_ref())?;
self.ratio_sd.as_mut().unwrap().compute_all(
indexer,
@@ -652,22 +652,22 @@ impl ComputedRatioVecsFromDateIndex {
fn mut_ratio_vecs(&mut self) -> Vec<&mut EagerVec<DateIndex, StoredF32>> {
[
self.ratio_p1
self.ratio_pct1
.as_mut()
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
self.ratio_p2
self.ratio_pct2
.as_mut()
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
self.ratio_p5
self.ratio_pct5
.as_mut()
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
self.ratio_p95
self.ratio_pct95
.as_mut()
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
self.ratio_p98
self.ratio_pct98
.as_mut()
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
self.ratio_p99
self.ratio_pct99
.as_mut()
.map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]),
]
@@ -686,22 +686,22 @@ impl ComputedRatioVecsFromDateIndex {
self.ratio_1y_sd.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_2y_sd.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_4y_sd.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_p1.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_p2.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_p5.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_p95.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_p98.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_p99.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_p1_as_price.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_p2_as_price.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_p5_as_price.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_p95_as_price
self.ratio_pct1.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_pct2.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_pct5.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_pct95.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_pct98.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_pct99.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_pct1_in_usd.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_pct2_in_usd.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_pct5_in_usd.as_ref().map_or(vec![], |v| v.vecs()),
self.ratio_pct95_in_usd
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.ratio_p98_as_price
self.ratio_pct98_in_usd
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.ratio_p99_as_price
self.ratio_pct99_in_usd
.as_ref()
.map_or(vec![], |v| v.vecs()),
]
@@ -16,7 +16,7 @@ pub struct ComputedStandardDeviationVecsFromDateIndex {
pub sma: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub sd: ComputedVecsFromDateIndex<StoredF32>,
pub _0sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub _0sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub p0_5sd: ComputedVecsFromDateIndex<StoredF32>,
pub p1sd: ComputedVecsFromDateIndex<StoredF32>,
pub p1_5sd: ComputedVecsFromDateIndex<StoredF32>,
@@ -29,18 +29,18 @@ pub struct ComputedStandardDeviationVecsFromDateIndex {
pub m2sd: ComputedVecsFromDateIndex<StoredF32>,
pub m2_5sd: ComputedVecsFromDateIndex<StoredF32>,
pub m3sd: ComputedVecsFromDateIndex<StoredF32>,
pub p0_5sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub p1sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub p1_5sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub p2sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub p2_5sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub p3sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub m0_5sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub m1sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub m1_5sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub m2sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub m2_5sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub m3sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub p0_5sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub p1sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub p1_5sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub p2sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub p2_5sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub p3sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub m0_5sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub m1sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub m1_5sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub m2sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub m2_5sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub m3sd_in_usd: ComputedVecsFromDateIndex<Dollars>,
pub zscore: ComputedVecsFromDateIndex<StoredF32>,
}
@@ -175,105 +175,105 @@ impl ComputedStandardDeviationVecsFromDateIndex {
indexes,
options,
)?,
_0sd_as_price: ComputedVecsFromDateIndex::forced_import(
_0sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_0sd_as_price"),
&format!("{name}_0sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
options,
)?,
p0_5sd_as_price: ComputedVecsFromDateIndex::forced_import(
p0_5sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_p0_5sd_as_price"),
&format!("{name}_p0_5sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
options,
)?,
p1sd_as_price: ComputedVecsFromDateIndex::forced_import(
p1sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_p1sd_as_price"),
&format!("{name}_p1sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
options,
)?,
p1_5sd_as_price: ComputedVecsFromDateIndex::forced_import(
p1_5sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_p1_5sd_as_price"),
&format!("{name}_p1_5sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
options,
)?,
p2sd_as_price: ComputedVecsFromDateIndex::forced_import(
p2sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_p2sd_as_price"),
&format!("{name}_p2sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
options,
)?,
p2_5sd_as_price: ComputedVecsFromDateIndex::forced_import(
p2_5sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_p2_5sd_as_price"),
&format!("{name}_p2_5sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
options,
)?,
p3sd_as_price: ComputedVecsFromDateIndex::forced_import(
p3sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_p3sd_as_price"),
&format!("{name}_p3sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
options,
)?,
m0_5sd_as_price: ComputedVecsFromDateIndex::forced_import(
m0_5sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_m0_5sd_as_price"),
&format!("{name}_m0_5sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
options,
)?,
m1sd_as_price: ComputedVecsFromDateIndex::forced_import(
m1sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_m1sd_as_price"),
&format!("{name}_m1sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
options,
)?,
m1_5sd_as_price: ComputedVecsFromDateIndex::forced_import(
m1_5sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_m1_5sd_as_price"),
&format!("{name}_m1_5sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
options,
)?,
m2sd_as_price: ComputedVecsFromDateIndex::forced_import(
m2sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_m2sd_as_price"),
&format!("{name}_m2sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
options,
)?,
m2_5sd_as_price: ComputedVecsFromDateIndex::forced_import(
m2_5sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_m2_5sd_as_price"),
&format!("{name}_m2_5sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
options,
)?,
m3sd_as_price: ComputedVecsFromDateIndex::forced_import(
m3sd_in_usd: ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_m3sd_as_price"),
&format!("{name}_m3sd_in_usd"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -297,7 +297,7 @@ impl ComputedStandardDeviationVecsFromDateIndex {
starting_indexes: &Indexes,
exit: &Exit,
source: &impl CollectableVec<DateIndex, StoredF32>,
source_as_price: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
source_in_usd: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
) -> Result<()> {
let min_date = DateIndex::try_from(Date::MIN_RATIO).unwrap();
@@ -326,7 +326,7 @@ impl ComputedStandardDeviationVecsFromDateIndex {
exit,
sma_opt,
source,
source_as_price,
source_in_usd,
)
}
@@ -339,7 +339,7 @@ impl ComputedStandardDeviationVecsFromDateIndex {
exit: &Exit,
sma_opt: Option<&impl AnyIterableVec<DateIndex, StoredF32>>,
source: &impl CollectableVec<DateIndex, StoredF32>,
source_as_price: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
source_in_usd: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
) -> Result<()> {
let sma = sma_opt.unwrap_or_else(|| unsafe {
std::mem::transmute(&self.sma.as_ref().unwrap().dateindex)
@@ -571,14 +571,14 @@ impl ComputedStandardDeviationVecsFromDateIndex {
},
)?;
let Some(price) = source_as_price else {
let Some(price) = source_in_usd else {
return Ok(());
};
let compute_as_price =
|as_price: &mut ComputedVecsFromDateIndex<Dollars>,
let compute_in_usd =
|in_usd: &mut ComputedVecsFromDateIndex<Dollars>,
mut iter: BoxedVecIterator<DateIndex, StoredF32>| {
as_price.compute_all(
in_usd.compute_all(
indexer,
indexes,
starting_indexes,
@@ -598,53 +598,53 @@ impl ComputedStandardDeviationVecsFromDateIndex {
)
};
compute_as_price(&mut self._0sd_as_price, sma.iter())?;
compute_as_price(
&mut self.p0_5sd_as_price,
compute_in_usd(&mut self._0sd_in_usd, sma.iter())?;
compute_in_usd(
&mut self.p0_5sd_in_usd,
self.p0_5sd.dateindex.as_ref().unwrap().iter(),
)?;
compute_as_price(
&mut self.p1sd_as_price,
compute_in_usd(
&mut self.p1sd_in_usd,
self.p1sd.dateindex.as_ref().unwrap().iter(),
)?;
compute_as_price(
&mut self.p1_5sd_as_price,
compute_in_usd(
&mut self.p1_5sd_in_usd,
self.p1_5sd.dateindex.as_ref().unwrap().iter(),
)?;
compute_as_price(
&mut self.p2sd_as_price,
compute_in_usd(
&mut self.p2sd_in_usd,
self.p2sd.dateindex.as_ref().unwrap().iter(),
)?;
compute_as_price(
&mut self.p2_5sd_as_price,
compute_in_usd(
&mut self.p2_5sd_in_usd,
self.p2_5sd.dateindex.as_ref().unwrap().iter(),
)?;
compute_as_price(
&mut self.p3sd_as_price,
compute_in_usd(
&mut self.p3sd_in_usd,
self.p3sd.dateindex.as_ref().unwrap().iter(),
)?;
compute_as_price(
&mut self.m0_5sd_as_price,
compute_in_usd(
&mut self.m0_5sd_in_usd,
self.m0_5sd.dateindex.as_ref().unwrap().iter(),
)?;
compute_as_price(
&mut self.m1sd_as_price,
compute_in_usd(
&mut self.m1sd_in_usd,
self.m1sd.dateindex.as_ref().unwrap().iter(),
)?;
compute_as_price(
&mut self.m1_5sd_as_price,
compute_in_usd(
&mut self.m1_5sd_in_usd,
self.m1_5sd.dateindex.as_ref().unwrap().iter(),
)?;
compute_as_price(
&mut self.m2sd_as_price,
compute_in_usd(
&mut self.m2sd_in_usd,
self.m2sd.dateindex.as_ref().unwrap().iter(),
)?;
compute_as_price(
&mut self.m2_5sd_as_price,
compute_in_usd(
&mut self.m2_5sd_in_usd,
self.m2_5sd.dateindex.as_ref().unwrap().iter(),
)?;
compute_as_price(
&mut self.m3sd_as_price,
compute_in_usd(
&mut self.m3sd_in_usd,
self.m3sd.dateindex.as_ref().unwrap().iter(),
)?;
@@ -685,19 +685,19 @@ impl ComputedStandardDeviationVecsFromDateIndex {
self.m2sd.vecs(),
self.m2_5sd.vecs(),
self.m3sd.vecs(),
self._0sd_as_price.vecs(),
self.p0_5sd_as_price.vecs(),
self.p1sd_as_price.vecs(),
self.p1_5sd_as_price.vecs(),
self.p2sd_as_price.vecs(),
self.p2_5sd_as_price.vecs(),
self.p3sd_as_price.vecs(),
self.m0_5sd_as_price.vecs(),
self.m1sd_as_price.vecs(),
self.m1_5sd_as_price.vecs(),
self.m2sd_as_price.vecs(),
self.m2_5sd_as_price.vecs(),
self.m3sd_as_price.vecs(),
self._0sd_in_usd.vecs(),
self.p0_5sd_in_usd.vecs(),
self.p1sd_in_usd.vecs(),
self.p1_5sd_in_usd.vecs(),
self.p2sd_in_usd.vecs(),
self.p2_5sd_in_usd.vecs(),
self.p3sd_in_usd.vecs(),
self.m0_5sd_in_usd.vecs(),
self.m1sd_in_usd.vecs(),
self.m1_5sd_in_usd.vecs(),
self.m2sd_in_usd.vecs(),
self.m2_5sd_in_usd.vecs(),
self.m3sd_in_usd.vecs(),
self.zscore.vecs(),
]
.into_iter()
@@ -138,10 +138,10 @@ impl ComputedValueVecsFromDateIndex {
}
let dateindex_to_bitcoin = self.bitcoin.dateindex.as_ref().unwrap();
let dateindex_to_close = price
let dateindex_to_price_close = price
.as_ref()
.unwrap()
.timeindexes_to_close
.timeindexes_to_price_close
.dateindex
.as_ref()
.unwrap();
@@ -156,7 +156,7 @@ impl ComputedValueVecsFromDateIndex {
v.compute_from_bitcoin(
starting_indexes.dateindex,
dateindex_to_bitcoin,
dateindex_to_close,
dateindex_to_price_close,
exit,
)
},
@@ -139,7 +139,7 @@ impl ComputedValueVecsFromHeight {
}
let height_to_bitcoin = self.bitcoin.height.as_ref().unwrap();
let height_to_close = &price.as_ref().unwrap().chainindexes_to_close.height;
let height_to_price_close = &price.as_ref().unwrap().chainindexes_to_price_close.height;
if let Some(dollars) = self.dollars.as_mut() {
dollars.compute_all(
@@ -151,7 +151,7 @@ impl ComputedValueVecsFromHeight {
v.compute_from_bitcoin(
starting_indexes.height,
height_to_bitcoin,
height_to_close,
height_to_price_close,
exit,
)
},
@@ -78,23 +78,25 @@ impl ComputedValueVecsFromTxindex {
version + VERSION,
bitcoin_txindex.boxed_clone(),
indexes.txindex_to_height.boxed_clone(),
price.chainindexes_to_close.height.boxed_clone(),
price.chainindexes_to_price_close.height.boxed_clone(),
|txindex: TxIndex,
txindex_to_btc_iter,
txindex_to_in_btc_iter,
txindex_to_height_iter,
height_to_close_iter| {
height_to_price_close_iter| {
let txindex = txindex.unwrap_to_usize();
txindex_to_btc_iter.next_at(txindex).and_then(|(_, value)| {
let btc = value.into_owned();
txindex_to_height_iter
.next_at(txindex)
.and_then(|(_, value)| {
let height = value.into_owned();
height_to_close_iter
.next_at(height.unwrap_to_usize())
.map(|(_, close)| *close.into_owned() * btc)
})
})
txindex_to_in_btc_iter
.next_at(txindex)
.and_then(|(_, value)| {
let btc = value.into_owned();
txindex_to_height_iter
.next_at(txindex)
.and_then(|(_, value)| {
let height = value.into_owned();
height_to_price_close_iter
.next_at(height.unwrap_to_usize())
.map(|(_, close)| *close.into_owned() * btc)
})
})
},
)
});
@@ -102,13 +102,13 @@ impl ComputedHeightValueVecs {
}
let height_to_bitcoin = &self.bitcoin;
let height_to_close = &price.as_ref().unwrap().chainindexes_to_close.height;
let height_to_price_close = &price.as_ref().unwrap().chainindexes_to_price_close.height;
if let Some(dollars) = self.dollars.as_mut() {
dollars.compute_from_bitcoin(
starting_indexes.height,
height_to_bitcoin,
height_to_close,
height_to_price_close,
exit,
)?;
}
+11 -2
View File
@@ -236,7 +236,7 @@ impl Vecs {
|index, _| Some(index),
);
Ok(Self {
let this = Self {
emptyoutputindex_to_emptyoutputindex,
inputindex_to_inputindex,
opreturnindex_to_opreturnindex,
@@ -472,7 +472,16 @@ impl Vecs {
)?,
db,
})
};
this.db.retain_regions(
this.vecs()
.into_iter()
.flat_map(|v| v.region_names())
.collect(),
)?;
Ok(this)
}
pub fn compute(
+32 -43
View File
@@ -1,6 +1,6 @@
#![doc = include_str!("../README.md")]
use std::path::Path;
use std::{path::Path, thread};
use brk_error::Result;
use brk_fetcher::Fetcher;
@@ -9,19 +9,17 @@ use brk_structs::Version;
use log::info;
use vecdb::{AnyCollectableVec, Exit, Format};
mod blocks;
mod chain;
mod cointime;
mod constants;
mod fetched;
mod grouped;
mod indexes;
mod market;
mod mining;
mod price;
mod stateful;
mod states;
mod traits;
mod transactions;
mod utils;
use indexes::Indexes;
@@ -33,11 +31,9 @@ use states::*;
pub struct Computer {
pub indexes: indexes::Vecs,
pub constants: constants::Vecs,
pub blocks: blocks::Vecs,
pub mining: mining::Vecs,
pub market: market::Vecs,
pub price: Option<price::Vecs>,
pub transactions: transactions::Vecs,
pub chain: chain::Vecs,
pub stateful: stateful::Vecs,
pub fetched: Option<fetched::Vecs>,
pub cointime: cointime::Vecs,
@@ -68,8 +64,6 @@ impl Computer {
});
Ok(Self {
blocks: blocks::Vecs::forced_import(&computed_path, VERSION + Version::ZERO, &indexes)?,
mining: mining::Vecs::forced_import(&computed_path, VERSION + Version::ZERO, &indexes)?,
constants: constants::Vecs::forced_import(
&computed_path,
VERSION + Version::ZERO,
@@ -83,7 +77,7 @@ impl Computer {
&indexes,
price.as_ref(),
)?,
transactions: transactions::Vecs::forced_import(
chain: chain::Vecs::forced_import(
&computed_path,
VERSION + Version::ZERO,
indexer,
@@ -115,14 +109,6 @@ impl Computer {
self.constants
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
info!("Computing blocks...");
self.blocks
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
info!("Computing mining...");
self.mining
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
if let Some(fetched) = self.fetched.as_mut() {
info!("Computing fetched...");
fetched.compute(indexer, &self.indexes, &starting_indexes, exit)?;
@@ -137,44 +123,49 @@ impl Computer {
)?;
}
info!("Computing transactions...");
self.transactions.compute(
indexer,
&self.indexes,
&starting_indexes,
self.price.as_ref(),
exit,
)?;
thread::scope(|scope| -> Result<()> {
let chain = scope.spawn(|| {
info!("Computing chain...");
self.chain.compute(
indexer,
&self.indexes,
&starting_indexes,
self.price.as_ref(),
exit,
)
});
if let Some(price) = self.price.as_ref() {
info!("Computing market...");
self.market.compute(
indexer,
&self.indexes,
price,
&mut self.transactions,
&starting_indexes,
exit,
)?;
}
let market = scope.spawn(|| -> Result<()> {
if let Some(price) = self.price.as_ref() {
info!("Computing market...");
self.market
.compute(indexer, &self.indexes, price, &starting_indexes, exit)?;
}
Ok(())
});
chain.join().unwrap()?;
market.join().unwrap()?;
Ok(())
})?;
info!("Computing stateful...");
self.stateful.compute(
indexer,
&self.indexes,
&self.transactions,
&self.chain,
self.price.as_ref(),
&self.market,
&mut starting_indexes,
exit,
)?;
info!("Computing cointime...");
self.cointime.compute(
indexer,
&self.indexes,
&starting_indexes,
self.price.as_ref(),
&self.transactions,
&self.chain,
&self.stateful,
exit,
)?;
@@ -186,10 +177,8 @@ impl Computer {
[
self.constants.vecs(),
self.indexes.vecs(),
self.blocks.vecs(),
self.mining.vecs(),
self.market.vecs(),
self.transactions.vecs(),
self.chain.vecs(),
self.stateful.vecs(),
self.cointime.vecs(),
self.fetched.as_ref().map_or(vec![], |v| v.vecs()),
File diff suppressed because it is too large Load Diff
-151
View File
@@ -1,151 +0,0 @@
use std::path::Path;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_structs::{DifficultyEpoch, HalvingEpoch, StoredF64, Version};
use vecdb::{AnyCollectableVec, Database, Exit, PAGE_SIZE, VecIterator};
use crate::grouped::Source;
use super::{
Indexes,
grouped::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, VecBuilderOptions},
indexes,
};
const VERSION: Version = Version::ZERO;
#[derive(Clone)]
pub struct Vecs {
db: Database,
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
pub indexes_to_difficultyepoch: ComputedVecsFromDateIndex<DifficultyEpoch>,
pub indexes_to_halvingepoch: ComputedVecsFromDateIndex<HalvingEpoch>,
}
impl Vecs {
pub fn forced_import(parent: &Path, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let db = Database::open(&parent.join("mining"))?;
db.set_min_len(PAGE_SIZE * 1_000_000)?;
Ok(Self {
indexes_to_difficulty: ComputedVecsFromHeight::forced_import(
&db,
"difficulty",
Source::None,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_difficultyepoch: ComputedVecsFromDateIndex::forced_import(
&db,
"difficultyepoch",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_halvingepoch: ComputedVecsFromDateIndex::forced_import(
&db,
"halvingepoch",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
db,
})
}
pub fn compute(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.compute_(indexer, indexes, starting_indexes, exit)?;
self.db.flush_then_punch()?;
Ok(())
}
fn compute_(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
let mut height_to_difficultyepoch_iter = indexes.height_to_difficultyepoch.into_iter();
self.indexes_to_difficultyepoch.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, indexes, starting_indexes, exit| {
let mut height_count_iter = indexes.dateindex_to_height_count.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&indexes.dateindex_to_first_height,
|(di, height, ..)| {
(
di,
height_to_difficultyepoch_iter.unwrap_get_inner(
height + (*height_count_iter.unwrap_get_inner(di) - 1),
),
)
},
exit,
)?;
Ok(())
},
)?;
let mut height_to_halvingepoch_iter = indexes.height_to_halvingepoch.into_iter();
self.indexes_to_halvingepoch.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, indexes, starting_indexes, exit| {
let mut height_count_iter = indexes.dateindex_to_height_count.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&indexes.dateindex_to_first_height,
|(di, height, ..)| {
(
di,
height_to_halvingepoch_iter.unwrap_get_inner(
height + (*height_count_iter.unwrap_get_inner(di) - 1),
),
)
},
exit,
)?;
Ok(())
},
)?;
self.indexes_to_difficulty.compute_rest(
indexes,
starting_indexes,
exit,
Some(&indexer.vecs.height_to_difficulty),
)?;
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
self.indexes_to_difficulty.vecs(),
self.indexes_to_difficultyepoch.vecs(),
self.indexes_to_halvingepoch.vecs(),
]
.into_iter()
.flatten()
.collect::<Vec<_>>()
}
}
File diff suppressed because it is too large Load Diff
@@ -11,7 +11,7 @@ use vecdb::{
use crate::{
Indexes,
grouped::{ComputedVecsFromHeight, Source, VecBuilderOptions},
indexes, market, price,
indexes, price,
stateful::{
common,
r#trait::{CohortVecs, DynCohortVecs},
@@ -29,8 +29,8 @@ pub struct Vecs {
pub inner: common::Vecs,
pub height_to_address_count: EagerVec<Height, StoredU64>,
pub indexes_to_address_count: ComputedVecsFromHeight<StoredU64>,
pub height_to_addr_count: EagerVec<Height, StoredU64>,
pub indexes_to_addr_count: ComputedVecsFromHeight<StoredU64>,
}
impl Vecs {
@@ -43,7 +43,7 @@ impl Vecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
states_path: Option<&Path>,
compute_relative_to_all: bool,
compute_rel_to_all: bool,
) -> Result<Self> {
let compute_dollars = price.is_some();
@@ -58,15 +58,15 @@ impl Vecs {
compute_dollars,
)
}),
height_to_address_count: EagerVec::forced_import(
height_to_addr_count: EagerVec::forced_import(
db,
&suffix("address_count"),
&suffix("addr_count"),
version + VERSION + Version::ZERO,
format,
)?,
indexes_to_address_count: ComputedVecsFromHeight::forced_import(
indexes_to_addr_count: ComputedVecsFromHeight::forced_import(
db,
&suffix("address_count"),
&suffix("addr_count"),
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -79,8 +79,8 @@ impl Vecs {
version,
indexes,
price,
compute_relative_to_all,
false,
compute_rel_to_all,
false,
)?,
})
@@ -90,7 +90,7 @@ impl Vecs {
impl DynCohortVecs for Vecs {
fn min_height_vecs_len(&self) -> usize {
[
self.height_to_address_count.len(),
self.height_to_addr_count.len(),
self.inner.min_height_vecs_len(),
]
.into_iter()
@@ -110,8 +110,8 @@ impl DynCohortVecs for Vecs {
self.starting_height = Some(starting_height);
if let Some(prev_height) = starting_height.decremented() {
self.state.as_mut().unwrap().address_count = *self
.height_to_address_count
self.state.as_mut().unwrap().addr_count = *self
.height_to_addr_count
.into_iter()
.unwrap_get_inner(prev_height);
}
@@ -120,9 +120,9 @@ impl DynCohortVecs for Vecs {
}
fn validate_computed_versions(&mut self, base_version: Version) -> Result<()> {
self.height_to_address_count
self.height_to_addr_count
.validate_computed_version_or_reset(
base_version + self.height_to_address_count.inner_version(),
base_version + self.height_to_addr_count.inner_version(),
)?;
self.inner.validate_computed_versions(base_version)
@@ -133,9 +133,9 @@ impl DynCohortVecs for Vecs {
return Ok(());
}
self.height_to_address_count.forced_push_at(
self.height_to_addr_count.forced_push_at(
height,
self.state.as_ref().unwrap().address_count.into(),
self.state.as_ref().unwrap().addr_count.into(),
exit,
)?;
@@ -162,7 +162,7 @@ impl DynCohortVecs for Vecs {
}
fn safe_flush_stateful_vecs(&mut self, height: Height, exit: &Exit) -> Result<()> {
self.height_to_address_count.safe_flush(exit)?;
self.height_to_addr_count.safe_flush(exit)?;
self.inner
.safe_flush_stateful_vecs(height, exit, &mut self.state.as_mut().unwrap().inner)
@@ -177,11 +177,11 @@ impl DynCohortVecs for Vecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.indexes_to_address_count.compute_rest(
self.indexes_to_addr_count.compute_rest(
indexes,
starting_indexes,
exit,
Some(&self.height_to_address_count),
Some(&self.height_to_addr_count),
)?;
self.inner
@@ -191,8 +191,8 @@ impl DynCohortVecs for Vecs {
fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
self.inner.vecs(),
self.indexes_to_address_count.vecs(),
vec![&self.height_to_address_count],
self.indexes_to_addr_count.vecs(),
vec![&self.height_to_addr_count],
]
.concat()
}
@@ -205,11 +205,11 @@ impl CohortVecs for Vecs {
others: &[&Self],
exit: &Exit,
) -> Result<()> {
self.height_to_address_count.compute_sum_of_others(
self.height_to_addr_count.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| &v.height_to_address_count)
.map(|v| &v.height_to_addr_count)
.collect::<Vec<_>>()
.as_slice(),
exit,
@@ -228,9 +228,10 @@ impl CohortVecs for Vecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &Indexes,
market: &market::Vecs,
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
exit: &Exit,
@@ -240,9 +241,10 @@ impl CohortVecs for Vecs {
indexes,
price,
starting_indexes,
market,
height_to_supply,
dateindex_to_supply,
height_to_market_cap,
dateindex_to_market_cap,
height_to_realized_cap,
dateindex_to_realized_cap,
exit,
@@ -10,7 +10,7 @@ use derive_deref::{Deref, DerefMut};
use vecdb::{AnyIterableVec, Database, Exit, Format};
use crate::{
Indexes, indexes, market, price,
Indexes, indexes, price,
stateful::{
address_cohort,
r#trait::{CohortVecs, DynCohortVecs},
@@ -520,9 +520,10 @@ impl Vecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &Indexes,
market: &market::Vecs,
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
exit: &Exit,
@@ -534,9 +535,10 @@ impl Vecs {
indexes,
price,
starting_indexes,
market,
height_to_supply,
dateindex_to_supply,
height_to_market_cap,
dateindex_to_market_cap,
height_to_realized_cap,
dateindex_to_realized_cap,
exit,
File diff suppressed because it is too large Load Diff
+257 -147
View File
@@ -18,15 +18,18 @@ use brk_structs::{
use log::info;
use rayon::prelude::*;
use vecdb::{
AnyCollectableVec, AnyStoredVec, AnyVec, CollectableVec, Database, EagerVec, Exit, Format,
GenericStoredVec, ImportOptions, PAGE_SIZE, RawVec, Reader, Stamp, StoredIndex, VecIterator,
AnyCloneableIterableVec, AnyCollectableVec, AnyStoredVec, AnyVec, CollectableVec, Database,
EagerVec, Exit, Format, GenericStoredVec, ImportOptions, LazyVecFrom1, PAGE_SIZE, RawVec,
Reader, Stamp, StoredIndex, VecIterator,
};
use crate::{
BlockState, Indexes, SupplyState, Transacted,
grouped::{ComputedValueVecsFromHeight, VecBuilderOptions},
grouped::{ComputedVecsFromHeight, Source},
indexes, market, price, transactions,
BlockState, Indexes, SupplyState, Transacted, chain,
grouped::{
ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source,
VecBuilderOptions,
},
indexes, price,
};
mod address_cohort;
@@ -70,18 +73,24 @@ pub struct Vecs {
pub height_to_unspendable_supply: EagerVec<Height, Sats>,
pub height_to_opreturn_supply: EagerVec<Height, Sats>,
pub addresstype_to_height_to_address_count: AddressTypeToHeightToAddressCount,
pub addresstype_to_height_to_empty_address_count: AddressTypeToHeightToAddressCount,
pub addresstype_to_height_to_addr_count: AddressTypeToHeightToAddressCount,
pub addresstype_to_height_to_empty_addr_count: AddressTypeToHeightToAddressCount,
// ---
// Computed
// ---
pub addresstype_to_indexes_to_address_count: AddressTypeToIndexesToAddressCount,
pub addresstype_to_indexes_to_empty_address_count: AddressTypeToIndexesToAddressCount,
pub addresstype_to_indexes_to_addr_count: AddressTypeToIndexesToAddressCount,
pub addresstype_to_indexes_to_empty_addr_count: AddressTypeToIndexesToAddressCount,
pub indexes_to_unspendable_supply: ComputedValueVecsFromHeight,
pub indexes_to_opreturn_supply: ComputedValueVecsFromHeight,
pub indexes_to_address_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_empty_address_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_addr_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_empty_addr_count: ComputedVecsFromHeight<StoredU64>,
pub height_to_market_cap: Option<LazyVecFrom1<Height, Dollars, Height, Dollars>>,
pub indexes_to_market_cap: Option<ComputedVecsFromDateIndex<Dollars>>,
pub loadedaddressindex_to_loadedaddressindex:
LazyVecFrom1<LoadedAddressIndex, LoadedAddressIndex, LoadedAddressIndex, LoadedAddressData>,
pub emptyaddressindex_to_emptyaddressindex:
LazyVecFrom1<EmptyAddressIndex, EmptyAddressIndex, EmptyAddressIndex, EmptyAddressData>,
}
const SAVED_STAMPED_CHANGES: u16 = 10;
@@ -103,7 +112,31 @@ impl Vecs {
let compute_dollars = price.is_some();
Ok(Self {
let utxo_cohorts =
utxo_cohorts::Vecs::forced_import(&db, version, format, indexes, price, &states_path)?;
let loadedaddressindex_to_loadedaddressdata = RawVec::forced_import_with(
ImportOptions::new(&db, "loadedaddressdata", version + VERSION + Version::ZERO)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?;
let emptyaddressindex_to_emptyaddressdata = RawVec::forced_import_with(
ImportOptions::new(&db, "emptyaddressdata", version + VERSION + Version::ZERO)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?;
let loadedaddressindex_to_loadedaddressindex = LazyVecFrom1::init(
"loadedaddressindex",
version + VERSION + Version::ZERO,
loadedaddressindex_to_loadedaddressdata.boxed_clone(),
|index, _| Some(index),
);
let emptyaddressindex_to_emptyaddressindex = LazyVecFrom1::init(
"emptyaddressindex",
version + VERSION + Version::ZERO,
emptyaddressindex_to_emptyaddressdata.boxed_clone(),
|index, _| Some(index),
);
let this = Self {
chain_state: RawVec::forced_import_with(
ImportOptions::new(&db, "chain", version + VERSION + Version::ZERO)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
@@ -137,115 +170,146 @@ impl Vecs {
compute_dollars,
indexes,
)?,
indexes_to_address_count: ComputedVecsFromHeight::forced_import(
indexes_to_addr_count: ComputedVecsFromHeight::forced_import(
&db,
"address_count",
"addr_count",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_empty_address_count: ComputedVecsFromHeight::forced_import(
indexes_to_empty_addr_count: ComputedVecsFromHeight::forced_import(
&db,
"empty_address_count",
"empty_addr_count",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
addresstype_to_height_to_address_count: AddressTypeToHeightToAddressCount::from(
height_to_market_cap: compute_dollars.then(|| {
LazyVecFrom1::init(
"market_cap",
version + VERSION + Version::ONE,
utxo_cohorts
.all
.1
.height_to_supply_value
.dollars
.as_ref()
.unwrap()
.boxed_clone(),
|height: Height, iter| {
iter.next_at(height.unwrap_to_usize()).map(|(_, value)| {
let d: Dollars = value.into_owned();
d
})
},
)
}),
indexes_to_market_cap: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
&db,
"market_cap",
Source::Compute,
version + VERSION + Version::TWO,
indexes,
VecBuilderOptions::default().add_last(),
)
.unwrap()
}),
addresstype_to_height_to_addr_count: AddressTypeToHeightToAddressCount::from(
ByAddressType {
p2pk65: EagerVec::forced_import_compressed(
&db,
"p2pk65_address_count",
"p2pk65_addr_count",
version + VERSION + Version::ZERO,
)?,
p2pk33: EagerVec::forced_import_compressed(
&db,
"p2pk33_address_count",
"p2pk33_addr_count",
version + VERSION + Version::ZERO,
)?,
p2pkh: EagerVec::forced_import_compressed(
&db,
"p2pkh_address_count",
"p2pkh_addr_count",
version + VERSION + Version::ZERO,
)?,
p2sh: EagerVec::forced_import_compressed(
&db,
"p2sh_address_count",
"p2sh_addr_count",
version + VERSION + Version::ZERO,
)?,
p2wpkh: EagerVec::forced_import_compressed(
&db,
"p2wpkh_address_count",
"p2wpkh_addr_count",
version + VERSION + Version::ZERO,
)?,
p2wsh: EagerVec::forced_import_compressed(
&db,
"p2wsh_address_count",
"p2wsh_addr_count",
version + VERSION + Version::ZERO,
)?,
p2tr: EagerVec::forced_import_compressed(
&db,
"p2tr_address_count",
"p2tr_addr_count",
version + VERSION + Version::ZERO,
)?,
p2a: EagerVec::forced_import_compressed(
&db,
"p2a_address_count",
"p2a_addr_count",
version + VERSION + Version::ZERO,
)?,
},
),
addresstype_to_height_to_empty_address_count: AddressTypeToHeightToAddressCount::from(
addresstype_to_height_to_empty_addr_count: AddressTypeToHeightToAddressCount::from(
ByAddressType {
p2pk65: EagerVec::forced_import_compressed(
&db,
"p2pk65_empty_address_count",
"p2pk65_empty_addr_count",
version + VERSION + Version::ZERO,
)?,
p2pk33: EagerVec::forced_import_compressed(
&db,
"p2pk33_empty_address_count",
"p2pk33_empty_addr_count",
version + VERSION + Version::ZERO,
)?,
p2pkh: EagerVec::forced_import_compressed(
&db,
"p2pkh_empty_address_count",
"p2pkh_empty_addr_count",
version + VERSION + Version::ZERO,
)?,
p2sh: EagerVec::forced_import_compressed(
&db,
"p2sh_empty_address_count",
"p2sh_empty_addr_count",
version + VERSION + Version::ZERO,
)?,
p2wpkh: EagerVec::forced_import_compressed(
&db,
"p2wpkh_empty_address_count",
"p2wpkh_empty_addr_count",
version + VERSION + Version::ZERO,
)?,
p2wsh: EagerVec::forced_import_compressed(
&db,
"p2wsh_empty_address_count",
"p2wsh_empty_addr_count",
version + VERSION + Version::ZERO,
)?,
p2tr: EagerVec::forced_import_compressed(
&db,
"p2tr_empty_address_count",
"p2tr_empty_addr_count",
version + VERSION + Version::ZERO,
)?,
p2a: EagerVec::forced_import_compressed(
&db,
"p2a_empty_address_count",
"p2a_empty_addr_count",
version + VERSION + Version::ZERO,
)?,
},
),
addresstype_to_indexes_to_address_count: AddressTypeToIndexesToAddressCount::from(
addresstype_to_indexes_to_addr_count: AddressTypeToIndexesToAddressCount::from(
ByAddressType {
p2pk65: ComputedVecsFromHeight::forced_import(
&db,
"p2pk65_address_count",
"p2pk65_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -253,7 +317,7 @@ impl Vecs {
)?,
p2pk33: ComputedVecsFromHeight::forced_import(
&db,
"p2pk33_address_count",
"p2pk33_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -261,7 +325,7 @@ impl Vecs {
)?,
p2pkh: ComputedVecsFromHeight::forced_import(
&db,
"p2pkh_address_count",
"p2pkh_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -269,7 +333,7 @@ impl Vecs {
)?,
p2sh: ComputedVecsFromHeight::forced_import(
&db,
"p2sh_address_count",
"p2sh_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -277,7 +341,7 @@ impl Vecs {
)?,
p2wpkh: ComputedVecsFromHeight::forced_import(
&db,
"p2wpkh_address_count",
"p2wpkh_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -285,7 +349,7 @@ impl Vecs {
)?,
p2wsh: ComputedVecsFromHeight::forced_import(
&db,
"p2wsh_address_count",
"p2wsh_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -293,7 +357,7 @@ impl Vecs {
)?,
p2tr: ComputedVecsFromHeight::forced_import(
&db,
"p2tr_address_count",
"p2tr_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -301,7 +365,7 @@ impl Vecs {
)?,
p2a: ComputedVecsFromHeight::forced_import(
&db,
"p2a_address_count",
"p2a_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -309,11 +373,11 @@ impl Vecs {
)?,
},
),
addresstype_to_indexes_to_empty_address_count: AddressTypeToIndexesToAddressCount::from(
addresstype_to_indexes_to_empty_addr_count: AddressTypeToIndexesToAddressCount::from(
ByAddressType {
p2pk65: ComputedVecsFromHeight::forced_import(
&db,
"p2pk65_empty_address_count",
"p2pk65_empty_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -321,7 +385,7 @@ impl Vecs {
)?,
p2pk33: ComputedVecsFromHeight::forced_import(
&db,
"p2pk33_empty_address_count",
"p2pk33_empty_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -329,7 +393,7 @@ impl Vecs {
)?,
p2pkh: ComputedVecsFromHeight::forced_import(
&db,
"p2pkh_empty_address_count",
"p2pkh_empty_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -337,7 +401,7 @@ impl Vecs {
)?,
p2sh: ComputedVecsFromHeight::forced_import(
&db,
"p2sh_empty_address_count",
"p2sh_empty_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -345,7 +409,7 @@ impl Vecs {
)?,
p2wpkh: ComputedVecsFromHeight::forced_import(
&db,
"p2wpkh_empty_address_count",
"p2wpkh_empty_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -353,7 +417,7 @@ impl Vecs {
)?,
p2wsh: ComputedVecsFromHeight::forced_import(
&db,
"p2wsh_empty_address_count",
"p2wsh_empty_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -361,7 +425,7 @@ impl Vecs {
)?,
p2tr: ComputedVecsFromHeight::forced_import(
&db,
"p2tr_empty_address_count",
"p2tr_empty_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -369,7 +433,7 @@ impl Vecs {
)?,
p2a: ComputedVecsFromHeight::forced_import(
&db,
"p2a_empty_address_count",
"p2a_empty_addr_count",
Source::None,
version + VERSION + Version::ZERO,
indexes,
@@ -377,14 +441,7 @@ impl Vecs {
)?,
},
),
utxo_cohorts: utxo_cohorts::Vecs::forced_import(
&db,
version,
format,
indexes,
price,
&states_path,
)?,
utxo_cohorts,
address_cohorts: address_cohorts::Vecs::forced_import(
&db,
version,
@@ -427,17 +484,22 @@ impl Vecs {
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?,
loadedaddressindex_to_loadedaddressdata: RawVec::forced_import_with(
ImportOptions::new(&db, "loadedaddressdata", version + VERSION + Version::ZERO)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?,
emptyaddressindex_to_emptyaddressdata: RawVec::forced_import_with(
ImportOptions::new(&db, "emptyaddressdata", version + VERSION + Version::ZERO)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?,
loadedaddressindex_to_loadedaddressdata,
emptyaddressindex_to_emptyaddressdata,
loadedaddressindex_to_loadedaddressindex,
emptyaddressindex_to_emptyaddressindex,
db,
})
};
this.db.retain_regions(
this.vecs()
.into_iter()
.flat_map(|v| v.region_names())
.collect(),
)?;
Ok(this)
}
#[allow(clippy::too_many_arguments)]
@@ -445,22 +507,13 @@ impl Vecs {
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
transactions: &transactions::Vecs,
chain: &chain::Vecs,
price: Option<&price::Vecs>,
market: &market::Vecs,
// Must take ownership as its indexes will be updated for this specific function
starting_indexes: &mut Indexes,
exit: &Exit,
) -> Result<()> {
self.compute_(
indexer,
indexes,
transactions,
price,
market,
starting_indexes,
exit,
)?;
self.compute_(indexer, indexes, chain, price, starting_indexes, exit)?;
self.db.flush_then_punch()?;
Ok(())
}
@@ -470,9 +523,8 @@ impl Vecs {
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
transactions: &transactions::Vecs,
chain: &chain::Vecs,
price: Option<&price::Vecs>,
market: &market::Vecs,
// Must take ownership as its indexes will be updated for this specific function
starting_indexes: &mut Indexes,
exit: &Exit,
@@ -487,8 +539,8 @@ impl Vecs {
let height_to_first_p2traddressindex = &indexer.vecs.height_to_first_p2traddressindex;
let height_to_first_p2wpkhaddressindex = &indexer.vecs.height_to_first_p2wpkhaddressindex;
let height_to_first_p2wshaddressindex = &indexer.vecs.height_to_first_p2wshaddressindex;
let height_to_output_count = transactions.indexes_to_output_count.height.unwrap_sum();
let height_to_input_count = transactions.indexes_to_input_count.height.unwrap_sum();
let height_to_output_count = chain.indexes_to_output_count.height.unwrap_sum();
let height_to_input_count = chain.indexes_to_input_count.height.unwrap_sum();
let inputindex_to_outputindex = &indexer.vecs.inputindex_to_outputindex;
let outputindex_to_value = &indexer.vecs.outputindex_to_value;
let txindex_to_height = &indexes.txindex_to_height;
@@ -496,23 +548,23 @@ impl Vecs {
let outputindex_to_txindex = &indexes.outputindex_to_txindex;
let outputindex_to_outputtype = &indexer.vecs.outputindex_to_outputtype;
let outputindex_to_typeindex = &indexer.vecs.outputindex_to_typeindex;
let height_to_unclaimed_rewards = transactions
let height_to_unclaimed_rewards = chain
.indexes_to_unclaimed_rewards
.sats
.height
.as_ref()
.unwrap();
let height_to_close = price
let height_to_price_close = price
.as_ref()
.map(|price| &price.chainindexes_to_close.height);
let dateindex_to_close = price
.map(|price| &price.chainindexes_to_price_close.height);
let dateindex_to_price_close = price
.as_ref()
.map(|price| price.timeindexes_to_close.dateindex.as_ref().unwrap());
.map(|price| price.timeindexes_to_price_close.dateindex.as_ref().unwrap());
let height_to_date_fixed = &indexes.height_to_date_fixed;
let dateindex_to_first_height = &indexes.dateindex_to_first_height;
let dateindex_to_height_count = &indexes.dateindex_to_height_count;
let mut height_to_close_iter = height_to_close.as_ref().map(|v| v.into_iter());
let mut height_to_price_close_iter = height_to_price_close.as_ref().map(|v| v.into_iter());
let mut height_to_timestamp_fixed_iter = height_to_timestamp_fixed.into_iter();
let base_version = Version::ZERO
@@ -536,10 +588,10 @@ impl Vecs {
+ outputindex_to_outputtype.version()
+ outputindex_to_typeindex.version()
+ height_to_unclaimed_rewards.version()
+ height_to_close
+ height_to_price_close
.as_ref()
.map_or(Version::ZERO, |v| v.version())
+ dateindex_to_close
+ dateindex_to_price_close
.as_ref()
.map_or(Version::ZERO, |v| v.version())
+ height_to_date_fixed.version()
@@ -635,12 +687,14 @@ impl Vecs {
.rollback_before(starting_height.into())?,
]
.into_iter()
.enumerate()
.map(|(i, s)| {
let h = Height::from(s).incremented();
dbg!((i, s, h));
h
})
// .enumerate()
// .map(|(i, s)| {
// let h = Height::from(s).incremented();
// // dbg!((i, s, h));
// h
// })
.map(Height::from)
.map(Height::incremented)
.collect::<BTreeSet<Height>>();
if set.len() == 1 {
@@ -687,7 +741,7 @@ impl Vecs {
.map(|(height, supply)| {
let height = Height::from(height);
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
let price = height_to_close_iter
let price = height_to_price_close_iter
.as_mut()
.map(|i| *i.unwrap_get_inner(height));
BlockState {
@@ -758,13 +812,14 @@ impl Vecs {
let mut height_to_output_count_iter = height_to_output_count.into_iter();
let mut height_to_input_count_iter = height_to_input_count.into_iter();
let mut height_to_unclaimed_rewards_iter = height_to_unclaimed_rewards.into_iter();
let mut dateindex_to_close_iter = dateindex_to_close.as_ref().map(|v| v.into_iter());
let mut dateindex_to_price_close_iter =
dateindex_to_price_close.as_ref().map(|v| v.into_iter());
let mut height_to_date_fixed_iter = height_to_date_fixed.into_iter();
let mut dateindex_to_first_height_iter = dateindex_to_first_height.into_iter();
let mut dateindex_to_height_count_iter = dateindex_to_height_count.into_iter();
let height_to_close_vec =
height_to_close.map(|height_to_close| height_to_close.collect().unwrap());
let height_to_price_close_vec = height_to_price_close
.map(|height_to_price_close| height_to_price_close.collect().unwrap());
let height_to_timestamp_fixed_vec = height_to_timestamp_fixed.collect().unwrap();
let outputindex_range_to_height = RangeMap::from(height_to_first_outputindex);
@@ -783,12 +838,12 @@ impl Vecs {
} else {
Sats::ZERO
};
let mut addresstype_to_address_count = AddressTypeToAddressCount::from((
&self.addresstype_to_height_to_address_count,
let mut addresstype_to_addr_count = AddressTypeToAddressCount::from((
&self.addresstype_to_height_to_addr_count,
starting_height,
));
let mut addresstype_to_empty_address_count = AddressTypeToAddressCount::from((
&self.addresstype_to_height_to_empty_address_count,
let mut addresstype_to_empty_addr_count = AddressTypeToAddressCount::from((
&self.addresstype_to_height_to_empty_addr_count,
starting_height,
));
@@ -833,7 +888,7 @@ impl Vecs {
.for_each(|(_, v)| v.state.as_mut().unwrap().reset_single_iteration_values());
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
let price = height_to_close_iter
let price = height_to_price_close_iter
.as_mut()
.map(|i| *i.unwrap_get_inner(height));
let first_outputindex = height_to_first_outputindex_iter
@@ -1101,8 +1156,8 @@ impl Vecs {
&mut addresstype_to_typeindex_to_loadedaddressdata,
&mut addresstype_to_typeindex_to_emptyaddressdata,
price,
&mut addresstype_to_address_count,
&mut addresstype_to_empty_address_count,
&mut addresstype_to_addr_count,
&mut addresstype_to_empty_addr_count,
&mut stored_or_new_addresstype_to_typeindex_to_addressdatawithsource,
);
@@ -1112,9 +1167,9 @@ impl Vecs {
&mut addresstype_to_typeindex_to_loadedaddressdata,
&mut addresstype_to_typeindex_to_emptyaddressdata,
price,
&mut addresstype_to_address_count,
&mut addresstype_to_empty_address_count,
height_to_close_vec.as_ref(),
&mut addresstype_to_addr_count,
&mut addresstype_to_empty_addr_count,
height_to_price_close_vec.as_ref(),
&height_to_timestamp_fixed_vec,
height,
timestamp,
@@ -1173,14 +1228,14 @@ impl Vecs {
self.height_to_opreturn_supply
.forced_push_at(height, opreturn_supply, exit)?;
self.addresstype_to_height_to_address_count.forced_push_at(
self.addresstype_to_height_to_addr_count.forced_push_at(
height,
&addresstype_to_address_count,
&addresstype_to_addr_count,
exit,
)?;
self.addresstype_to_height_to_empty_address_count
.forced_push_at(height, &addresstype_to_empty_address_count, exit)?;
self.addresstype_to_height_to_empty_addr_count
.forced_push_at(height, &addresstype_to_empty_addr_count, exit)?;
let date = height_to_date_fixed_iter.unwrap_get_inner(height);
let dateindex = DateIndex::try_from(date).unwrap();
@@ -1191,7 +1246,7 @@ impl Vecs {
let is_date_last_height = date_first_height
+ Height::from(date_height_count).decremented().unwrap()
== height;
let date_price = dateindex_to_close_iter
let date_price = dateindex_to_price_close_iter
.as_mut()
.map(|v| is_date_last_height.then(|| *v.unwrap_get_inner(dateindex)));
@@ -1254,7 +1309,7 @@ impl Vecs {
info!("Computing rest part 1...");
self.indexes_to_address_count.compute_all(
self.indexes_to_addr_count.compute_all(
indexer,
indexes,
starting_indexes,
@@ -1263,7 +1318,7 @@ impl Vecs {
v.compute_sum_of_others(
starting_indexes.height,
&self
.addresstype_to_height_to_address_count
.addresstype_to_height_to_addr_count
.as_typed_vec()
.into_iter()
.map(|(_, v)| v)
@@ -1274,7 +1329,7 @@ impl Vecs {
},
)?;
self.indexes_to_empty_address_count.compute_all(
self.indexes_to_empty_addr_count.compute_all(
indexer,
indexes,
starting_indexes,
@@ -1283,7 +1338,7 @@ impl Vecs {
v.compute_sum_of_others(
starting_indexes.height,
&self
.addresstype_to_height_to_empty_address_count
.addresstype_to_height_to_empty_addr_count
.as_typed_vec()
.into_iter()
.map(|(_, v)| v)
@@ -1311,18 +1366,18 @@ impl Vecs {
Some(&self.height_to_opreturn_supply),
)?;
self.addresstype_to_indexes_to_address_count.compute(
self.addresstype_to_indexes_to_addr_count.compute(
indexes,
starting_indexes,
exit,
&self.addresstype_to_height_to_address_count,
&self.addresstype_to_height_to_addr_count,
)?;
self.addresstype_to_indexes_to_empty_address_count.compute(
self.addresstype_to_indexes_to_empty_addr_count.compute(
indexes,
starting_indexes,
exit,
&self.addresstype_to_height_to_empty_address_count,
&self.addresstype_to_height_to_empty_addr_count,
)?;
self.utxo_cohorts
@@ -1331,6 +1386,33 @@ impl Vecs {
self.address_cohorts
.compute_rest_part1(indexer, indexes, price, starting_indexes, exit)?;
if let Some(indexes_to_market_cap) = self.indexes_to_market_cap.as_mut() {
indexes_to_market_cap.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_transform(
starting_indexes.dateindex,
self.utxo_cohorts
.all
.1
.indexes_to_supply
.dollars
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
|(i, v, ..)| (i, v),
exit,
)?;
Ok(())
},
)?;
}
info!("Computing rest part 2...");
let height_to_supply = &self
@@ -1348,6 +1430,11 @@ impl Vecs {
.bitcoin
.dateindex
.clone();
let height_to_market_cap = self.height_to_market_cap.clone();
let dateindex_to_market_cap = self
.indexes_to_market_cap
.as_ref()
.map(|v| v.dateindex.as_ref().unwrap().clone());
let height_to_realized_cap = self.utxo_cohorts.all.1.height_to_realized_cap.clone();
let dateindex_to_realized_cap = self
.utxo_cohorts
@@ -1357,6 +1444,8 @@ impl Vecs {
.as_ref()
.map(|v| v.dateindex.unwrap_last().clone());
let dateindex_to_supply_ref = dateindex_to_supply.as_ref().unwrap();
let height_to_market_cap_ref = height_to_market_cap.as_ref();
let dateindex_to_market_cap_ref = dateindex_to_market_cap.as_ref();
let height_to_realized_cap_ref = height_to_realized_cap.as_ref();
let dateindex_to_realized_cap_ref = dateindex_to_realized_cap.as_ref();
@@ -1365,9 +1454,10 @@ impl Vecs {
indexes,
price,
starting_indexes,
market,
height_to_supply,
dateindex_to_supply_ref,
height_to_market_cap_ref,
dateindex_to_market_cap_ref,
height_to_realized_cap_ref,
dateindex_to_realized_cap_ref,
exit,
@@ -1378,9 +1468,10 @@ impl Vecs {
indexes,
price,
starting_indexes,
market,
height_to_supply,
dateindex_to_supply_ref,
height_to_market_cap_ref,
dateindex_to_market_cap_ref,
height_to_realized_cap_ref,
dateindex_to_realized_cap_ref,
exit,
@@ -1585,11 +1676,11 @@ impl Vecs {
.try_for_each(|(_, v)| v.safe_flush_stateful_vecs(height, exit))?;
self.height_to_unspendable_supply.safe_flush(exit)?;
self.height_to_opreturn_supply.safe_flush(exit)?;
self.addresstype_to_height_to_address_count
self.addresstype_to_height_to_addr_count
.as_mut_vec()
.into_iter()
.try_for_each(|v| v.safe_flush(exit))?;
self.addresstype_to_height_to_empty_address_count
self.addresstype_to_height_to_empty_addr_count
.as_mut_vec()
.into_iter()
.try_for_each(|v| v.safe_flush(exit))?;
@@ -1787,23 +1878,42 @@ impl Vecs {
.collect::<Vec<_>>(),
self.indexes_to_unspendable_supply.vecs(),
self.indexes_to_opreturn_supply.vecs(),
self.indexes_to_address_count.vecs(),
self.indexes_to_empty_address_count.vecs(),
self.addresstype_to_indexes_to_address_count.vecs(),
self.addresstype_to_indexes_to_empty_address_count.vecs(),
self.addresstype_to_height_to_address_count
self.indexes_to_addr_count.vecs(),
self.indexes_to_empty_addr_count.vecs(),
self.addresstype_to_indexes_to_addr_count.vecs(),
self.indexes_to_market_cap
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.addresstype_to_indexes_to_empty_addr_count.vecs(),
self.addresstype_to_height_to_addr_count
.as_typed_vec()
.into_iter()
.map(|(_, v)| v as &dyn AnyCollectableVec)
.collect::<Vec<_>>(),
self.addresstype_to_height_to_empty_address_count
self.addresstype_to_height_to_empty_addr_count
.as_typed_vec()
.into_iter()
.map(|(_, v)| v as &dyn AnyCollectableVec)
.collect::<Vec<_>>(),
self.height_to_market_cap
.as_ref()
.map_or(vec![], |v| vec![v]),
vec![
&self.height_to_unspendable_supply,
&self.height_to_opreturn_supply,
&self.chain_state,
&self.p2pk33addressindex_to_anyaddressindex,
&self.p2pk65addressindex_to_anyaddressindex,
&self.p2pkhaddressindex_to_anyaddressindex,
&self.p2shaddressindex_to_anyaddressindex,
&self.p2traddressindex_to_anyaddressindex,
&self.p2wpkhaddressindex_to_anyaddressindex,
&self.p2wshaddressindex_to_anyaddressindex,
&self.p2aaddressindex_to_anyaddressindex,
&self.loadedaddressindex_to_loadedaddressdata,
&self.emptyaddressindex_to_emptyaddressdata,
&self.loadedaddressindex_to_loadedaddressindex,
&self.emptyaddressindex_to_emptyaddressindex,
],
]
.into_iter()
@@ -1824,8 +1934,8 @@ impl AddressTypeToVec<(TypeIndex, Sats)> {
WithAddressDataSource<EmptyAddressData>,
>,
price: Option<Dollars>,
addresstype_to_address_count: &mut ByAddressType<u64>,
addresstype_to_empty_address_count: &mut ByAddressType<u64>,
addresstype_to_addr_count: &mut ByAddressType<u64>,
addresstype_to_empty_addr_count: &mut ByAddressType<u64>,
stored_or_new_addresstype_to_typeindex_to_addressdatawithsource: &mut AddressTypeToTypeIndexTree<
WithAddressDataSource<LoadedAddressData>,
>,
@@ -1862,9 +1972,9 @@ impl AddressTypeToVec<(TypeIndex, Sats)> {
});
if is_new || from_any_empty {
(*addresstype_to_address_count.get_mut(_type).unwrap()) += 1;
(*addresstype_to_addr_count.get_mut(_type).unwrap()) += 1;
if from_any_empty {
(*addresstype_to_empty_address_count.get_mut(_type).unwrap()) -= 1;
(*addresstype_to_empty_addr_count.get_mut(_type).unwrap()) -= 1;
}
}
@@ -1924,9 +2034,9 @@ impl HeightToAddressTypeToVec<(TypeIndex, Sats)> {
WithAddressDataSource<EmptyAddressData>,
>,
price: Option<Dollars>,
addresstype_to_address_count: &mut ByAddressType<u64>,
addresstype_to_empty_address_count: &mut ByAddressType<u64>,
height_to_close_vec: Option<&Vec<brk_structs::Close<Dollars>>>,
addresstype_to_addr_count: &mut ByAddressType<u64>,
addresstype_to_empty_addr_count: &mut ByAddressType<u64>,
height_to_price_close_vec: Option<&Vec<brk_structs::Close<Dollars>>>,
height_to_timestamp_fixed_vec: &[Timestamp],
height: Height,
timestamp: Timestamp,
@@ -1935,7 +2045,7 @@ impl HeightToAddressTypeToVec<(TypeIndex, Sats)> {
>,
) -> Result<()> {
self.0.into_iter().try_for_each(|(prev_height, mut v)| {
let prev_price = height_to_close_vec
let prev_price = height_to_price_close_vec
.as_ref()
.map(|v| **v.get(prev_height.unwrap_to_usize()).unwrap());
@@ -1975,7 +2085,7 @@ impl HeightToAddressTypeToVec<(TypeIndex, Sats)> {
let amount = prev_amount.checked_sub(value).unwrap();
let will_be_empty = addressdata.outputs_len - 1 == 0;
let will_be_empty = addressdata.utxos - 1 == 0;
if will_be_empty
|| vecs.amount_range.get_mut(amount).0.clone()
@@ -1996,8 +2106,8 @@ impl HeightToAddressTypeToVec<(TypeIndex, Sats)> {
unreachable!()
}
(*addresstype_to_address_count.get_mut(_type).unwrap()) -= 1;
(*addresstype_to_empty_address_count.get_mut(_type).unwrap()) += 1;
(*addresstype_to_addr_count.get_mut(_type).unwrap()) -= 1;
(*addresstype_to_empty_addr_count.get_mut(_type).unwrap()) += 1;
let addressdata =
typeindex_to_loadedaddressdata.remove(&type_index).unwrap();
+3 -2
View File
@@ -3,7 +3,7 @@ use brk_indexer::Indexer;
use brk_structs::{Bitcoin, DateIndex, Dollars, Height, Version};
use vecdb::{AnyCollectableVec, AnyIterableVec, Exit};
use crate::{Indexes, indexes, market, price};
use crate::{Indexes, indexes, price};
pub trait DynCohortVecs: Send + Sync {
fn min_height_vecs_len(&self) -> usize;
@@ -54,9 +54,10 @@ pub trait CohortVecs: DynCohortVecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &Indexes,
market: &market::Vecs,
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
exit: &Exit,
@@ -6,7 +6,7 @@ use brk_structs::{Bitcoin, DateIndex, Dollars, Height, Version};
use vecdb::{AnyCollectableVec, AnyIterableVec, Database, Exit, Format};
use crate::{
Indexes, UTXOCohortState, indexes, market, price,
Indexes, UTXOCohortState, indexes, price,
stateful::{
common,
r#trait::{CohortVecs, DynCohortVecs},
@@ -32,8 +32,8 @@ impl Vecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
states_path: Option<&Path>,
compute_relative_to_all: bool,
ratio_extended: bool,
extended: bool,
compute_rel_to_all: bool,
compute_adjusted: bool,
) -> Result<Self> {
let compute_dollars = price.is_some();
@@ -56,8 +56,8 @@ impl Vecs {
version,
indexes,
price,
compute_relative_to_all,
ratio_extended,
extended,
compute_rel_to_all,
compute_adjusted,
)?,
})
@@ -158,9 +158,10 @@ impl CohortVecs for Vecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &Indexes,
market: &market::Vecs,
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
exit: &Exit,
@@ -170,9 +171,10 @@ impl CohortVecs for Vecs {
indexes,
price,
starting_indexes,
market,
height_to_supply,
dateindex_to_supply,
height_to_market_cap,
dateindex_to_market_cap,
height_to_realized_cap,
dateindex_to_realized_cap,
exit,
@@ -11,7 +11,7 @@ use derive_deref::{Deref, DerefMut};
use vecdb::{AnyIterableVec, Database, Exit, Format, StoredIndex};
use crate::{
Indexes, indexes, market, price,
Indexes, indexes, price,
stateful::r#trait::DynCohortVecs,
states::{BlockState, Transacted},
};
@@ -42,14 +42,14 @@ impl Vecs {
indexes,
price,
None,
false,
true,
false,
true,
)?,
term: ByTerm {
short: utxo_cohort::Vecs::forced_import(
db,
Some("short_term_holders"),
Some("sth"),
format,
version + VERSION + Version::ZERO,
indexes,
@@ -61,7 +61,7 @@ impl Vecs {
)?,
long: utxo_cohort::Vecs::forced_import(
db,
Some("long_term_holders"),
Some("lth"),
format,
version + VERSION + Version::ZERO,
indexes,
@@ -143,8 +143,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
p2pk33: utxo_cohort::Vecs::forced_import(
@@ -155,8 +155,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
p2pkh: utxo_cohort::Vecs::forced_import(
@@ -167,8 +167,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
p2sh: utxo_cohort::Vecs::forced_import(
@@ -179,8 +179,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
p2wpkh: utxo_cohort::Vecs::forced_import(
@@ -191,8 +191,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
p2wsh: utxo_cohort::Vecs::forced_import(
@@ -203,8 +203,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
p2tr: utxo_cohort::Vecs::forced_import(
@@ -215,8 +215,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
p2a: utxo_cohort::Vecs::forced_import(
@@ -227,8 +227,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
p2ms: utxo_cohort::Vecs::forced_import(
@@ -239,8 +239,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
empty: utxo_cohort::Vecs::forced_import(
@@ -251,8 +251,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
unknown: utxo_cohort::Vecs::forced_import(
@@ -263,8 +263,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
},
@@ -955,8 +955,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_1sat_to_10sats: utxo_cohort::Vecs::forced_import(
@@ -967,8 +967,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_10sats_to_100sats: utxo_cohort::Vecs::forced_import(
@@ -979,8 +979,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_100sats_to_1k_sats: utxo_cohort::Vecs::forced_import(
@@ -991,8 +991,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_1k_sats_to_10k_sats: utxo_cohort::Vecs::forced_import(
@@ -1003,8 +1003,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_10k_sats_to_100k_sats: utxo_cohort::Vecs::forced_import(
@@ -1015,8 +1015,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_100k_sats_to_1m_sats: utxo_cohort::Vecs::forced_import(
@@ -1027,8 +1027,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_1m_sats_to_10m_sats: utxo_cohort::Vecs::forced_import(
@@ -1039,8 +1039,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_10m_sats_to_1btc: utxo_cohort::Vecs::forced_import(
@@ -1051,8 +1051,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_1btc_to_10btc: utxo_cohort::Vecs::forced_import(
@@ -1063,8 +1063,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_10btc_to_100btc: utxo_cohort::Vecs::forced_import(
@@ -1075,8 +1075,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_100btc_to_1k_btc: utxo_cohort::Vecs::forced_import(
@@ -1087,8 +1087,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_1k_btc_to_10k_btc: utxo_cohort::Vecs::forced_import(
@@ -1099,8 +1099,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_10k_btc_to_100k_btc: utxo_cohort::Vecs::forced_import(
@@ -1111,8 +1111,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
_100k_btc_or_more: utxo_cohort::Vecs::forced_import(
@@ -1123,8 +1123,8 @@ impl Vecs {
indexes,
price,
Some(states_path),
true,
false,
true,
false,
)?,
},
@@ -1137,8 +1137,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_100sats: utxo_cohort::Vecs::forced_import(
@@ -1149,8 +1149,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_1k_sats: utxo_cohort::Vecs::forced_import(
@@ -1161,8 +1161,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_10k_sats: utxo_cohort::Vecs::forced_import(
@@ -1173,8 +1173,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_100k_sats: utxo_cohort::Vecs::forced_import(
@@ -1185,8 +1185,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_1m_sats: utxo_cohort::Vecs::forced_import(
@@ -1197,8 +1197,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_10m_sats: utxo_cohort::Vecs::forced_import(
@@ -1209,8 +1209,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_1btc: utxo_cohort::Vecs::forced_import(
@@ -1221,8 +1221,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_10btc: utxo_cohort::Vecs::forced_import(
@@ -1233,8 +1233,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_100btc: utxo_cohort::Vecs::forced_import(
@@ -1245,8 +1245,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_1k_btc: utxo_cohort::Vecs::forced_import(
@@ -1257,8 +1257,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_10k_btc: utxo_cohort::Vecs::forced_import(
@@ -1269,8 +1269,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_100k_btc: utxo_cohort::Vecs::forced_import(
@@ -1281,8 +1281,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
},
@@ -1295,8 +1295,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_10sats: utxo_cohort::Vecs::forced_import(
@@ -1307,8 +1307,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_100sats: utxo_cohort::Vecs::forced_import(
@@ -1319,8 +1319,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_1k_sats: utxo_cohort::Vecs::forced_import(
@@ -1331,8 +1331,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_10k_sats: utxo_cohort::Vecs::forced_import(
@@ -1343,8 +1343,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_100k_sats: utxo_cohort::Vecs::forced_import(
@@ -1355,8 +1355,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_1m_sats: utxo_cohort::Vecs::forced_import(
@@ -1367,8 +1367,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_10m_sats: utxo_cohort::Vecs::forced_import(
@@ -1379,8 +1379,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_1btc: utxo_cohort::Vecs::forced_import(
@@ -1391,8 +1391,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_10btc: utxo_cohort::Vecs::forced_import(
@@ -1403,8 +1403,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_100btc: utxo_cohort::Vecs::forced_import(
@@ -1415,8 +1415,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_1k_btc: utxo_cohort::Vecs::forced_import(
@@ -1427,8 +1427,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
_10k_btc: utxo_cohort::Vecs::forced_import(
@@ -1439,8 +1439,8 @@ impl Vecs {
indexes,
price,
None,
true,
false,
true,
false,
)?,
},
@@ -1754,9 +1754,10 @@ impl Vecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &Indexes,
market: &market::Vecs,
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
exit: &Exit,
@@ -1768,9 +1769,10 @@ impl Vecs {
indexes,
price,
starting_indexes,
market,
height_to_supply,
dateindex_to_supply,
height_to_market_cap,
dateindex_to_market_cap,
height_to_realized_cap,
dateindex_to_realized_cap,
exit,
@@ -9,14 +9,14 @@ use super::CohortState;
#[derive(Clone)]
pub struct AddressCohortState {
pub address_count: u64,
pub addr_count: u64,
pub inner: CohortState,
}
impl AddressCohortState {
pub fn new(path: &Path, name: &str, compute_dollars: bool) -> Self {
Self {
address_count: 0,
addr_count: 0,
inner: CohortState::new(path, name, compute_dollars),
}
}
@@ -44,14 +44,14 @@ impl AddressCohortState {
let prev_realized_price = compute_price.then(|| addressdata.realized_price());
let prev_supply_state = SupplyState {
utxos: addressdata.outputs_len as u64,
utxos: addressdata.utxos as u64,
value: addressdata.amount(),
};
addressdata.send(value, prev_price)?;
let supply_state = SupplyState {
utxos: addressdata.outputs_len as u64,
utxos: addressdata.utxos as u64,
value: addressdata.amount(),
};
@@ -79,14 +79,14 @@ impl AddressCohortState {
let prev_realized_price = compute_price.then(|| address_data.realized_price());
let prev_supply_state = SupplyState {
utxos: address_data.outputs_len as u64,
utxos: address_data.utxos as u64,
value: address_data.amount(),
};
address_data.receive(value, price);
let supply_state = SupplyState {
utxos: address_data.outputs_len as u64,
utxos: address_data.utxos as u64,
value: address_data.amount(),
};
@@ -99,7 +99,7 @@ impl AddressCohortState {
}
pub fn add(&mut self, addressdata: &LoadedAddressData) {
self.address_count += 1;
self.addr_count += 1;
self.inner.increment_(
&addressdata.into(),
addressdata.realized_cap,
@@ -108,7 +108,7 @@ impl AddressCohortState {
}
pub fn subtract(&mut self, addressdata: &LoadedAddressData) {
self.address_count = self.address_count.checked_sub(1).unwrap();
self.addr_count = self.addr_count.checked_sub(1).unwrap();
self.inner.decrement_(
&addressdata.into(),
addressdata.realized_cap,
@@ -283,7 +283,7 @@ impl CohortState {
}
}
Ordering::Equal => {
state.supply_even += sats;
state.supply_breakeven += sats;
}
}
};
+1 -1
View File
@@ -43,7 +43,7 @@ impl SubAssign<&SupplyState> for SupplyState {
impl From<&LoadedAddressData> for SupplyState {
fn from(value: &LoadedAddressData) -> Self {
Self {
utxos: value.outputs_len as u64,
utxos: value.utxos as u64,
value: value.amount(),
}
}
+3 -3
View File
@@ -3,7 +3,7 @@ use brk_structs::{Dollars, Sats};
#[derive(Debug, Default, Clone)]
pub struct UnrealizedState {
pub supply_in_profit: Sats,
pub supply_even: Sats,
pub supply_breakeven: Sats,
pub supply_in_loss: Sats,
pub unrealized_profit: Dollars,
pub unrealized_loss: Dollars,
@@ -12,7 +12,7 @@ pub struct UnrealizedState {
impl UnrealizedState {
pub const NAN: Self = Self {
supply_in_profit: Sats::ZERO,
supply_even: Sats::ZERO,
supply_breakeven: Sats::ZERO,
supply_in_loss: Sats::ZERO,
unrealized_profit: Dollars::NAN,
unrealized_loss: Dollars::NAN,
@@ -20,7 +20,7 @@ impl UnrealizedState {
pub const ZERO: Self = Self {
supply_in_profit: Sats::ZERO,
supply_even: Sats::ZERO,
supply_breakeven: Sats::ZERO,
supply_in_loss: Sats::ZERO,
unrealized_profit: Dollars::ZERO,
unrealized_loss: Dollars::ZERO,
+8 -8
View File
@@ -25,7 +25,7 @@
**Key-Value Storage (lookups):**
- Block hash prefixes → heights
- Transaction ID prefixes → transaction indices
- Transaction ID prefixes → transaction indices
- Address byte hashes → type indices
- Fast point queries by hash or address
@@ -60,7 +60,7 @@ let rpc = Box::leak(Box::new(Client::new(
// Create parser for Bitcoin Core block files
let parser = Parser::new(
Path::new("~/.bitcoin/blocks").to_path_buf(),
Path::new("./brk_data").to_path_buf(),
Some(Path::new("./brk_data").to_path_buf()),
rpc
);
@@ -85,19 +85,19 @@ use std::thread::sleep;
// Continuous indexing loop for real-time updates
loop {
let start_time = Instant::now();
// Index new blocks
let indexes = indexer.index(&parser, rpc, &exit, true)?;
println!("Indexed to height {} in {:?}",
println!("Indexed to height {} in {:?}",
indexes.height, start_time.elapsed());
// Check for exit signal
if exit.is_signaled() {
println!("Graceful shutdown requested");
break;
}
// Wait before next update cycle
sleep(Duration::from_secs(5 * 60));
}
@@ -187,4 +187,4 @@ pub struct Indexes {
---
*This README was generated by Claude Code*
*This README was generated by Claude Code*
+5 -5
View File
@@ -21,8 +21,8 @@ fn main() -> Result<()> {
let blocks_dir = bitcoin_dir.join("blocks");
let outputs_dir = Path::new("../../_outputs");
fs::create_dir_all(outputs_dir)?;
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
fs::create_dir_all(&outputs_dir)?;
// let outputs_dir = Path::new("/Volumes/WD_BLACK1/brk");
let rpc = Box::leak(Box::new(bitcoincore_rpc::Client::new(
@@ -33,11 +33,11 @@ fn main() -> Result<()> {
let exit = Exit::new();
exit.set_ctrlc_handler();
let parser = Parser::new(blocks_dir, outputs_dir.to_path_buf(), rpc);
let parser = Parser::new(blocks_dir, Some(outputs_dir.to_path_buf()), rpc);
fs::create_dir_all(outputs_dir)?;
fs::create_dir_all(&outputs_dir)?;
let mut indexer = Indexer::forced_import(outputs_dir)?;
let mut indexer = Indexer::forced_import(&outputs_dir)?;
loop {
let i = Instant::now();
+11 -19
View File
@@ -5,7 +5,7 @@ use std::{collections::BTreeMap, path::Path, str::FromStr, thread, time::Instant
use bitcoin::{Transaction, TxIn, TxOut};
use brk_error::{Error, Result};
use brk_parser::Parser;
use brk_parser::{BlockExtended, Parser};
use brk_store::AnyStore;
use brk_structs::{
AddressBytes, AddressBytesHash, BlockHash, BlockHashPrefix, Height, InputIndex, OutputIndex,
@@ -14,7 +14,7 @@ use brk_structs::{
};
use log::{error, info};
use rayon::prelude::*;
use vecdb::{AnyVec, Database, Exit, GenericStoredVec, PAGE_SIZE, Reader, VecIterator};
use vecdb::{AnyVec, Exit, GenericStoredVec, Reader, VecIterator};
mod indexes;
mod stores;
mod vecs;
@@ -29,7 +29,6 @@ const VERSION: Version = Version::ONE;
#[derive(Clone)]
pub struct Indexer {
pub db: Database,
pub vecs: Vecs,
pub stores: Stores,
}
@@ -38,18 +37,15 @@ impl Indexer {
pub fn forced_import(outputs_dir: &Path) -> Result<Self> {
info!("Importing indexer...");
let db = Database::open(&outputs_dir.join("indexed/vecs"))?;
db.set_min_len(PAGE_SIZE * 50_000_000)?;
info!("Opened database");
let path = outputs_dir.join("indexed");
let vecs = Vecs::forced_import(&db, VERSION + Version::ZERO)?;
let vecs = Vecs::forced_import(&path, VERSION + Version::ZERO)?;
info!("Imported vecs");
let stores =
Stores::forced_import(&outputs_dir.join("indexed/stores"), VERSION + Version::ZERO)?;
let stores = Stores::forced_import(&path, VERSION + Version::ZERO)?;
info!("Imported stores");
Ok(Self { vecs, stores, db })
Ok(Self { vecs, stores })
}
pub fn index(
@@ -59,16 +55,9 @@ impl Indexer {
exit: &Exit,
check_collisions: bool,
) -> Result<Indexes> {
let db = self.db.clone();
// dbg!(self.db.regions().id_to_index());
// dbg!(self.db.layout());
let starting_indexes = Indexes::try_from((&mut self.vecs, &self.stores, rpc))
.unwrap_or_else(|_report| Indexes::default());
// dbg!(&starting_indexes);
let lock = exit.lock();
self.stores
.rollback_if_needed(&mut self.vecs, &starting_indexes)?;
@@ -108,7 +97,6 @@ impl Indexer {
vecs.flush(height)?;
info!("Flushed vecs in {}s", i.elapsed().as_secs());
let i = Instant::now();
db.flush()?;
info!("Flushed db in {}s", i.elapsed().as_secs());
Ok(())
};
@@ -210,6 +198,10 @@ impl Indexer {
.blockhashprefix_to_height
.insert_if_needed(blockhash_prefix, height, height);
stores
.height_to_coinbase_tag
.insert_if_needed( height, block.coinbase_tag().into(), height);
vecs.height_to_blockhash.push_if_needed(height, blockhash)?;
vecs.height_to_difficulty
.push_if_needed(height, block.header.difficulty_float().into())?;
@@ -797,7 +789,7 @@ impl Indexer {
}
let i = Instant::now();
db.punch_holes()?;
self.vecs.punch_holes()?;
info!("Punched holes in db in {}s", i.elapsed().as_secs());
Ok(starting_indexes)
+46 -24
View File
@@ -4,11 +4,12 @@ use brk_error::Result;
use brk_store::{AnyStore, Store};
use brk_structs::{
AddressBytes, AddressBytesHash, BlockHashPrefix, ByAddressType, Height, OutputIndex,
OutputType, TxIndex, TxidPrefix, TypeIndex, TypeIndexWithOutputindex, Unit, Version,
OutputType, StoredString, TxIndex, TxidPrefix, TypeIndex, TypeIndexWithOutputindex, Unit,
Version,
};
use fjall::{PersistMode, TransactionalKeyspace};
use rayon::prelude::*;
use vecdb::VecIterator;
use vecdb::{AnyVec, StoredIndex, VecIterator};
use crate::Indexes;
@@ -20,6 +21,7 @@ pub struct Stores {
pub addressbyteshash_to_typeindex: Store<AddressBytesHash, TypeIndex>,
pub blockhashprefix_to_height: Store<BlockHashPrefix, Height>,
pub height_to_coinbase_tag: Store<Height, StoredString>,
pub txidprefix_to_txindex: Store<TxidPrefix, TxIndex>,
pub addresstype_to_typeindex_with_outputindex:
ByAddressType<Store<TypeIndexWithOutputindex, Unit>>,
@@ -28,14 +30,16 @@ pub struct Stores {
const VERSION: Version = Version::ZERO;
impl Stores {
pub fn forced_import(path: &Path, version: Version) -> Result<Self> {
fs::create_dir_all(path)?;
pub fn forced_import(parent: &Path, version: Version) -> Result<Self> {
let path = parent.join("stores");
let keyspace = match brk_store::open_keyspace(path) {
fs::create_dir_all(&path)?;
let keyspace = match brk_store::open_keyspace(&path) {
Ok(keyspace) => keyspace,
Err(_) => {
fs::remove_dir_all(path)?;
return Self::forced_import(path, version);
fs::remove_dir_all(&path)?;
return Self::forced_import(&path, version);
}
};
@@ -43,7 +47,7 @@ impl Stores {
let addressbyteshash_to_typeindex = scope.spawn(|| {
Store::import(
&keyspace,
path,
&path,
"addressbyteshash_to_typeindex",
version + VERSION + Version::ZERO,
None,
@@ -52,7 +56,7 @@ impl Stores {
let blockhashprefix_to_height = scope.spawn(|| {
Store::import(
&keyspace,
path,
&path,
"blockhashprefix_to_height",
version + VERSION + Version::ZERO,
None,
@@ -61,7 +65,7 @@ impl Stores {
let txidprefix_to_txindex = scope.spawn(|| {
Store::import(
&keyspace,
path,
&path,
"txidprefix_to_txindex",
version + VERSION + Version::ZERO,
None,
@@ -70,7 +74,7 @@ impl Stores {
let p2aaddressindex_with_outputindex = scope.spawn(|| {
Store::import(
&keyspace,
path,
&path,
"p2aaddressindex_with_outputindex",
version + VERSION + Version::ZERO,
Some(false),
@@ -79,7 +83,7 @@ impl Stores {
let p2pk33addressindex_with_outputindex = scope.spawn(|| {
Store::import(
&keyspace,
path,
&path,
"p2pk33addressindex_with_outputindex",
version + VERSION + Version::ZERO,
Some(false),
@@ -88,7 +92,7 @@ impl Stores {
let p2pk65addressindex_with_outputindex = scope.spawn(|| {
Store::import(
&keyspace,
path,
&path,
"p2pk65addressindex_with_outputindex",
version + VERSION + Version::ZERO,
Some(false),
@@ -97,7 +101,7 @@ impl Stores {
let p2pkhaddressindex_with_outputindex = scope.spawn(|| {
Store::import(
&keyspace,
path,
&path,
"p2pkhaddressindex_with_outputindex",
version + VERSION + Version::ZERO,
Some(false),
@@ -106,7 +110,7 @@ impl Stores {
let p2shaddressindex_with_outputindex = scope.spawn(|| {
Store::import(
&keyspace,
path,
&path,
"p2shaddressindex_with_outputindex",
version + VERSION + Version::ZERO,
Some(false),
@@ -115,7 +119,7 @@ impl Stores {
let p2traddressindex_with_outputindex = scope.spawn(|| {
Store::import(
&keyspace,
path,
&path,
"p2traddressindex_with_outputindex",
version + VERSION + Version::ZERO,
Some(false),
@@ -124,7 +128,7 @@ impl Stores {
let p2wpkhaddressindex_with_outputindex = scope.spawn(|| {
Store::import(
&keyspace,
path,
&path,
"p2wpkhaddressindex_with_outputindex",
version + VERSION + Version::ZERO,
Some(false),
@@ -133,16 +137,25 @@ impl Stores {
let p2wshaddressindex_with_outputindex = scope.spawn(|| {
Store::import(
&keyspace,
path,
&path,
"p2wshaddressindex_with_outputindex",
version + VERSION + Version::ZERO,
Some(false),
)
});
let height_to_coinbase_tag = Store::import(
&keyspace,
&path,
"height_to_coinbase_tag",
version + VERSION + Version::ZERO,
None,
)?;
Ok(Self {
keyspace: keyspace.clone(),
height_to_coinbase_tag,
addressbyteshash_to_typeindex: addressbyteshash_to_typeindex.join().unwrap()?,
blockhashprefix_to_height: blockhashprefix_to_height.join().unwrap()?,
txidprefix_to_txindex: txidprefix_to_txindex.join().unwrap()?,
@@ -182,11 +195,9 @@ impl Stores {
.map_err(|e| e.into())
}
fn as_slice(&self) -> [&(dyn AnyStore + Send + Sync); 11] {
fn as_slice(&self) -> [&(dyn AnyStore + Send + Sync); 12] {
[
&self.addressbyteshash_to_typeindex,
&self.blockhashprefix_to_height,
&self.txidprefix_to_txindex,
&self.addresstype_to_typeindex_with_outputindex.p2a,
&self.addresstype_to_typeindex_with_outputindex.p2pk33,
&self.addresstype_to_typeindex_with_outputindex.p2pk65,
@@ -195,14 +206,15 @@ impl Stores {
&self.addresstype_to_typeindex_with_outputindex.p2tr,
&self.addresstype_to_typeindex_with_outputindex.p2wpkh,
&self.addresstype_to_typeindex_with_outputindex.p2wsh,
&self.blockhashprefix_to_height,
&self.height_to_coinbase_tag,
&self.txidprefix_to_txindex,
]
}
fn as_mut_slice(&mut self) -> [&mut (dyn AnyStore + Send + Sync); 11] {
fn as_mut_slice(&mut self) -> [&mut (dyn AnyStore + Send + Sync); 12] {
[
&mut self.addressbyteshash_to_typeindex,
&mut self.blockhashprefix_to_height,
&mut self.txidprefix_to_txindex,
&mut self.addresstype_to_typeindex_with_outputindex.p2a,
&mut self.addresstype_to_typeindex_with_outputindex.p2pk33,
&mut self.addresstype_to_typeindex_with_outputindex.p2pk65,
@@ -211,6 +223,9 @@ impl Stores {
&mut self.addresstype_to_typeindex_with_outputindex.p2tr,
&mut self.addresstype_to_typeindex_with_outputindex.p2wpkh,
&mut self.addresstype_to_typeindex_with_outputindex.p2wsh,
&mut self.blockhashprefix_to_height,
&mut self.height_to_coinbase_tag,
&mut self.txidprefix_to_txindex,
]
}
@@ -222,6 +237,7 @@ impl Stores {
if self.addressbyteshash_to_typeindex.is_empty()?
&& self.blockhashprefix_to_height.is_empty()?
&& self.txidprefix_to_txindex.is_empty()?
&& self.height_to_coinbase_tag.is_empty()?
&& self
.addresstype_to_typeindex_with_outputindex
.p2a
@@ -266,6 +282,12 @@ impl Stores {
self.blockhashprefix_to_height.remove(blockhashprefix);
});
(starting_indexes.height.unwrap_to_usize()..vecs.height_to_blockhash.len())
.map(Height::from)
.for_each(|h| {
self.height_to_coinbase_tag.remove(h);
});
if let Some(mut index) = vecs
.height_to_first_p2pk65addressindex
.iter()
+74 -48
View File
@@ -1,3 +1,5 @@
use std::path::Path;
use brk_error::Result;
use brk_structs::{
AddressBytes, BlockHash, EmptyOutputIndex, Height, InputIndex, OpReturnIndex, OutputIndex,
@@ -9,7 +11,8 @@ use brk_structs::{
};
use rayon::prelude::*;
use vecdb::{
AnyCollectableVec, AnyStoredVec, CompressedVec, Database, GenericStoredVec, RawVec, Stamp,
AnyCollectableVec, AnyStoredVec, CompressedVec, Database, GenericStoredVec, PAGE_SIZE, RawVec,
Stamp,
};
use crate::Indexes;
@@ -18,6 +21,8 @@ const VERSION: Version = Version::ZERO;
#[derive(Clone)]
pub struct Vecs {
db: Database,
pub emptyoutputindex_to_txindex: CompressedVec<EmptyOutputIndex, TxIndex>,
pub height_to_blockhash: RawVec<Height, BlockHash>,
pub height_to_difficulty: CompressedVec<Height, StoredF64>,
@@ -67,225 +72,240 @@ pub struct Vecs {
}
impl Vecs {
pub fn forced_import(db: &Database, version: Version) -> Result<Self> {
Ok(Self {
pub fn forced_import(parent: &Path, version: Version) -> Result<Self> {
let db = Database::open(&parent.join("vecs"))?;
db.set_min_len(PAGE_SIZE * 50_000_000)?;
let this = Self {
emptyoutputindex_to_txindex: CompressedVec::forced_import(
db,
&db,
"txindex",
version + VERSION + Version::ZERO,
)?,
height_to_blockhash: RawVec::forced_import(
db,
&db,
"blockhash",
version + VERSION + Version::ZERO,
)?,
height_to_difficulty: CompressedVec::forced_import(
db,
&db,
"difficulty",
version + VERSION + Version::ZERO,
)?,
height_to_first_emptyoutputindex: CompressedVec::forced_import(
db,
&db,
"first_emptyoutputindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_inputindex: CompressedVec::forced_import(
db,
&db,
"first_inputindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_opreturnindex: CompressedVec::forced_import(
db,
&db,
"first_opreturnindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_outputindex: CompressedVec::forced_import(
db,
&db,
"first_outputindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_p2aaddressindex: CompressedVec::forced_import(
db,
&db,
"first_p2aaddressindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_p2msoutputindex: CompressedVec::forced_import(
db,
&db,
"first_p2msoutputindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_p2pk33addressindex: CompressedVec::forced_import(
db,
&db,
"first_p2pk33addressindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_p2pk65addressindex: CompressedVec::forced_import(
db,
&db,
"first_p2pk65addressindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_p2pkhaddressindex: CompressedVec::forced_import(
db,
&db,
"first_p2pkhaddressindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_p2shaddressindex: CompressedVec::forced_import(
db,
&db,
"first_p2shaddressindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_p2traddressindex: CompressedVec::forced_import(
db,
&db,
"first_p2traddressindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_p2wpkhaddressindex: CompressedVec::forced_import(
db,
&db,
"first_p2wpkhaddressindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_p2wshaddressindex: CompressedVec::forced_import(
db,
&db,
"first_p2wshaddressindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_txindex: CompressedVec::forced_import(
db,
&db,
"first_txindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_unknownoutputindex: CompressedVec::forced_import(
db,
&db,
"first_unknownoutputindex",
version + VERSION + Version::ZERO,
)?,
height_to_timestamp: CompressedVec::forced_import(
db,
&db,
"timestamp",
version + VERSION + Version::ZERO,
)?,
height_to_total_size: CompressedVec::forced_import(
db,
&db,
"total_size",
version + VERSION + Version::ZERO,
)?,
height_to_weight: CompressedVec::forced_import(
db,
&db,
"weight",
version + VERSION + Version::ZERO,
)?,
inputindex_to_outputindex: RawVec::forced_import(
db,
&db,
"outputindex",
version + VERSION + Version::ZERO,
)?,
opreturnindex_to_txindex: CompressedVec::forced_import(
db,
&db,
"txindex",
version + VERSION + Version::ZERO,
)?,
outputindex_to_outputtype: RawVec::forced_import(
db,
&db,
"outputtype",
version + VERSION + Version::ZERO,
)?,
outputindex_to_typeindex: RawVec::forced_import(
db,
&db,
"typeindex",
version + VERSION + Version::ZERO,
)?,
outputindex_to_value: RawVec::forced_import(
db,
&db,
"value",
version + VERSION + Version::ZERO,
)?,
p2aaddressindex_to_p2abytes: RawVec::forced_import(
db,
&db,
"p2abytes",
version + VERSION + Version::ZERO,
)?,
p2msoutputindex_to_txindex: CompressedVec::forced_import(
db,
&db,
"txindex",
version + VERSION + Version::ZERO,
)?,
p2pk33addressindex_to_p2pk33bytes: RawVec::forced_import(
db,
&db,
"p2pk33bytes",
version + VERSION + Version::ZERO,
)?,
p2pk65addressindex_to_p2pk65bytes: RawVec::forced_import(
db,
&db,
"p2pk65bytes",
version + VERSION + Version::ZERO,
)?,
p2pkhaddressindex_to_p2pkhbytes: RawVec::forced_import(
db,
&db,
"p2pkhbytes",
version + VERSION + Version::ZERO,
)?,
p2shaddressindex_to_p2shbytes: RawVec::forced_import(
db,
&db,
"p2shbytes",
version + VERSION + Version::ZERO,
)?,
p2traddressindex_to_p2trbytes: RawVec::forced_import(
db,
&db,
"p2trbytes",
version + VERSION + Version::ZERO,
)?,
p2wpkhaddressindex_to_p2wpkhbytes: RawVec::forced_import(
db,
&db,
"p2wpkhbytes",
version + VERSION + Version::ZERO,
)?,
p2wshaddressindex_to_p2wshbytes: RawVec::forced_import(
db,
&db,
"p2wshbytes",
version + VERSION + Version::ZERO,
)?,
txindex_to_base_size: CompressedVec::forced_import(
db,
&db,
"base_size",
version + VERSION + Version::ZERO,
)?,
txindex_to_first_inputindex: CompressedVec::forced_import(
db,
&db,
"first_inputindex",
version + VERSION + Version::ZERO,
)?,
txindex_to_first_outputindex: CompressedVec::forced_import(
db,
&db,
"first_outputindex",
version + VERSION + Version::ZERO,
)?,
txindex_to_is_explicitly_rbf: CompressedVec::forced_import(
db,
&db,
"is_explicitly_rbf",
version + VERSION + Version::ZERO,
)?,
txindex_to_rawlocktime: CompressedVec::forced_import(
db,
&db,
"rawlocktime",
version + VERSION + Version::ZERO,
)?,
txindex_to_total_size: CompressedVec::forced_import(
db,
&db,
"total_size",
version + VERSION + Version::ZERO,
)?,
txindex_to_txid: RawVec::forced_import(db, "txid", version + VERSION + Version::ZERO)?,
txindex_to_txid: RawVec::forced_import(&db, "txid", version + VERSION + Version::ZERO)?,
txindex_to_txversion: CompressedVec::forced_import(
db,
&db,
"txversion",
version + VERSION + Version::ZERO,
)?,
unknownoutputindex_to_txindex: CompressedVec::forced_import(
db,
&db,
"txindex",
version + VERSION + Version::ZERO,
)?,
})
db,
};
// self.db.retain_regions(
// this.vecs()
// .into_iter()
// .flat_map(|v| v.region_names())
// .collect(),
// )?;
Ok(this)
}
pub fn rollback_if_needed(&mut self, starting_indexes: &Indexes) -> Result<()> {
@@ -438,6 +458,7 @@ impl Vecs {
self.mut_vecs()
.into_par_iter()
.try_for_each(|vec| vec.stamped_flush(Stamp::from(height)))?;
self.db.flush()?;
Ok(())
}
@@ -452,6 +473,11 @@ impl Vecs {
.unwrap()
}
pub fn punch_holes(&self) -> Result<()> {
self.db.punch_holes()?;
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
vec![
&self.emptyoutputindex_to_txindex,
+1
View File
@@ -21,3 +21,4 @@ serde = { workspace = true }
serde_json = { workspace = true }
serde_with = "3.14.0"
tabled = "0.20.0"
nucleo-matcher = "0.3.1"
+20 -6
View File
@@ -2,11 +2,11 @@ use std::fmt::{self, Debug};
use brk_error::Error;
use brk_structs::{
DateIndex, DecadeIndex, DifficultyEpoch, EmptyOutputIndex, HalvingEpoch, Height, InputIndex,
MonthIndex, OpReturnIndex, OutputIndex, P2AAddressIndex, P2MSOutputIndex, P2PK33AddressIndex,
P2PK65AddressIndex, P2PKHAddressIndex, P2SHAddressIndex, P2TRAddressIndex, P2WPKHAddressIndex,
P2WSHAddressIndex, Printable, QuarterIndex, SemesterIndex, TxIndex, UnknownOutputIndex,
WeekIndex, YearIndex,
DateIndex, DecadeIndex, DifficultyEpoch, EmptyAddressIndex, EmptyOutputIndex, HalvingEpoch,
Height, InputIndex, LoadedAddressIndex, MonthIndex, OpReturnIndex, OutputIndex,
P2AAddressIndex, P2MSOutputIndex, P2PK33AddressIndex, P2PK65AddressIndex, P2PKHAddressIndex,
P2SHAddressIndex, P2TRAddressIndex, P2WPKHAddressIndex, P2WSHAddressIndex, Printable,
QuarterIndex, SemesterIndex, TxIndex, UnknownOutputIndex, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use serde::Deserialize;
@@ -63,10 +63,14 @@ pub enum Index {
WeekIndex,
#[schemars(description = "Year index")]
YearIndex,
#[schemars(description = "Loaded Address Index")]
LoadedAddressIndex,
#[schemars(description = "Empty Address Index")]
EmptyAddressIndex,
}
impl Index {
pub fn all() -> [Self; 25] {
pub fn all() -> [Self; 27] {
[
Self::DateIndex,
Self::DecadeIndex,
@@ -93,6 +97,8 @@ impl Index {
Self::UnknownOutputIndex,
Self::WeekIndex,
Self::YearIndex,
Self::LoadedAddressIndex,
Self::EmptyAddressIndex,
]
}
@@ -123,6 +129,8 @@ impl Index {
Self::UnknownOutputIndex => UnknownOutputIndex::to_possible_strings(),
Self::WeekIndex => WeekIndex::to_possible_strings(),
Self::YearIndex => YearIndex::to_possible_strings(),
Self::LoadedAddressIndex => LoadedAddressIndex::to_possible_strings(),
Self::EmptyAddressIndex => EmptyAddressIndex::to_possible_strings(),
}
}
@@ -186,6 +194,12 @@ impl TryFrom<&str> for Index {
v if (Self::UnknownOutputIndex).possible_values().contains(&v) => {
Self::UnknownOutputIndex
}
v if (Self::LoadedAddressIndex).possible_values().contains(&v) => {
Self::LoadedAddressIndex
}
v if (Self::EmptyAddressIndex).possible_values().contains(&v) => {
Self::EmptyAddressIndex
}
_ => return Err(Error::Str("Bad index")),
})
}
+64 -33
View File
@@ -3,9 +3,13 @@
use std::collections::BTreeMap;
use brk_computer::Computer;
use brk_error::Result;
use brk_error::{Error, Result};
use brk_indexer::Indexer;
use brk_structs::Height;
use nucleo_matcher::{
Config, Matcher,
pattern::{AtomKind, CaseMatching, Normalization, Pattern},
};
use tabled::settings::Style;
use vecdb::{AnyCollectableVec, AnyStoredVec};
@@ -53,38 +57,65 @@ impl<'a> Interface<'a> {
Height::from(self.indexer.vecs.height_to_blockhash.stamp())
}
pub fn search(&self, params: &Params) -> Vec<(String, &&dyn AnyCollectableVec)> {
let tuples = params
.ids
.iter()
.flat_map(|s| {
s.to_lowercase()
.replace("-", "_")
.split_whitespace()
.flat_map(|s| {
s.split(',')
.flat_map(|s| s.split('+').map(|s| s.to_string()))
})
.collect::<Vec<_>>()
})
.map(|mut id| {
let mut res = self.vecs.id_to_index_to_vec.get(id.as_str());
if res.is_none()
&& let Ok(index) = Index::try_from(id.as_str())
{
id = index.possible_values().last().unwrap().to_string();
res = self.vecs.id_to_index_to_vec.get(id.as_str())
}
(id, res)
})
.filter(|(_, opt)| opt.is_some())
.map(|(id, vec)| (id, vec.unwrap()))
.collect::<Vec<_>>();
pub fn search(&self, params: &Params) -> Result<Vec<(String, &&dyn AnyCollectableVec)>> {
let ids_to_vec = self
.vecs
.index_to_id_to_vec
.get(&params.index)
.ok_or(Error::String(format!(
"Index \"{}\" isn't a valid index",
params.index
)))?;
tuples
.iter()
.flat_map(|(str, i_to_v)| i_to_v.get(&params.index).map(|vec| (str.to_owned(), vec)))
.collect::<Vec<_>>()
let maybe_ids = params.ids.iter().flat_map(|s| {
s.to_lowercase()
.replace("-", "_")
.split_whitespace()
.flat_map(|s| {
s.split(',')
.flat_map(|s| s.split('+').map(|s| s.to_string()))
})
.collect::<Vec<_>>()
});
maybe_ids
.map(|id| {
let vec = ids_to_vec.get(id.as_str()).ok_or_else(|| {
let mut message = format!(
"No vec named \"{}\" indexed by \"{}\" found.\n",
// tell if id found in another index
id,
params.index
);
let mut matcher = Matcher::new(Config::DEFAULT);
let matches = Pattern::new(
id.as_str(),
CaseMatching::Ignore,
Normalization::Smart,
AtomKind::Fuzzy,
)
.match_list(ids_to_vec.keys(), &mut matcher)
.into_iter()
.take(10)
.map(|(s, _)| s)
.collect::<Vec<_>>();
if !matches.is_empty() {
message +=
&format!("\nMaybe you meant one of the following: {matches:#?} ?\n");
}
if let Some(index_to_vec) = self.id_to_index_to_vec().get(id.as_str()) {
message += &format!("\nBut there is a vec named {id} which supports the following indexes: {:#?}\n", index_to_vec.keys());
}
Error::String(message)
});
vec.map(|vec| (id, vec))
})
.collect::<Result<Vec<_>>>()
}
pub fn format(
@@ -183,7 +214,7 @@ impl<'a> Interface<'a> {
}
pub fn search_and_format(&self, params: Params) -> Result<Output> {
self.format(self.search(&params), &params.rest)
self.format(self.search(&params)?, &params.rest)
}
pub fn id_to_index_to_vec(&self) -> &BTreeMap<&str, IndexToVec<'_>> {
+2
View File
@@ -4,6 +4,8 @@
`brk_mcp` provides a Model Context Protocol server that enables Large Language Models (LLMs) to access Bitcoin blockchain data through BRK's interface layer. It implements the MCP specification to expose BRK's analytics capabilities as tools that LLMs can call.
Try it out: [https://bitview.space/mcp](https://bitview.space/mcp)
## What it provides
- **MCP Server Implementation**: Standards-compliant Model Context Protocol server
+6 -6
View File
@@ -8,7 +8,7 @@
- **Sequential block access**: Blocks delivered in height order (0, 1, 2, ...) regardless of physical file storage
- **Fork filtering**: Automatically excludes orphaned blocks using Bitcoin Core RPC verification
- **XOR encryption support**: Transparently handles XOR-encrypted block files
- **XOR encryption support**: Transparently handles XOR-encrypted block files
- **High performance**: Multi-threaded parsing with ~500MB peak memory usage
- **State persistence**: Caches parsing state for fast restarts
@@ -47,7 +47,7 @@ let rpc = Box::leak(Box::new(Client::new(
// Create parser
let parser = Parser::new(
Path::new("~/.bitcoin/blocks").to_path_buf(),
Path::new("./output").to_path_buf(),
Some(Path::new("./output").to_path_buf()),
rpc,
);
@@ -90,7 +90,7 @@ use bitcoin::Block;
fn analyze_blockchain(parser: &Parser) {
let mut total_transactions = 0;
let mut total_outputs = 0;
parser.parse(None, None)
.iter()
.for_each(|(height, block, _hash)| {
@@ -98,12 +98,12 @@ fn analyze_blockchain(parser: &Parser) {
total_outputs += block.txdata.iter()
.map(|tx| tx.output.len())
.sum::<usize>();
if height.0 % 10000 == 0 {
println!("Processed {} blocks", height);
}
});
println!("Total transactions: {}", total_transactions);
println!("Total outputs: {}", total_outputs);
}
@@ -150,4 +150,4 @@ The parser saves parsing state in `{output_dir}/blk_index_to_blk_recap.json` con
---
*This README was generated by Claude Code*
*This README was generated by Claude Code*
+22 -7
View File
@@ -8,24 +8,26 @@ use brk_structs::Height;
fn main() -> Result<()> {
let i = std::time::Instant::now();
let bitcoin_dir = Path::new("").join("");
let brk_dir = Path::new("").join("");
let bitcoin_dir = Path::new(&std::env::var("HOME").unwrap())
.join("Library")
.join("Application Support")
.join("Bitcoin");
let brk_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
let rpc = Box::leak(Box::new(Client::new(
"http://localhost:8332",
Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?));
let parser = Parser::new(bitcoin_dir.join("blocks"), Some(brk_dir), rpc);
let start = None;
let end = None;
let parser = Parser::new(bitcoin_dir.join("blocks"), brk_dir, rpc);
parser
.parse(start, end)
.iter()
.for_each(|(height, _block, hash)| {
println!("{height}: {hash}");
println!("{height}: {}", hash);
});
let block_0 = parser.get(Height::new(0));
@@ -42,7 +44,20 @@ fn main() -> Result<()> {
.script_pubkey
);
let block_840_000 = parser.get(Height::new(840_000));
let block_158251 = parser.get(Height::new(158251));
println!(
"{}",
block_158251
.txdata
.first()
.unwrap()
.output
.first()
.unwrap()
.script_pubkey
);
let block_840_000 = parser.get(Height::new(840_004));
println!(
"{}",
+1 -1
View File
@@ -21,7 +21,7 @@ fn main() {
// let start = None;
// let end = None;
let parser = Parser::new(bitcoin_dir.join("blocks"), brk_dir, rpc);
let parser = Parser::new(bitcoin_dir.join("blocks"), Some(brk_dir), rpc);
// parser
// .parse(start, end)
+19
View File
@@ -0,0 +1,19 @@
use bitcoin::Block;
pub trait BlockExtended {
fn coinbase_tag(&self) -> String;
}
impl BlockExtended for Block {
fn coinbase_tag(&self) -> String {
let Some(input) = self.txdata.first().and_then(|tx| tx.input.first()) else {
return String::new();
};
let bytes = input.script_sig.as_bytes();
String::from_utf8_lossy(bytes)
.chars()
.filter(|&c| c != '\u{FFFD}' && (c >= ' ' || c == '\n' || c == '\r' || c == '\t'))
.take(1_024)
.collect()
}
}
+9 -4
View File
@@ -14,6 +14,7 @@ mod blk_index_to_blk_path;
mod blk_index_to_blk_recap;
mod blk_metadata;
mod blk_recap;
mod block;
mod block_state;
mod error;
mod utils;
@@ -22,6 +23,7 @@ mod xor_index;
use blk_index_to_blk_recap::*;
use blk_metadata::*;
pub use block::*;
use block_state::*;
pub use error::*;
use utils::*;
@@ -35,14 +37,14 @@ const BOUND_CAP: usize = 50;
pub struct Parser {
blocks_dir: PathBuf,
outputs_dir: PathBuf,
outputs_dir: Option<PathBuf>,
rpc: &'static bitcoincore_rpc::Client,
}
impl Parser {
pub fn new(
blocks_dir: PathBuf,
outputs_dir: PathBuf,
outputs_dir: Option<PathBuf>,
rpc: &'static bitcoincore_rpc::Client,
) -> Self {
Self {
@@ -79,8 +81,11 @@ impl Parser {
let blk_index_to_blk_path = BlkIndexToBlkPath::scan(blocks_dir);
let (mut blk_index_to_blk_recap, blk_index) =
BlkIndexToBlkRecap::import(&self.outputs_dir, &blk_index_to_blk_path, start);
let (mut blk_index_to_blk_recap, blk_index) = BlkIndexToBlkRecap::import(
self.outputs_dir.as_ref().unwrap(),
&blk_index_to_blk_path,
start,
);
let xor_bytes = XORBytes::from(blocks_dir);
+9 -7
View File
@@ -4,6 +4,8 @@
`brk_server` provides a high-performance HTTP server that exposes BRK's indexed blockchain data and computed analytics through a comprehensive REST API. It offers multiple output formats, intelligent caching, compression, and optional web interface serving.
URL: [`https://bitview.space/api`](https://bitview.space/api)
## What it provides
- **REST API**: Vector-based data access with flexible querying and pagination
@@ -60,26 +62,26 @@ server.serve(true).await?;
```bash
# Latest 100 price values
curl "http://brekit.org/api/vecs/date-to-close?from=-100"
curl "https://bitview.space/api/vecs/date-to-close?from=-100"
# First 50 difficulty values as CSV
curl "http://brekit.org/api/vecs/height-to-difficulty?count=50&format=csv"
curl "https://bitview.space/api/vecs/height-to-difficulty?count=50&format=csv"
# Range from block 800,000 to 800,100
curl "https://brekit.org/api/vecs/height-to-timestamp?from=800000&to=800100"
curl "https://bitview.space/api/vecs/height-to-timestamp?from=800000&to=800100"
```
#### Multi-Vector Queries
```bash
# Multiple price metrics for last 30 days
curl "http://brekit.org/api/vecs/query?index=date&ids=open,high,low,close&from=-30&format=csv"
curl "https://bitview.space/api/vecs/query?index=date&ids=open,high,low,close&from=-30&format=csv"
# Block statistics for specific range
curl "https://brekit.org/api/vecs/query?index=height&ids=size,weight,tx_count,fee_sum&from=800000&count=100"
curl "https://bitview.space/api/vecs/query?index=height&ids=size,weight,tx_count,fee_sum&from=800000&count=100"
# Weekly analytics as JSON matrix
curl "https://brekit.org/api/vecs/query?index=week&ids=close,difficulty&from=-52"
curl "https://bitview.space/api/vecs/query?index=week&ids=close,difficulty&from=-52"
```
## API Reference
@@ -145,7 +147,7 @@ curl "/api/vecs/month-to-supply"
**CSV Format**:
```csv
index,close,supply,feerate
index,close,supply,fee_rate
0,42.5,1500,0.05
1,43.1,1520,0.052
2,44.2,1480,0.048
+1 -1
View File
@@ -26,7 +26,7 @@ pub fn main() -> Result<()> {
let exit = Exit::new();
exit.set_ctrlc_handler();
let parser = Parser::new(bitcoin_dir.join("blocks"), brk_dir.to_path_buf(), rpc);
let parser = Parser::new(bitcoin_dir.join("blocks"), Some(brk_dir.to_path_buf()), rpc);
let outputs_dir = Path::new("../../_outputs");
+5 -5
View File
@@ -16,7 +16,7 @@ use crate::{HeaderMapExtended, ResponseExtended};
use super::AppState;
const MAX_WEIGHT: usize = 320_000;
const MAX_WEIGHT: usize = 65 * 10_000;
pub async fn handler(
uri: Uri,
@@ -43,7 +43,7 @@ fn req_to_response_res(
interface, cache, ..
}: AppState,
) -> Result<Response> {
let vecs = interface.search(&params);
let vecs = interface.search(&params)?;
if vecs.is_empty() {
return Ok(Json(vec![] as Vec<usize>).into_response());
@@ -61,9 +61,9 @@ fn req_to_response_res(
.sum::<usize>();
if weight > MAX_WEIGHT {
return Err(Error::Str(
"Request is too heavy, max weight is {MAX_WEIGHT} bytes",
));
return Err(Error::String(format!(
"Request is too heavy, max weight is {MAX_WEIGHT} bytes"
)));
}
// TODO: height should be from vec, but good enough for now
-10
View File
@@ -106,16 +106,6 @@ impl ApiRoutes for Router<AppState> {
},
),
)
.route(
"/health",
get(|| async {
Json(serde_json::json!({
"status": "healthy",
"service": "brk-server",
"timestamp": jiff::Timestamp::now().to_string()
}))
}),
)
.route(
"/api",
get(|| async {
+29 -1
View File
@@ -11,6 +11,7 @@ use axum::{
body::{Body, Bytes},
http::{Request, Response, StatusCode, Uri},
middleware::Next,
response::Redirect,
routing::get,
serve,
};
@@ -47,7 +48,7 @@ impl Server {
Self(AppState {
interface: Box::leak(Box::new(interface)),
path: files_path,
cache: Arc::new(Cache::new(10_000)),
cache: Arc::new(Cache::new(5_000)),
})
}
@@ -98,6 +99,33 @@ impl Server {
.add_files_routes(state.path.as_ref())
.add_mcp_routes(state.interface, mcp)
.route("/version", get(Json(VERSION)))
.route(
"/health",
get(Json(serde_json::json!({
"status": "healthy",
"service": "brk-server",
"timestamp": jiff::Timestamp::now().to_string()
}))),
)
.route(
"/discord",
get(Redirect::temporary("https://discord.gg/WACpShCB7M")),
)
.route("/crates", get(Redirect::temporary("https://crates.io/crates/brk")))
.route(
"/status",
get(Redirect::temporary("https://status.bitview.space")),
)
.route("/github", get(Redirect::temporary("https://github.com/bitcoinresearchkit/brk")))
.route(
"/cli",
get(Redirect::temporary("https://crates.io/crates/brk_cli")),
)
.route(
"/hosting",
get(Redirect::temporary("https://github.com/bitcoinresearchkit/brk?tab=readme-ov-file#hosting-as-a-service")),
)
.route("/nostr", get(Redirect::temporary("https://primal.net/p/npub1jagmm3x39lmwfnrtvxcs9ac7g300y3dusv9lgzhk2e4x5frpxlrqa73v44")))
.with_state(state)
.layer(compression_layer)
.layer(response_uri_layer)
+4
View File
@@ -47,6 +47,10 @@ impl Date {
pub fn into_jiff(self) -> Date_ {
self.into()
}
pub fn today() -> Self {
Self::from(Timestamp::now())
}
}
impl Default for Date {
@@ -1,8 +1,8 @@
use std::ops::Add;
use vecdb::{CheckedSub, Printable};
use derive_deref::Deref;
use serde::Serialize;
use vecdb::{CheckedSub, Printable, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
use crate::TypeIndex;
@@ -22,6 +22,7 @@ use crate::TypeIndex;
IntoBytes,
KnownLayout,
Serialize,
StoredCompressed,
)]
pub struct EmptyAddressIndex(TypeIndex);
+13 -13
View File
@@ -12,9 +12,9 @@ use super::{Sats, StoredU64};
#[derive(
Debug, Clone, Copy, Serialize, FromBytes, Immutable, IntoBytes, KnownLayout, StoredCompressed,
)]
pub struct Feerate(f64);
pub struct FeeRate(f64);
impl From<(Sats, StoredU64)> for Feerate {
impl From<(Sats, StoredU64)> for FeeRate {
fn from((sats, vsize): (Sats, StoredU64)) -> Self {
let sats = u64::from(sats);
let vsize = u64::from(vsize);
@@ -22,44 +22,44 @@ impl From<(Sats, StoredU64)> for Feerate {
}
}
impl From<f64> for Feerate {
impl From<f64> for FeeRate {
fn from(value: f64) -> Self {
Self(value)
}
}
impl From<Feerate> for f64 {
fn from(value: Feerate) -> Self {
impl From<FeeRate> for f64 {
fn from(value: FeeRate) -> Self {
value.0
}
}
impl Add for Feerate {
impl Add for FeeRate {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self(self.0 + rhs.0)
}
}
impl AddAssign for Feerate {
impl AddAssign for FeeRate {
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs
}
}
impl Div<usize> for Feerate {
impl Div<usize> for FeeRate {
type Output = Self;
fn div(self, rhs: usize) -> Self::Output {
Self(self.0 / rhs as f64)
}
}
impl From<usize> for Feerate {
impl From<usize> for FeeRate {
fn from(value: usize) -> Self {
Self(value as f64)
}
}
impl PartialEq for Feerate {
impl PartialEq for FeeRate {
fn eq(&self, other: &Self) -> bool {
match (self.0.is_nan(), other.0.is_nan()) {
(true, true) => true,
@@ -70,17 +70,17 @@ impl PartialEq for Feerate {
}
}
impl Eq for Feerate {}
impl Eq for FeeRate {}
#[allow(clippy::derive_ord_xor_partial_ord)]
impl PartialOrd for Feerate {
impl PartialOrd for FeeRate {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[allow(clippy::derive_ord_xor_partial_ord)]
impl Ord for Feerate {
impl Ord for FeeRate {
fn cmp(&self, other: &Self) -> Ordering {
match (self.0.is_nan(), other.0.is_nan()) {
(true, true) => Ordering::Equal,
+7 -1
View File
@@ -227,13 +227,19 @@ impl TryFrom<&std::path::Path> for Height {
}
impl From<ByteView> for Height {
fn from(value: byteview::ByteView) -> Self {
fn from(value: ByteView) -> Self {
Self(u32::from_be_bytes(copy_first_4bytes(&value).unwrap()))
}
}
impl From<Height> for ByteView {
fn from(value: Height) -> Self {
Self::from(&value)
}
}
impl From<&Height> for ByteView {
fn from(value: &Height) -> Self {
Self::new(&value.0.to_be_bytes())
}
}
@@ -11,7 +11,8 @@ pub struct LoadedAddressData {
pub sent: Sats,
pub received: Sats,
pub realized_cap: Dollars,
pub outputs_len: u32,
pub utxos: u32,
#[serde(skip)]
padding: u32,
}
@@ -41,12 +42,12 @@ impl LoadedAddressData {
#[inline]
pub fn has_0_utxos(&self) -> bool {
self.outputs_len == 0
self.utxos == 0
}
pub fn receive(&mut self, amount: Sats, price: Option<Dollars>) {
self.received += amount;
self.outputs_len += 1;
self.utxos += 1;
if let Some(price) = price {
let added = price * amount;
self.realized_cap += added;
@@ -62,7 +63,7 @@ impl LoadedAddressData {
return Err(Error::Str("Previous_amount smaller than sent amount"));
}
self.sent += amount;
self.outputs_len -= 1;
self.utxos -= 1;
if let Some(previous_price) = previous_price {
let subtracted = previous_price * amount;
let realized_cap = self.realized_cap.checked_sub(subtracted).unwrap();
@@ -94,7 +95,7 @@ impl From<&EmptyAddressData> for LoadedAddressData {
sent: value.transfered,
received: value.transfered,
realized_cap: Dollars::ZERO,
outputs_len: 0,
utxos: 0,
padding: 0,
}
}
@@ -2,7 +2,7 @@ use std::ops::Add;
use derive_deref::Deref;
use serde::Serialize;
use vecdb::{CheckedSub, Printable};
use vecdb::{CheckedSub, Printable, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
use crate::TypeIndex;
@@ -22,6 +22,7 @@ use crate::TypeIndex;
IntoBytes,
KnownLayout,
Serialize,
StoredCompressed,
)]
pub struct LoadedAddressIndex(TypeIndex);
+2
View File
@@ -43,6 +43,7 @@ mod stored_bool;
mod stored_f32;
mod stored_f64;
mod stored_i16;
mod stored_string;
mod stored_u16;
mod stored_u32;
mod stored_u64;
@@ -105,6 +106,7 @@ pub use stored_bool::*;
pub use stored_f32::*;
pub use stored_f64::*;
pub use stored_i16::*;
pub use stored_string::*;
pub use stored_u8::*;
pub use stored_u16::*;
pub use stored_u32::*;
@@ -36,6 +36,12 @@ impl From<f64> for StoredF64 {
}
}
impl From<f32> for StoredF64 {
fn from(value: f32) -> Self {
Self(value as f64)
}
}
impl From<usize> for StoredF64 {
fn from(value: usize) -> Self {
Self(value as f64)
@@ -88,6 +94,12 @@ impl From<StoredF64> for f64 {
}
}
impl From<StoredF64> for f32 {
fn from(value: StoredF64) -> Self {
value.0 as f32
}
}
impl From<Dollars> for StoredF64 {
fn from(value: Dollars) -> Self {
Self(f64::from(value))
@@ -0,0 +1,56 @@
use byteview::ByteView;
use derive_deref::Deref;
use serde::Serialize;
use vecdb::Printable;
#[derive(Default, Debug, Deref, Clone, Serialize)]
pub struct StoredString(String);
impl StoredString {
pub fn new(string: String) -> Self {
Self(string)
}
pub fn as_str(&self) -> &str {
self
}
pub fn as_string(&self) -> &String {
self
}
}
impl From<String> for StoredString {
fn from(value: String) -> Self {
Self(value)
}
}
impl From<ByteView> for StoredString {
fn from(value: ByteView) -> Self {
let bytes = &*value;
Self(String::from_utf8_lossy(bytes).into_owned())
}
}
impl From<StoredString> for ByteView {
fn from(value: StoredString) -> Self {
Self::from(&value)
}
}
impl From<&StoredString> for ByteView {
fn from(value: &StoredString) -> Self {
Self::new(value.as_bytes())
}
}
impl Printable for StoredString {
fn to_string() -> &'static str {
"string"
}
fn to_possible_strings() -> &'static [&'static str] {
&["string"]
}
}
@@ -69,6 +69,18 @@ impl Timestamp {
pub fn is_more_than_hour(&self) -> bool {
self.0 >= ONE_HOUR_IN_SEC
}
pub fn now() -> Self {
Self::from(jiff::Timestamp::now())
}
pub fn day_completion(&self) -> f64 {
let rounded = jiff::Timestamp::from(Self::from(Date::from(*self)));
ONE_DAY_IN_SEC_F64
/ jiff::Timestamp::from(*self)
.duration_since(rounded)
.as_secs_f64()
}
}
impl From<u32> for Timestamp {

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Before

Width:  |  Height:  |  Size: 511 B

After

Width:  |  Height:  |  Size: 511 B

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Some files were not shown because too many files have changed in this diff Show More