mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-26 14:14:30 -07:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 664b125ce2 | |||
| 5f4b1c9e32 | |||
| d11d3f19bd | |||
| f34f4f2738 | |||
| 15db7c2310 | |||
| f9257ed04d | |||
| 15e6ef8488 | |||
| 9ae0a57f22 | |||
| 1e38c21f8e | |||
| bdc3c19163 | |||
| d55478da54 | |||
| 82bcc55645 | |||
| 07618ebe43 | |||
| 1492834d1e | |||
| 5ab6197356 | |||
| 0a789fe551 | |||
| caa8ff23ed | |||
| ee30d1d36d | |||
| 0d9415db9d | |||
| 8020e1126f | |||
| 3439422057 | |||
| 68d2bf736f | |||
| d78c39fd8c |
Generated
+139
-95
@@ -34,6 +34,19 @@ dependencies = [
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"getrandom 0.2.16",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy 0.7.35",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
@@ -152,9 +165,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||
|
||||
[[package]]
|
||||
name = "async-compression"
|
||||
version = "0.4.22"
|
||||
version = "0.4.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59a194f9d963d8099596278594b3107448656ba73831c9d8c783e613ce86da64"
|
||||
checksum = "b37fc50485c4f3f736a4fb14199f6d5f5ba008d7f28fe710306c92780f004c07"
|
||||
dependencies = [
|
||||
"brotli",
|
||||
"flate2",
|
||||
@@ -374,7 +387,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk"
|
||||
version = "0.0.27"
|
||||
version = "0.0.31"
|
||||
dependencies = [
|
||||
"brk_cli",
|
||||
"brk_computer",
|
||||
@@ -391,7 +404,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_cli"
|
||||
version = "0.0.27"
|
||||
version = "0.0.31"
|
||||
dependencies = [
|
||||
"brk_computer",
|
||||
"brk_core",
|
||||
@@ -412,7 +425,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_computer"
|
||||
version = "0.0.27"
|
||||
version = "0.0.31"
|
||||
dependencies = [
|
||||
"brk_core",
|
||||
"brk_exit",
|
||||
@@ -422,12 +435,13 @@ dependencies = [
|
||||
"brk_parser",
|
||||
"brk_vec",
|
||||
"color-eyre",
|
||||
"fjall",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brk_core"
|
||||
version = "0.0.27"
|
||||
version = "0.0.31"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
@@ -439,12 +453,12 @@ dependencies = [
|
||||
"rlimit",
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
"zerocopy",
|
||||
"zerocopy 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brk_exit"
|
||||
version = "0.0.27"
|
||||
version = "0.0.31"
|
||||
dependencies = [
|
||||
"brk_logger",
|
||||
"ctrlc",
|
||||
@@ -453,7 +467,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_fetcher"
|
||||
version = "0.0.27"
|
||||
version = "0.0.31"
|
||||
dependencies = [
|
||||
"brk_core",
|
||||
"brk_logger",
|
||||
@@ -466,7 +480,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_indexer"
|
||||
version = "0.0.27"
|
||||
version = "0.0.31"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
@@ -480,12 +494,12 @@ dependencies = [
|
||||
"fjall",
|
||||
"log",
|
||||
"rayon",
|
||||
"zerocopy",
|
||||
"zerocopy 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brk_logger"
|
||||
version = "0.0.27"
|
||||
version = "0.0.31"
|
||||
dependencies = [
|
||||
"color-eyre",
|
||||
"env_logger",
|
||||
@@ -495,7 +509,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_parser"
|
||||
version = "0.0.27"
|
||||
version = "0.0.31"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
@@ -505,12 +519,12 @@ dependencies = [
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"zerocopy",
|
||||
"zerocopy 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brk_query"
|
||||
version = "0.0.27"
|
||||
version = "0.0.31"
|
||||
dependencies = [
|
||||
"brk_computer",
|
||||
"brk_indexer",
|
||||
@@ -526,7 +540,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_server"
|
||||
version = "0.0.27"
|
||||
version = "0.0.31"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"brk_computer",
|
||||
@@ -552,7 +566,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_vec"
|
||||
version = "0.0.27"
|
||||
version = "0.0.31"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"axum",
|
||||
@@ -560,15 +574,15 @@ dependencies = [
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"zerocopy",
|
||||
"zerocopy 0.8.24",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "7.0.0"
|
||||
version = "8.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd"
|
||||
checksum = "cf19e729cdbd51af9a397fb9ef8ac8378007b797f8273cfbfdf45dcaa316167b"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
@@ -577,9 +591,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brotli-decompressor"
|
||||
version = "4.0.3"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a334ef7c9e23abf0ce748e8cd309037da93e606ad52eb372e4ce327a0dcfbdfd"
|
||||
checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
@@ -648,9 +662,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.19"
|
||||
version = "1.2.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362"
|
||||
checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
@@ -694,9 +708,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.36"
|
||||
version = "4.5.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04"
|
||||
checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -704,9 +718,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.36"
|
||||
version = "4.5.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5"
|
||||
checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -1107,9 +1121,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
||||
|
||||
[[package]]
|
||||
name = "fjall"
|
||||
version = "2.8.0"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b2ced3483989a62b3533c9f99054d73b527c6c0045cf22b00fe87956f1a46f"
|
||||
checksum = "958511f67d1f80e6bff9ffac05c626bb340d4602ca6ea5617d9901c218c894f0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"byteview",
|
||||
@@ -1204,9 +1218,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@@ -1478,9 +1492,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "jiff"
|
||||
version = "0.2.8"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5ad87c89110f55e4cd4dc2893a9790820206729eaf221555f742d540b0724a0"
|
||||
checksum = "5a064218214dc6a10fbae5ec5fa888d80c45d611aba169222fc272072bf7aef6"
|
||||
dependencies = [
|
||||
"jiff-static",
|
||||
"jiff-tzdb-platform",
|
||||
@@ -1493,9 +1507,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "jiff-static"
|
||||
version = "0.2.8"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d076d5b64a7e2fe6f0743f02c43ca4a6725c0f904203bfe276a5b3e793103605"
|
||||
checksum = "199b7932d97e325aff3a7030e141eafe7f2c6268e1d1b24859b753a627f45254"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1585,9 +1599,9 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "lsm-tree"
|
||||
version = "2.8.0"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a63a5e98a38b51765274137d8aedfbd848da5f4d016867e186b673fcc06a8c"
|
||||
checksum = "87d58bdef2dcbf50fce9f343265bdbd7fb08a458d241eb837ce426be22d674b4"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crossbeam-skiplist",
|
||||
@@ -1791,9 +1805,9 @@ checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564"
|
||||
|
||||
[[package]]
|
||||
name = "oxc"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "548086420c5c78546c7417384689af59ed11dbe9462e8bfef42636be0f545b96"
|
||||
checksum = "409ba57c4752b7fab9609af78790aadeb541316933d1525484dad877988622f6"
|
||||
dependencies = [
|
||||
"oxc_allocator",
|
||||
"oxc_ast",
|
||||
@@ -1834,9 +1848,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_allocator"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acaf33eacde1fca8fdb26655d7486842a8106916bc3855265607db2b4a4eaec4"
|
||||
checksum = "43fe5f8d34c351e3c90b512046dbfff2ff87c8a1927ebe6945f1cdefcc3219d0"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"bumpalo",
|
||||
@@ -1848,9 +1862,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_ast"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3044daf0f6b02f27330954141d799f9206e04b9175a3f4fa199f78c5ef46b2b4"
|
||||
checksum = "5ad2e9c3fb4b409b14fd791fbbf6ced9a81363364beedd48059bbb8f42bf4987"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cow-utils",
|
||||
@@ -1865,9 +1879,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_ast_macros"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ee5d1546ecb309530b30b48f1aefefad7e6d53b8502e7b91b20d6a523af270e"
|
||||
checksum = "578b69ed39d814cb8396674e17a0f94f1c02bc25d226b265c2913bd6e84afffb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1876,9 +1890,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_ast_visit"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b29d0e9e05d2638317c39470b5a528e268fc088ae1e3fda26b049661f2de25ad"
|
||||
checksum = "f437ca959bf931d5facbc6df77c7491a4aec32df5b9f647ffa19c52055a7dc56"
|
||||
dependencies = [
|
||||
"oxc_allocator",
|
||||
"oxc_ast",
|
||||
@@ -1888,9 +1902,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_cfg"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b3740da43d597136474fa738bafb697c8469b8ecd9c256819ae443ec91a67aa"
|
||||
checksum = "ccecf0bce4034ebf17e7edb6f214fa0e6f8d134d1a3fb98408d6bcbef024a3a1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"itertools",
|
||||
@@ -1903,9 +1917,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_codegen"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee5e197f8bed070bcc6e9744a7a5f91bc4ff250543f07849567e6e602383c7db"
|
||||
checksum = "e3361ed40dd6b4b6a7a4b44c175aa6beea68eefed68bc32a28684a0d1a00bc39"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cow-utils",
|
||||
@@ -1924,15 +1938,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_data_structures"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ca20f4fc9af4f462bfc6bbca60e3f4c2ca9c4f09e99363c0c85d90bb936641c"
|
||||
checksum = "0d2d64d2e627796f73e37ccb51f1f87cd9de612245ef3f790051855587d3734e"
|
||||
|
||||
[[package]]
|
||||
name = "oxc_diagnostics"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50e5ef1106d01ade76eec600e5b0da38932f555d1cb661f0d5ec7f3d717da22d"
|
||||
checksum = "96ece1486240cfeec516eaaa7332c96decb3a756d72e504bb63393507996c39d"
|
||||
dependencies = [
|
||||
"cow-utils",
|
||||
"oxc-miette",
|
||||
@@ -1940,9 +1954,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_ecmascript"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76b1ea0ef90fda6b68127181b3b136b21041a595e8c2028c4e08fcf85f99a10c"
|
||||
checksum = "0d7d5ddf1cd783ed1a930ac6eedd4f73c6a5359beaabad7ee8333e366816291c"
|
||||
dependencies = [
|
||||
"cow-utils",
|
||||
"num-bigint",
|
||||
@@ -1954,9 +1968,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_estree"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b9ce9584683d43622ef4b66bd605ce9878f3bf7468b9b59ad041f33af13c34d"
|
||||
checksum = "62de94b10df7ab86a379f01b75076f6a762fc91a001678108318203fc0805ad9"
|
||||
|
||||
[[package]]
|
||||
name = "oxc_index"
|
||||
@@ -1966,9 +1980,9 @@ checksum = "2fa07b0cfa997730afed43705766ef27792873fdf5215b1391949fec678d2392"
|
||||
|
||||
[[package]]
|
||||
name = "oxc_mangler"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20c80a552dc097088d466679bcaba2576bbe88a430ca9c5b0cb67e23787aaa7a"
|
||||
checksum = "8d691c6609bca852ae1e0571de564de3b4d110a46c9877aa029e9dba56b76d1c"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"itertools",
|
||||
@@ -1983,9 +1997,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_minifier"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5e504ac83f23ff755eae4ebd6291258b44e05cf58379e1fe1c00b1007e41f29"
|
||||
checksum = "294aa5790cc0beae7018d99dc5b389d373725ef7ea7ecef5d0ed18794b3414b3"
|
||||
dependencies = [
|
||||
"cow-utils",
|
||||
"oxc_allocator",
|
||||
@@ -2005,9 +2019,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_parser"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "688491b2dfe8049a6410bc6b92f71e75bebfe9a1f352a64084a62069cd644e7f"
|
||||
checksum = "5b7defa49cc20f9e3c346674b06752cacaacce053cde69a04f0f85f31e00820f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cow-utils",
|
||||
@@ -2028,9 +2042,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_regular_expression"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be6231edf43b8ca0fa8edad93b0b8e9067a3991ea2d8aa9f22a4c8fa464f267"
|
||||
checksum = "14d37e8585630a167c4a2b121dcdab52bf13b71a6bd64260efe797956bd4f6d0"
|
||||
dependencies = [
|
||||
"oxc_allocator",
|
||||
"oxc_ast_macros",
|
||||
@@ -2044,9 +2058,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_semantic"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f5c80c996fafc27a8444732bbba06f1de3eb488c585d65293a4b40b089ff564"
|
||||
checksum = "895130e4f197b77d9b54deffccc2ce8a9d977435c022a49ddecb1f467b946854"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"oxc_allocator",
|
||||
@@ -2080,9 +2094,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_span"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bce0a945765d00dd9ee0bfdc38fa265008e66f919157894c0383c525d026511f"
|
||||
checksum = "8350c982e6284f41668ebd3c714de22280a19f617c3cb6117bbc4e16afc6b13a"
|
||||
dependencies = [
|
||||
"compact_str",
|
||||
"oxc-miette",
|
||||
@@ -2093,9 +2107,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_syntax"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12b876a00908cb1fc6648823d7d8579a69af1c5a5c6d4cf6135040e09f41d116"
|
||||
checksum = "7e85d9197e08e176d6f58a3885d125738c46a69145410e82b3a32f676ddd5546"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cow-utils",
|
||||
@@ -2114,9 +2128,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_traverse"
|
||||
version = "0.64.0"
|
||||
version = "0.66.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9c25f3da54211abd4b6ff1390a0f28d42b2128cb33f4b38edbdc5cb71bc3d3c"
|
||||
checksum = "ac43e668dcd3a0b17cf4f889feac5321e56430a0550205df2e85b3e9314f6caa"
|
||||
dependencies = [
|
||||
"compact_str",
|
||||
"itoa",
|
||||
@@ -2133,12 +2147,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "papergrid"
|
||||
version = "0.14.0"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b915f831b85d984193fdc3d3611505871dc139b2534530fa01c1a6a6707b6723"
|
||||
checksum = "30268a8d20c2c0d126b2b6610ab405f16517f6ba9f244d8c59ac2c512a8a1ce7"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"bytecount",
|
||||
"fnv",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
@@ -2298,7 +2312,7 @@ version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
"zerocopy 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2384,7 +2398,7 @@ version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.15",
|
||||
"getrandom 0.2.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2459,7 +2473,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom 0.2.15",
|
||||
"getrandom 0.2.16",
|
||||
"libc",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
@@ -2718,9 +2732,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.2"
|
||||
version = "1.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
||||
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -2819,19 +2833,20 @@ checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
|
||||
|
||||
[[package]]
|
||||
name = "tabled"
|
||||
version = "0.18.0"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "121d8171ee5687a4978d1b244f7d99c43e7385a272185a2f1e1fa4dc0979d444"
|
||||
checksum = "228d124371171cd39f0f454b58f73ddebeeef3cef3207a82ffea1c29465aea43"
|
||||
dependencies = [
|
||||
"papergrid",
|
||||
"tabled_derive",
|
||||
"testing_table",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tabled_derive"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52d9946811baad81710ec921809e2af67ad77719418673b2a3794932d57b7538"
|
||||
checksum = "0ea5d1b13ca6cff1f9231ffd62f15eefd72543dab5e468735f1a456728a02846"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error2",
|
||||
@@ -2853,6 +2868,15 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "testing_table"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f8daae29995a24f65619e19d8d31dea5b389f3d853d8bf297bbf607cd0014cc"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.16.2"
|
||||
@@ -2956,9 +2980,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.14"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034"
|
||||
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
@@ -3153,9 +3177,9 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||
|
||||
[[package]]
|
||||
name = "value-log"
|
||||
version = "1.8.0"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd29b17c041f94e0885179637289815cd038f0c9fc19c4549d5a97017404fb7d"
|
||||
checksum = "62fc7c4ce161f049607ecea654dca3f2d727da5371ae85e2e4f14ce2b98ed67c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"byteview",
|
||||
@@ -3408,9 +3432,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.6"
|
||||
version = "0.7.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10"
|
||||
checksum = "6cb8234a863ea0e8cd7284fcdd4f145233eb00fee02bbdd9861aec44e6477bc5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -3439,13 +3463,33 @@ dependencies = [
|
||||
"lzma-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||
dependencies = [
|
||||
"zerocopy-derive 0.7.35",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
"zerocopy-derive 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
+5
-5
@@ -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.27"
|
||||
package.version = "0.0.31"
|
||||
package.repository = "https://github.com/bitcoinresearchkit/brk"
|
||||
|
||||
[profile.release]
|
||||
@@ -31,17 +31,17 @@ brk_query = { version = "0", path = "crates/brk_query" }
|
||||
brk_server = { version = "0", path = "crates/brk_server" }
|
||||
brk_vec = { version = "0", path = "crates/brk_vec" }
|
||||
byteview = "0.6.1"
|
||||
clap = { version = "4.5.36", features = ["derive", "string"] }
|
||||
clap = { version = "4.5.37", features = ["derive", "string"] }
|
||||
color-eyre = "0.6.3"
|
||||
derive_deref = "1.1.1"
|
||||
fjall = "2.8.0"
|
||||
jiff = "0.2.8"
|
||||
fjall = "2.9.0"
|
||||
jiff = "0.2.10"
|
||||
log = { version = "0.4.27" }
|
||||
minreq = { version = "2.13.4", features = ["https", "serde_json"] }
|
||||
rayon = "1.10.0"
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = { version = "1.0.140", features = ["float_roundtrip"] }
|
||||
tabled = "0.18.0"
|
||||
tabled = "0.19.0"
|
||||
zerocopy = { version = "0.8.24", features = ["derive"] }
|
||||
|
||||
[workspace.metadata.release]
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a href="https://bsky.app/profile/bitcoinresearchkit.org">
|
||||
<img src="https://img.shields.io/badge/bluesky-blue?link=https%3A%2F%2Fbsky.app%2Fprofile%2Fbitcoinresearchkit.org" alt="Bluesky" />
|
||||
</a>
|
||||
<a href="https://x.com/0xbrk">
|
||||
<a href="https://x.com/brkdotorg">
|
||||
<img src="https://img.shields.io/badge/x.com-black" alt="X" />
|
||||
</a>
|
||||
</p>
|
||||
@@ -92,6 +92,7 @@ Heartfelt thanks go out to every donor on [Nostr](https://primal.net/p/npub1jagm
|
||||
If you'd like to have your own instance hosted for you please contact [hosting@bitcoinresearchkit.org](mailto:hosting@bitcoinresearchkit.org).
|
||||
|
||||
- 2 separate dedicated servers (1 GB/s each) with different ISPs and Cloudflare integration for enhanced performance and optimal availability
|
||||
- 99.9% SLA
|
||||
- Direct communication for feature requests and support
|
||||
- Updates delivered at your convenience
|
||||
- Optional subdomains: `*.bitcoinresearchkit.org`, `*.kibo.money` and `*.satonomics.xyz`
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a href="https://bsky.app/profile/bitcoinresearchkit.org">
|
||||
<img src="https://img.shields.io/badge/bluesky-blue?link=https%3A%2F%2Fbsky.app%2Fprofile%2Fbitcoinresearchkit.org" alt="Bluesky" />
|
||||
</a>
|
||||
<a href="https://x.com/0xbrk">
|
||||
<a href="https://x.com/brkdotorg">
|
||||
<img src="https://img.shields.io/badge/x.com-black" alt="X" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -10,10 +10,10 @@ pub fn query(params: QueryParams) -> color_eyre::Result<()> {
|
||||
|
||||
let compressed = config.compressed();
|
||||
|
||||
let mut indexer = Indexer::new(config.indexeddir(), compressed, config.check_collisions())?;
|
||||
let mut indexer = Indexer::new(&config.outputsdir(), compressed, config.check_collisions())?;
|
||||
indexer.import_vecs()?;
|
||||
|
||||
let mut computer = Computer::new(config.computeddir(), config.fetcher(), compressed);
|
||||
let mut computer = Computer::new(&config.outputsdir(), config.fetcher(), compressed);
|
||||
computer.import_vecs()?;
|
||||
|
||||
let query = Query::build(&indexer, &computer);
|
||||
|
||||
@@ -28,12 +28,12 @@ pub fn run(config: RunConfig) -> color_eyre::Result<()> {
|
||||
|
||||
let compressed = config.compressed();
|
||||
|
||||
let mut indexer = Indexer::new(config.indexeddir(), compressed, config.check_collisions())?;
|
||||
let mut indexer = Indexer::new(&config.outputsdir(), compressed, config.check_collisions())?;
|
||||
indexer.import_stores()?;
|
||||
indexer.import_vecs()?;
|
||||
|
||||
let mut computer = Computer::new(config.computeddir(), config.fetcher(), compressed);
|
||||
computer.import_stores()?;
|
||||
let mut computer = Computer::new(&config.outputsdir(), config.fetcher(), compressed);
|
||||
computer.import_stores(&indexer)?;
|
||||
computer.import_vecs()?;
|
||||
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
@@ -357,18 +357,10 @@ impl RunConfig {
|
||||
.map_or_else(default_brk_path, |s| Self::fix_user_path(s.as_ref()))
|
||||
}
|
||||
|
||||
fn outputsdir(&self) -> PathBuf {
|
||||
pub fn outputsdir(&self) -> PathBuf {
|
||||
self.brkdir().join("outputs")
|
||||
}
|
||||
|
||||
pub fn indexeddir(&self) -> PathBuf {
|
||||
self.outputsdir().join("indexed")
|
||||
}
|
||||
|
||||
pub fn computeddir(&self) -> PathBuf {
|
||||
self.outputsdir().join("computed")
|
||||
}
|
||||
|
||||
pub fn harsdir(&self) -> PathBuf {
|
||||
self.outputsdir().join("hars")
|
||||
}
|
||||
|
||||
@@ -15,4 +15,5 @@ brk_logger = { workspace = true }
|
||||
brk_parser = { workspace = true }
|
||||
brk_vec = { workspace = true }
|
||||
color-eyre = { workspace = true }
|
||||
fjall = { workspace = true }
|
||||
log = { workspace = true }
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a href="https://bsky.app/profile/bitcoinresearchkit.org">
|
||||
<img src="https://img.shields.io/badge/bluesky-blue?link=https%3A%2F%2Fbsky.app%2Fprofile%2Fbitcoinresearchkit.org" alt="Bluesky" />
|
||||
</a>
|
||||
<a href="https://x.com/0xbrk">
|
||||
<a href="https://x.com/brkdotorg">
|
||||
<img src="https://img.shields.io/badge/x.com-black" alt="X" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::dot_brk_path;
|
||||
use brk_indexer::Indexer;
|
||||
|
||||
pub fn main() -> color_eyre::Result<()> {
|
||||
color_eyre::install()?;
|
||||
|
||||
brk_logger::init(Some(Path::new(".log")));
|
||||
|
||||
let outputs_dir = dot_brk_path().join("outputs");
|
||||
// let outputs_dir = Path::new("../../_outputs");
|
||||
|
||||
let compressed = false;
|
||||
|
||||
let mut indexer = Indexer::new(outputs_dir.as_path(), compressed, true)?;
|
||||
indexer.import_stores()?;
|
||||
indexer.import_vecs()?;
|
||||
|
||||
let height_to_timestamp = &indexer.vecs().height_to_timestamp;
|
||||
|
||||
dbg!(height_to_timestamp.len());
|
||||
|
||||
// height_to_timestamp.iter().for_each(|t| {
|
||||
// dbg!(t);
|
||||
// });
|
||||
|
||||
// let index = max_from.min(A::from(self.len()));
|
||||
let mut height_to_timestamp_iter = height_to_timestamp.iter();
|
||||
// height_to_timestamp.iter().for_each(|t| {
|
||||
// dbg!(t);
|
||||
// });
|
||||
(0..2).for_each(|i| {
|
||||
dbg!(height_to_timestamp_iter.get_(i));
|
||||
});
|
||||
// for_each(|t| {
|
||||
// dbg!(t);
|
||||
// });
|
||||
// .try_for_each(|(height, timestamp)| -> Result<()> {
|
||||
// let interval = height.decremented().map_or(Timestamp::ZERO, |prev_h| {
|
||||
// dbg!((height, prev_h));
|
||||
// let prev_timestamp = height_to_timestamp_iter
|
||||
// .nth(prev_h.unwrap_to_usize())
|
||||
// .context("To work")
|
||||
// .inspect_err(|_| {
|
||||
// dbg!(prev_h);
|
||||
// })
|
||||
// .unwrap()
|
||||
// .1
|
||||
// .into_inner();
|
||||
// timestamp
|
||||
// .into_inner()
|
||||
// .checked_sub(prev_timestamp)
|
||||
// .unwrap_or(Timestamp::ZERO)
|
||||
// // Ok(())
|
||||
// });
|
||||
|
||||
// Ok(())
|
||||
// // let (i, v) = t((a, b.into_inner(), self, &mut other_iter));
|
||||
// // self.forced_push_at(i, v, exit)
|
||||
// })?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -24,16 +24,16 @@ pub fn main() -> color_eyre::Result<()> {
|
||||
|
||||
let outputs_dir = Path::new("../../_outputs");
|
||||
|
||||
let compressed = true;
|
||||
let compressed = false;
|
||||
|
||||
let mut indexer = Indexer::new(outputs_dir.join("indexed"), compressed, true)?;
|
||||
let mut indexer = Indexer::new(outputs_dir, compressed, true)?;
|
||||
indexer.import_stores()?;
|
||||
indexer.import_vecs()?;
|
||||
|
||||
let fetcher = Fetcher::import(None)?;
|
||||
|
||||
let mut computer = Computer::new(outputs_dir.join("computed"), Some(fetcher), compressed);
|
||||
computer.import_stores()?;
|
||||
let mut computer = Computer::new(outputs_dir, Some(fetcher), compressed);
|
||||
computer.import_stores(&indexer)?;
|
||||
computer.import_vecs()?;
|
||||
|
||||
let starting_indexes = indexer.index(&parser, rpc, &exit)?;
|
||||
|
||||
@@ -26,9 +26,9 @@ pub struct Computer {
|
||||
}
|
||||
|
||||
impl Computer {
|
||||
pub fn new(computed_dir: PathBuf, fetcher: Option<Fetcher>, compressed: bool) -> Self {
|
||||
pub fn new(outputs_dir: &Path, fetcher: Option<Fetcher>, compressed: bool) -> Self {
|
||||
Self {
|
||||
path: computed_dir,
|
||||
path: outputs_dir.to_owned(),
|
||||
fetcher,
|
||||
vecs: None,
|
||||
stores: None,
|
||||
@@ -38,7 +38,7 @@ impl Computer {
|
||||
|
||||
pub fn import_vecs(&mut self) -> color_eyre::Result<()> {
|
||||
self.vecs = Some(Vecs::import(
|
||||
&self.path.join("vecs"),
|
||||
&self.path.join("vecs/computed"),
|
||||
self.fetcher.is_some(),
|
||||
self.compressed,
|
||||
)?);
|
||||
@@ -47,8 +47,11 @@ impl Computer {
|
||||
|
||||
/// Do NOT import multiple times or things will break !!!
|
||||
/// Clone struct instead
|
||||
pub fn import_stores(&mut self) -> color_eyre::Result<()> {
|
||||
self.stores = Some(Stores::import(&self.path.join("stores"))?);
|
||||
pub fn import_stores(&mut self, indexer: &Indexer) -> color_eyre::Result<()> {
|
||||
self.stores = Some(Stores::import(
|
||||
&self.path.join("stores"),
|
||||
indexer.keyspace(),
|
||||
)?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -72,10 +75,6 @@ impl Computer {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> &Vecs {
|
||||
self.vecs.as_ref().unwrap()
|
||||
}
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{AddressindexTxoutindex, Unit};
|
||||
use brk_indexer::Store;
|
||||
use brk_vec::Version;
|
||||
use fjall::TransactionalKeyspace;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Stores {
|
||||
pub address_to_utxos_received: Store<AddressindexTxoutindex, Unit>,
|
||||
pub address_to_utxos_spent: Store<AddressindexTxoutindex, Unit>,
|
||||
// pub address_to_utxos_received: Store<AddressIndexOutputIndex, Unit>,
|
||||
// pub address_to_utxos_spent: Store<AddressIndexOutputIndex, Unit>,
|
||||
}
|
||||
|
||||
impl Stores {
|
||||
pub fn import(path: &Path) -> color_eyre::Result<Self> {
|
||||
let address_to_utxos_received =
|
||||
Store::import(&path.join("address_to_utxos_received"), Version::ZERO)?;
|
||||
let address_to_utxos_spent =
|
||||
Store::import(&path.join("address_to_utxos_spent"), Version::ZERO)?;
|
||||
pub fn import(_: &Path, _: &TransactionalKeyspace) -> color_eyre::Result<Self> {
|
||||
// let address_to_utxos_received = Store::import(
|
||||
// keyspace.clone(),
|
||||
// path,
|
||||
// "address_to_utxos_received",
|
||||
// Version::ZERO,
|
||||
// )?;
|
||||
// let address_to_utxos_spent = Store::import(
|
||||
// keyspace.clone(),
|
||||
// path,
|
||||
// "address_to_utxos_spent",
|
||||
// Version::ZERO,
|
||||
// )?;
|
||||
|
||||
Ok(Self {
|
||||
address_to_utxos_received,
|
||||
address_to_utxos_spent,
|
||||
// address_to_utxos_received,
|
||||
// address_to_utxos_spent,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,32 @@
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use brk_core::{CheckedSub, Height, StoredU32, StoredU64, StoredUsize, Timestamp, Weight};
|
||||
use brk_core::{
|
||||
CheckedSub, DifficultyEpoch, HalvingEpoch, Height, StoredU32, StoredU64, StoredUsize,
|
||||
Timestamp, Weight,
|
||||
};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_parser::bitcoin;
|
||||
use brk_vec::{Compressed, Version};
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
base::ComputedVec,
|
||||
grouped::{ComputedVecsFromHeight, StorableVecGeneatorOptions},
|
||||
EagerVec, Indexes,
|
||||
grouped::{ComputedVecsFromDateindex, ComputedVecsFromHeight, StorableVecGeneatorOptions},
|
||||
indexes,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
pub height_to_interval: ComputedVec<Height, Timestamp>,
|
||||
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
|
||||
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_weight: ComputedVecsFromHeight<Weight>,
|
||||
pub height_to_vbytes: ComputedVec<Height, StoredU64>,
|
||||
pub indexes_to_block_vbytes: ComputedVecsFromHeight<StoredU64>,
|
||||
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
|
||||
pub indexes_to_block_size: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_block_vbytes: ComputedVecsFromHeight<StoredU64>,
|
||||
pub indexes_to_block_weight: ComputedVecsFromHeight<Weight>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -29,11 +34,18 @@ impl Vecs {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
Ok(Self {
|
||||
height_to_interval: ComputedVec::forced_import(
|
||||
height_to_interval: EagerVec::forced_import(
|
||||
&path.join("height_to_interval"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
timeindexes_to_timestamp: ComputedVecsFromDateindex::forced_import(
|
||||
path,
|
||||
"timestamp",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_first(),
|
||||
)?,
|
||||
indexes_to_block_interval: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"block_interval",
|
||||
@@ -69,7 +81,7 @@ impl Vecs {
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_sum().add_total(),
|
||||
)?,
|
||||
height_to_vbytes: ComputedVec::forced_import(
|
||||
height_to_vbytes: EagerVec::forced_import(
|
||||
&path.join("height_to_vbytes"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
@@ -82,22 +94,67 @@ impl Vecs {
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_sum().add_total(),
|
||||
)?,
|
||||
difficultyepoch_to_timestamp: EagerVec::forced_import(
|
||||
&path.join("difficultyepoch_to_timestamp"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
halvingepoch_to_timestamp: EagerVec::forced_import(
|
||||
&path.join("halvingepoch_to_timestamp"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
indexes: &mut indexes::Vecs,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
self.timeindexes_to_timestamp.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
indexes.dateindex_to_date.vec(),
|
||||
|(di, d, ..)| (di, Timestamp::from(d)),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
let indexer_vecs = indexer.vecs();
|
||||
|
||||
v.compute_range(
|
||||
starting_indexes.height,
|
||||
indexer_vecs.height_to_weight.vec(),
|
||||
|h| (h, StoredU32::from(1_u32)),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
let indexer_vecs = indexer.vecs();
|
||||
|
||||
let mut height_to_timestamp_iter = indexer_vecs.height_to_timestamp.iter();
|
||||
self.height_to_interval.compute_transform(
|
||||
starting_indexes.height,
|
||||
indexer.mut_vecs().height_to_timestamp.mut_vec(),
|
||||
|(height, timestamp, _, height_to_timestamp)| {
|
||||
indexer_vecs.height_to_timestamp.vec(),
|
||||
|(height, timestamp, ..)| {
|
||||
let interval = height.decremented().map_or(Timestamp::ZERO, |prev_h| {
|
||||
let prev_timestamp = height_to_timestamp.double_unwrap_cached_get(prev_h);
|
||||
let prev_timestamp = height_to_timestamp_iter.unwrap_get_inner(prev_h);
|
||||
timestamp
|
||||
.checked_sub(prev_timestamp)
|
||||
.unwrap_or(Timestamp::ZERO)
|
||||
@@ -111,41 +168,26 @@ impl Vecs {
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.height_to_interval.mut_vec()),
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_transform(
|
||||
starting_indexes.height,
|
||||
indexer.mut_vecs().height_to_weight.mut_vec(),
|
||||
|(h, ..)| (h, StoredU32::from(1_u32)),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
Some(self.height_to_interval.vec()),
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_weight.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(indexer.mut_vecs().height_to_weight.mut_vec()),
|
||||
Some(indexer_vecs.height_to_weight.vec()),
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_size.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(indexer.mut_vecs().height_to_total_size.mut_vec()),
|
||||
Some(indexer_vecs.height_to_total_size.vec()),
|
||||
)?;
|
||||
|
||||
self.height_to_vbytes.compute_transform(
|
||||
starting_indexes.height,
|
||||
indexer.mut_vecs().height_to_weight.mut_vec(),
|
||||
indexer_vecs.height_to_weight.vec(),
|
||||
|(h, w, ..)| {
|
||||
(
|
||||
h,
|
||||
@@ -159,7 +201,23 @@ impl Vecs {
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.height_to_vbytes.mut_vec()),
|
||||
Some(self.height_to_vbytes.vec()),
|
||||
)?;
|
||||
|
||||
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.vec(),
|
||||
|(i, h, ..)| (i, height_to_timestamp_iter.get(h).unwrap().1.into_inner()),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.halvingepoch_to_timestamp.compute_transform(
|
||||
starting_indexes.halvingepoch,
|
||||
indexes.halvingepoch_to_first_height.vec(),
|
||||
|(i, h, ..)| (i, height_to_timestamp_iter.get(h).unwrap().1.into_inner()),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
@@ -170,12 +228,15 @@ impl Vecs {
|
||||
vec![
|
||||
self.height_to_interval.any_vec(),
|
||||
self.height_to_vbytes.any_vec(),
|
||||
self.difficultyepoch_to_timestamp.any_vec(),
|
||||
self.halvingepoch_to_timestamp.any_vec(),
|
||||
],
|
||||
self.indexes_to_block_interval.any_vecs(),
|
||||
self.timeindexes_to_timestamp.any_vecs(),
|
||||
self.indexes_to_block_count.any_vecs(),
|
||||
self.indexes_to_block_weight.any_vecs(),
|
||||
self.indexes_to_block_interval.any_vecs(),
|
||||
self.indexes_to_block_size.any_vecs(),
|
||||
self.indexes_to_block_vbytes.any_vecs(),
|
||||
self.indexes_to_block_weight.any_vecs(),
|
||||
]
|
||||
.concat()
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{CheckedSub, StoredUsize};
|
||||
use brk_exit::Exit;
|
||||
use brk_vec::{
|
||||
Compressed, DynamicVec, GenericVec, Result, StoredIndex, StoredType, StoredVec, Version,
|
||||
};
|
||||
use brk_vec::{Compressed, DynamicVec, Result, StoredIndex, StoredType, StoredVec, Version};
|
||||
use color_eyre::eyre::ContextCompat;
|
||||
|
||||
use crate::storage::vecs::base::ComputedVec;
|
||||
|
||||
use super::ComputedType;
|
||||
use crate::storage::{ComputedType, EagerVec};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ComputedVecBuilder<I, T>
|
||||
@@ -16,18 +13,18 @@ where
|
||||
I: StoredIndex,
|
||||
T: ComputedType,
|
||||
{
|
||||
first: Option<ComputedVec<I, T>>,
|
||||
average: Option<ComputedVec<I, T>>,
|
||||
sum: Option<ComputedVec<I, T>>,
|
||||
max: Option<ComputedVec<I, T>>,
|
||||
_90p: Option<ComputedVec<I, T>>,
|
||||
_75p: Option<ComputedVec<I, T>>,
|
||||
median: Option<ComputedVec<I, T>>,
|
||||
_25p: Option<ComputedVec<I, T>>,
|
||||
_10p: Option<ComputedVec<I, T>>,
|
||||
min: Option<ComputedVec<I, T>>,
|
||||
last: Option<ComputedVec<I, T>>,
|
||||
total: Option<ComputedVec<I, T>>,
|
||||
first: Option<EagerVec<I, T>>,
|
||||
average: Option<EagerVec<I, T>>,
|
||||
sum: Option<EagerVec<I, T>>,
|
||||
max: Option<EagerVec<I, T>>,
|
||||
_90p: Option<EagerVec<I, T>>,
|
||||
_75p: Option<EagerVec<I, T>>,
|
||||
median: Option<EagerVec<I, T>>,
|
||||
_25p: Option<EagerVec<I, T>>,
|
||||
_10p: Option<EagerVec<I, T>>,
|
||||
min: Option<EagerVec<I, T>>,
|
||||
last: Option<EagerVec<I, T>>,
|
||||
total: Option<EagerVec<I, T>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
@@ -74,15 +71,11 @@ where
|
||||
|
||||
let s = Self {
|
||||
first: options.first.then(|| {
|
||||
ComputedVec::forced_import(
|
||||
&maybe_prefix("first"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap()
|
||||
EagerVec::forced_import(&maybe_prefix("first"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
}),
|
||||
last: options.last.then(|| {
|
||||
ComputedVec::forced_import(
|
||||
EagerVec::forced_import(
|
||||
&path.join(format!("{key}_to_{name}")),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
@@ -90,23 +83,15 @@ where
|
||||
.unwrap()
|
||||
}),
|
||||
min: options.min.then(|| {
|
||||
ComputedVec::forced_import(
|
||||
&maybe_suffix("min"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap()
|
||||
EagerVec::forced_import(&maybe_suffix("min"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
}),
|
||||
max: options.max.then(|| {
|
||||
ComputedVec::forced_import(
|
||||
&maybe_suffix("max"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap()
|
||||
EagerVec::forced_import(&maybe_suffix("max"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
}),
|
||||
median: options.median.then(|| {
|
||||
ComputedVec::forced_import(
|
||||
EagerVec::forced_import(
|
||||
&maybe_suffix("median"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
@@ -114,7 +99,7 @@ where
|
||||
.unwrap()
|
||||
}),
|
||||
average: options.average.then(|| {
|
||||
ComputedVec::forced_import(
|
||||
EagerVec::forced_import(
|
||||
&maybe_suffix("average"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
@@ -122,55 +107,35 @@ where
|
||||
.unwrap()
|
||||
}),
|
||||
sum: options.sum.then(|| {
|
||||
ComputedVec::forced_import(
|
||||
&maybe_suffix("sum"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap()
|
||||
EagerVec::forced_import(&maybe_suffix("sum"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
}),
|
||||
total: options.total.then(|| {
|
||||
ComputedVec::forced_import(&prefix("total"), version + Version::ZERO, compressed)
|
||||
EagerVec::forced_import(&prefix("total"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
}),
|
||||
_90p: options._90p.then(|| {
|
||||
ComputedVec::forced_import(
|
||||
&maybe_suffix("90p"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap()
|
||||
EagerVec::forced_import(&maybe_suffix("90p"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
}),
|
||||
_75p: options._75p.then(|| {
|
||||
ComputedVec::forced_import(
|
||||
&maybe_suffix("75p"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap()
|
||||
EagerVec::forced_import(&maybe_suffix("75p"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
}),
|
||||
_25p: options._25p.then(|| {
|
||||
ComputedVec::forced_import(
|
||||
&maybe_suffix("25p"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap()
|
||||
EagerVec::forced_import(&maybe_suffix("25p"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
}),
|
||||
_10p: options._10p.then(|| {
|
||||
ComputedVec::forced_import(
|
||||
&maybe_suffix("10p"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap()
|
||||
EagerVec::forced_import(&maybe_suffix("10p"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
}),
|
||||
};
|
||||
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, max_from: I, source: &mut StoredVec<I, T>, exit: &Exit) -> Result<()> {
|
||||
pub fn extend(&mut self, max_from: I, source: &StoredVec<I, T>, exit: &Exit) -> Result<()> {
|
||||
if self.total.is_none() {
|
||||
return Ok(());
|
||||
};
|
||||
@@ -179,19 +144,12 @@ where
|
||||
|
||||
let total_vec = self.total.as_mut().unwrap();
|
||||
|
||||
source.iter_from(index, |(i, v, ..)| {
|
||||
let prev = i
|
||||
.unwrap_to_usize()
|
||||
.checked_sub(1)
|
||||
.map_or(T::from(0_usize), |prev_i| {
|
||||
total_vec
|
||||
.unwrap_cached_get(I::from(prev_i))
|
||||
.unwrap_or(T::from(0_usize))
|
||||
});
|
||||
let value = v.clone() + prev;
|
||||
total_vec.forced_push_at(i, value, exit)?;
|
||||
|
||||
Ok(())
|
||||
let mut total = index.decremented().map_or(T::from(0_usize), |index| {
|
||||
total_vec.iter().unwrap_get_inner(index)
|
||||
});
|
||||
source.iter_at(index).try_for_each(|(i, v)| -> Result<()> {
|
||||
total = total.clone() + v.into_inner();
|
||||
total_vec.forced_push_at(i, total.clone(), exit)
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)?;
|
||||
@@ -202,132 +160,154 @@ where
|
||||
pub fn compute<I2>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
source: &mut StoredVec<I2, T>,
|
||||
first_indexes: &mut StoredVec<I, I2>,
|
||||
last_indexes: &mut StoredVec<I, I2>,
|
||||
source: &StoredVec<I2, T>,
|
||||
first_indexes: &StoredVec<I, I2>,
|
||||
count_indexes: &StoredVec<I, StoredUsize>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
I2: StoredIndex + StoredType,
|
||||
T: Ord + From<f64>,
|
||||
f64: From<T>,
|
||||
I2: StoredIndex + StoredType + CheckedSub<I2>,
|
||||
{
|
||||
let index = self.starting_index(max_from);
|
||||
|
||||
first_indexes.iter_from(index, |(i, first_index, first_indexes)| {
|
||||
let last_index = last_indexes.double_unwrap_cached_get(i);
|
||||
let mut count_indexes_iter = count_indexes.iter();
|
||||
let mut source_iter = source.iter();
|
||||
|
||||
if let Some(first) = self.first.as_mut() {
|
||||
let v = source.double_unwrap_cached_get(first_index);
|
||||
first.forced_push_at(index, v, exit)?;
|
||||
}
|
||||
let total_vec = self.total.as_mut();
|
||||
|
||||
if let Some(last) = self.last.as_mut() {
|
||||
let v = source.double_unwrap_cached_get(last_index);
|
||||
last.forced_push_at(index, v, exit)?;
|
||||
}
|
||||
let mut total = total_vec.map(|total_vec| {
|
||||
index.decremented().map_or(T::from(0_usize), |index| {
|
||||
total_vec.iter().unwrap_get_inner(index)
|
||||
})
|
||||
});
|
||||
|
||||
let needs_sum_or_total = self.sum.is_some() || self.total.is_some();
|
||||
let needs_average_sum_or_total = needs_sum_or_total || self.average.is_some();
|
||||
let needs_sorted = self.max.is_some()
|
||||
|| self._90p.is_some()
|
||||
|| self._75p.is_some()
|
||||
|| self.median.is_some()
|
||||
|| self._25p.is_some()
|
||||
|| self._10p.is_some()
|
||||
|| self.min.is_some();
|
||||
let needs_values = needs_sorted || needs_average_sum_or_total;
|
||||
first_indexes
|
||||
.iter_at(index)
|
||||
.try_for_each(|(i, first_index)| -> Result<()> {
|
||||
let first_index = first_index.into_inner();
|
||||
|
||||
if needs_values {
|
||||
let mut values = source.collect_inclusive_range(first_index, last_index)?;
|
||||
let count_index = count_indexes_iter.get(i).unwrap().1.into_inner();
|
||||
|
||||
if needs_sorted {
|
||||
values.sort_unstable();
|
||||
|
||||
if let Some(max) = self.max.as_mut() {
|
||||
max.forced_push_at(
|
||||
i,
|
||||
values
|
||||
.last()
|
||||
.context("expect some")
|
||||
.inspect_err(|_| {
|
||||
dbg!(
|
||||
&values,
|
||||
max.path(),
|
||||
first_indexes.path(),
|
||||
first_index,
|
||||
last_indexes.path(),
|
||||
last_index,
|
||||
source.len(),
|
||||
source.path()
|
||||
);
|
||||
})
|
||||
.unwrap()
|
||||
.clone(),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
if let Some(_90p) = self._90p.as_mut() {
|
||||
_90p.forced_push_at(i, Self::get_percentile(&values, 0.90), exit)?;
|
||||
}
|
||||
|
||||
if let Some(_75p) = self._75p.as_mut() {
|
||||
_75p.forced_push_at(i, Self::get_percentile(&values, 0.75), exit)?;
|
||||
}
|
||||
|
||||
if let Some(median) = self.median.as_mut() {
|
||||
median.forced_push_at(i, Self::get_percentile(&values, 0.50), exit)?;
|
||||
}
|
||||
|
||||
if let Some(_25p) = self._25p.as_mut() {
|
||||
_25p.forced_push_at(i, Self::get_percentile(&values, 0.25), exit)?;
|
||||
}
|
||||
|
||||
if let Some(_10p) = self._10p.as_mut() {
|
||||
_10p.forced_push_at(i, Self::get_percentile(&values, 0.10), exit)?;
|
||||
}
|
||||
|
||||
if let Some(min) = self.min.as_mut() {
|
||||
min.forced_push_at(i, values.first().unwrap().clone(), exit)?;
|
||||
}
|
||||
if let Some(first) = self.first.as_mut() {
|
||||
let f = source_iter
|
||||
.get(first_index)
|
||||
.map_or(T::from(0_usize), |f| f.1.into_inner());
|
||||
first.forced_push_at(index, f, exit)?;
|
||||
}
|
||||
|
||||
if needs_average_sum_or_total {
|
||||
let len = values.len();
|
||||
if let Some(last) = self.last.as_mut() {
|
||||
let count_index = *count_index;
|
||||
if count_index == 0 {
|
||||
panic!("should compute last if count can be 0")
|
||||
}
|
||||
let last_index = first_index + (count_index - 1);
|
||||
let v = source_iter
|
||||
.get(last_index)
|
||||
.context("to work")
|
||||
.inspect_err(|_| {
|
||||
dbg!(first_index, count_index, last_index);
|
||||
})
|
||||
.unwrap()
|
||||
.1
|
||||
.into_inner();
|
||||
last.forced_push_at(index, v, exit)?;
|
||||
}
|
||||
|
||||
if let Some(average) = self.average.as_mut() {
|
||||
let len = len as f64;
|
||||
let total = values
|
||||
.iter()
|
||||
.map(|v| f64::from(v.clone()))
|
||||
.fold(0.0, |a, b| a + b);
|
||||
let avg = T::from(total / len);
|
||||
average.forced_push_at(i, avg, exit)?;
|
||||
let needs_sum_or_total = self.sum.is_some() || self.total.is_some();
|
||||
let needs_average_sum_or_total = needs_sum_or_total || self.average.is_some();
|
||||
let needs_sorted = self.max.is_some()
|
||||
|| self._90p.is_some()
|
||||
|| self._75p.is_some()
|
||||
|| self.median.is_some()
|
||||
|| self._25p.is_some()
|
||||
|| self._10p.is_some()
|
||||
|| self.min.is_some();
|
||||
let needs_values = needs_sorted || needs_average_sum_or_total;
|
||||
|
||||
if needs_values {
|
||||
source_iter.set(first_index);
|
||||
let mut values = (&mut source_iter)
|
||||
.take(*count_index)
|
||||
.map(|(_, v)| v.into_inner())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if needs_sorted {
|
||||
values.sort_unstable();
|
||||
|
||||
if let Some(max) = self.max.as_mut() {
|
||||
max.forced_push_at(
|
||||
i,
|
||||
values
|
||||
.last()
|
||||
.context("expect some")
|
||||
.inspect_err(|_| {
|
||||
dbg!(
|
||||
&values,
|
||||
max.path(),
|
||||
first_indexes.path(),
|
||||
first_index,
|
||||
count_indexes.path(),
|
||||
count_index,
|
||||
source.len(),
|
||||
source.path()
|
||||
);
|
||||
})
|
||||
.unwrap()
|
||||
.clone(),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
if let Some(_90p) = self._90p.as_mut() {
|
||||
_90p.forced_push_at(i, Self::get_percentile(&values, 0.90), exit)?;
|
||||
}
|
||||
|
||||
if let Some(_75p) = self._75p.as_mut() {
|
||||
_75p.forced_push_at(i, Self::get_percentile(&values, 0.75), exit)?;
|
||||
}
|
||||
|
||||
if let Some(median) = self.median.as_mut() {
|
||||
median.forced_push_at(i, Self::get_percentile(&values, 0.50), exit)?;
|
||||
}
|
||||
|
||||
if let Some(_25p) = self._25p.as_mut() {
|
||||
_25p.forced_push_at(i, Self::get_percentile(&values, 0.25), exit)?;
|
||||
}
|
||||
|
||||
if let Some(_10p) = self._10p.as_mut() {
|
||||
_10p.forced_push_at(i, Self::get_percentile(&values, 0.10), exit)?;
|
||||
}
|
||||
|
||||
if let Some(min) = self.min.as_mut() {
|
||||
min.forced_push_at(i, values.first().unwrap().clone(), exit)?;
|
||||
}
|
||||
}
|
||||
|
||||
if needs_sum_or_total {
|
||||
if needs_average_sum_or_total {
|
||||
let len = values.len();
|
||||
let sum = values.into_iter().fold(T::from(0), |a, b| a + b);
|
||||
|
||||
if let Some(sum_vec) = self.sum.as_mut() {
|
||||
sum_vec.forced_push_at(i, sum.clone(), exit)?;
|
||||
if let Some(average) = self.average.as_mut() {
|
||||
let avg = sum.clone() / len;
|
||||
average.forced_push_at(i, avg, exit)?;
|
||||
}
|
||||
|
||||
if let Some(total_vec) = self.total.as_mut() {
|
||||
let prev = i
|
||||
.unwrap_to_usize()
|
||||
.checked_sub(1)
|
||||
.map_or(T::from(0_usize), |prev_i| {
|
||||
total_vec.double_unwrap_cached_get(I::from(prev_i))
|
||||
});
|
||||
total_vec.forced_push_at(i, prev + sum, exit)?;
|
||||
if needs_sum_or_total {
|
||||
if let Some(sum_vec) = self.sum.as_mut() {
|
||||
sum_vec.forced_push_at(i, sum.clone(), exit)?;
|
||||
}
|
||||
|
||||
if let Some(total_vec) = self.total.as_mut() {
|
||||
let t = total.as_ref().unwrap().clone() + sum;
|
||||
total.replace(t.clone());
|
||||
total_vec.forced_push_at(i, t, exit)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)?;
|
||||
|
||||
@@ -338,15 +318,13 @@ where
|
||||
pub fn from_aligned<I2>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
source: &mut ComputedVecBuilder<I2, T>,
|
||||
first_indexes: &mut StoredVec<I, I2>,
|
||||
last_indexes: &mut StoredVec<I, I2>,
|
||||
source: &ComputedVecBuilder<I2, T>,
|
||||
first_indexes: &StoredVec<I, I2>,
|
||||
count_indexes: &StoredVec<I, StoredUsize>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
I2: StoredIndex + StoredType,
|
||||
T: Ord + From<f64>,
|
||||
f64: From<T>,
|
||||
I2: StoredIndex + StoredType + CheckedSub<I2>,
|
||||
{
|
||||
if self._90p.is_some()
|
||||
|| self._75p.is_some()
|
||||
@@ -359,100 +337,121 @@ where
|
||||
|
||||
let index = self.starting_index(max_from);
|
||||
|
||||
first_indexes.iter_from(index, |(i, first_index, ..)| {
|
||||
let last_index = last_indexes.double_unwrap_cached_get(i);
|
||||
let mut count_indexes_iter = count_indexes.iter();
|
||||
|
||||
if let Some(first) = self.first.as_mut() {
|
||||
let v = source
|
||||
.first
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.double_unwrap_cached_get(first_index);
|
||||
first.forced_push_at(index, v, exit)?;
|
||||
}
|
||||
let mut source_first_iter = source.first.as_ref().map(|f| f.iter());
|
||||
let mut source_last_iter = source.last.as_ref().map(|f| f.iter());
|
||||
let mut source_max_iter = source.max.as_ref().map(|f| f.iter());
|
||||
let mut source_min_iter = source.min.as_ref().map(|f| f.iter());
|
||||
let mut source_average_iter = source.average.as_ref().map(|f| f.iter());
|
||||
let mut source_sum_iter = source.sum.as_ref().map(|f| f.iter());
|
||||
|
||||
if let Some(last) = self.last.as_mut() {
|
||||
let v = source
|
||||
.last
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.double_unwrap_cached_get(last_index);
|
||||
last.forced_push_at(index, v, exit)?;
|
||||
}
|
||||
let mut total = self.total.as_mut().map(|total_vec| {
|
||||
index.decremented().map_or(T::from(0_usize), |index| {
|
||||
total_vec.iter().unwrap_get_inner(index)
|
||||
})
|
||||
});
|
||||
|
||||
let needs_sum_or_total = self.sum.is_some() || self.total.is_some();
|
||||
let needs_average_sum_or_total = needs_sum_or_total || self.average.is_some();
|
||||
let needs_sorted = self.max.is_some() || self.min.is_some();
|
||||
let needs_values = needs_sorted || needs_average_sum_or_total;
|
||||
first_indexes
|
||||
.iter_at(index)
|
||||
.try_for_each(|(i, first_index, ..)| -> Result<()> {
|
||||
let first_index = first_index.into_inner();
|
||||
|
||||
if needs_values {
|
||||
if needs_sorted {
|
||||
if let Some(max) = self.max.as_mut() {
|
||||
let mut values = source
|
||||
.max
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.collect_inclusive_range(first_index, last_index)?;
|
||||
values.sort_unstable();
|
||||
max.forced_push_at(i, values.last().unwrap().clone(), exit)?;
|
||||
}
|
||||
let count_index = count_indexes_iter.get(i).unwrap().1.into_inner();
|
||||
|
||||
if let Some(min) = self.min.as_mut() {
|
||||
let mut values = source
|
||||
.min
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.collect_inclusive_range(first_index, last_index)?;
|
||||
values.sort_unstable();
|
||||
min.forced_push_at(i, values.first().unwrap().clone(), exit)?;
|
||||
}
|
||||
if let Some(first) = self.first.as_mut() {
|
||||
let v = source_first_iter
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.unwrap_get_inner(first_index);
|
||||
first.forced_push_at(index, v, exit)?;
|
||||
}
|
||||
|
||||
if needs_average_sum_or_total {
|
||||
if let Some(average) = self.average.as_mut() {
|
||||
let values = source
|
||||
.average
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.collect_inclusive_range(first_index, last_index)?;
|
||||
let len = values.len() as f64;
|
||||
let total = values
|
||||
.into_iter()
|
||||
.map(|v| f64::from(v))
|
||||
.fold(0.0, |a, b| a + b);
|
||||
// TODO: Multiply by count then divide by total
|
||||
// Right now it's not 100% accurate as there could be more or less elements in the lower timeframe (28 days vs 31 days in a month for example)
|
||||
let avg = T::from(total / len);
|
||||
average.forced_push_at(i, avg, exit)?;
|
||||
if let Some(last) = self.last.as_mut() {
|
||||
let count_index = *count_index;
|
||||
if count_index == 0 {
|
||||
panic!("should compute last if count can be 0")
|
||||
}
|
||||
let last_index = first_index + (count_index - 1);
|
||||
let v = source_last_iter
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.unwrap_get_inner(last_index);
|
||||
last.forced_push_at(index, v, exit)?;
|
||||
}
|
||||
|
||||
if needs_sum_or_total {
|
||||
let values = source
|
||||
.sum
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.collect_inclusive_range(first_index, last_index)?;
|
||||
let sum = values.into_iter().fold(T::from(0), |a, b| a + b);
|
||||
let needs_sum_or_total = self.sum.is_some() || self.total.is_some();
|
||||
let needs_average_sum_or_total = needs_sum_or_total || self.average.is_some();
|
||||
let needs_sorted = self.max.is_some() || self.min.is_some();
|
||||
let needs_values = needs_sorted || needs_average_sum_or_total;
|
||||
|
||||
if let Some(sum_vec) = self.sum.as_mut() {
|
||||
sum_vec.forced_push_at(i, sum.clone(), exit)?;
|
||||
if needs_values {
|
||||
if needs_sorted {
|
||||
if let Some(max) = self.max.as_mut() {
|
||||
let source_max_iter = source_max_iter.as_mut().unwrap();
|
||||
source_max_iter.set(first_index);
|
||||
let mut values = source_max_iter
|
||||
.take(*count_index)
|
||||
.map(|(_, v)| v.into_inner())
|
||||
.collect::<Vec<_>>();
|
||||
values.sort_unstable();
|
||||
max.forced_push_at(i, values.last().unwrap().clone(), exit)?;
|
||||
}
|
||||
|
||||
if let Some(total_vec) = self.total.as_mut() {
|
||||
let prev = i
|
||||
.unwrap_to_usize()
|
||||
.checked_sub(1)
|
||||
.map_or(T::from(0_usize), |prev_i| {
|
||||
total_vec.double_unwrap_cached_get(I::from(prev_i))
|
||||
});
|
||||
total_vec.forced_push_at(i, prev + sum, exit)?;
|
||||
if let Some(min) = self.min.as_mut() {
|
||||
let source_min_iter = source_min_iter.as_mut().unwrap();
|
||||
source_min_iter.set(first_index);
|
||||
let mut values = source_min_iter
|
||||
.take(*count_index)
|
||||
.map(|(_, v)| v.into_inner())
|
||||
.collect::<Vec<_>>();
|
||||
values.sort_unstable();
|
||||
min.forced_push_at(i, values.first().unwrap().clone(), exit)?;
|
||||
}
|
||||
}
|
||||
|
||||
if needs_average_sum_or_total {
|
||||
if let Some(average) = self.average.as_mut() {
|
||||
let source_average_iter = source_average_iter.as_mut().unwrap();
|
||||
source_average_iter.set(first_index);
|
||||
let values = source_average_iter
|
||||
.take(*count_index)
|
||||
.map(|(_, v)| v.into_inner())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let len = values.len();
|
||||
let total = values.into_iter().fold(T::from(0), |a, b| a + b);
|
||||
// TODO: Multiply by count then divide by total
|
||||
// Right now it's not 100% accurate as there could be more or less elements in the lower timeframe (28 days vs 31 days in a month for example)
|
||||
let avg = total / len;
|
||||
average.forced_push_at(i, avg, exit)?;
|
||||
}
|
||||
|
||||
if needs_sum_or_total {
|
||||
let source_sum_iter = source_sum_iter.as_mut().unwrap();
|
||||
source_sum_iter.set(first_index);
|
||||
let values = source_sum_iter
|
||||
.take(*count_index)
|
||||
.map(|(_, v)| v.into_inner())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let sum = values.into_iter().fold(T::from(0), |a, b| a + b);
|
||||
|
||||
if let Some(sum_vec) = self.sum.as_mut() {
|
||||
sum_vec.forced_push_at(i, sum.clone(), exit)?;
|
||||
}
|
||||
|
||||
if let Some(total_vec) = self.total.as_mut() {
|
||||
let t = total.as_ref().unwrap().clone() + sum;
|
||||
total.replace(t.clone());
|
||||
total_vec.forced_push_at(i, t, exit)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)?;
|
||||
|
||||
@@ -487,40 +486,40 @@ where
|
||||
))
|
||||
}
|
||||
|
||||
pub fn unwrap_first(&mut self) -> &mut ComputedVec<I, T> {
|
||||
pub fn unwrap_first(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.first.as_mut().unwrap()
|
||||
}
|
||||
pub fn unwrap_average(&mut self) -> &mut ComputedVec<I, T> {
|
||||
pub fn unwrap_average(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.average.as_mut().unwrap()
|
||||
}
|
||||
pub fn unwrap_sum(&mut self) -> &mut ComputedVec<I, T> {
|
||||
pub fn unwrap_sum(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.sum.as_mut().unwrap()
|
||||
}
|
||||
pub fn unwrap_max(&mut self) -> &mut ComputedVec<I, T> {
|
||||
pub fn unwrap_max(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.max.as_mut().unwrap()
|
||||
}
|
||||
pub fn unwrap_90p(&mut self) -> &mut ComputedVec<I, T> {
|
||||
pub fn unwrap_90p(&mut self) -> &mut EagerVec<I, T> {
|
||||
self._90p.as_mut().unwrap()
|
||||
}
|
||||
pub fn unwrap_75p(&mut self) -> &mut ComputedVec<I, T> {
|
||||
pub fn unwrap_75p(&mut self) -> &mut EagerVec<I, T> {
|
||||
self._75p.as_mut().unwrap()
|
||||
}
|
||||
pub fn unwrap_median(&mut self) -> &mut ComputedVec<I, T> {
|
||||
pub fn unwrap_median(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.median.as_mut().unwrap()
|
||||
}
|
||||
pub fn unwrap_25p(&mut self) -> &mut ComputedVec<I, T> {
|
||||
pub fn unwrap_25p(&mut self) -> &mut EagerVec<I, T> {
|
||||
self._25p.as_mut().unwrap()
|
||||
}
|
||||
pub fn unwrap_10p(&mut self) -> &mut ComputedVec<I, T> {
|
||||
pub fn unwrap_10p(&mut self) -> &mut EagerVec<I, T> {
|
||||
self._10p.as_mut().unwrap()
|
||||
}
|
||||
pub fn unwrap_min(&mut self) -> &mut ComputedVec<I, T> {
|
||||
pub fn unwrap_min(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.min.as_mut().unwrap()
|
||||
}
|
||||
pub fn unwrap_last(&mut self) -> &mut ComputedVec<I, T> {
|
||||
pub fn unwrap_last(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.last.as_mut().unwrap()
|
||||
}
|
||||
pub fn unwrap_total(&mut self) -> &mut ComputedVec<I, T> {
|
||||
pub fn unwrap_total(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.total.as_mut().unwrap()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +1,33 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{Dateindex, Decadeindex, Monthindex, Quarterindex, Weekindex, Yearindex};
|
||||
use brk_core::{DateIndex, DecadeIndex, MonthIndex, QuarterIndex, WeekIndex, YearIndex};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyStoredVec, Compressed, Result, Version};
|
||||
|
||||
use crate::storage::vecs::{Indexes, base::ComputedVec, indexes};
|
||||
use crate::storage::{ComputedType, EagerVec, Indexes, indexes};
|
||||
|
||||
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
use super::{ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ComputedVecsFromDateindex<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
{
|
||||
pub dateindex: ComputedVec<Dateindex, T>,
|
||||
pub dateindex_extra: ComputedVecBuilder<Dateindex, T>,
|
||||
pub weekindex: ComputedVecBuilder<Weekindex, T>,
|
||||
pub monthindex: ComputedVecBuilder<Monthindex, T>,
|
||||
pub quarterindex: ComputedVecBuilder<Quarterindex, T>,
|
||||
pub yearindex: ComputedVecBuilder<Yearindex, T>,
|
||||
pub decadeindex: ComputedVecBuilder<Decadeindex, T>,
|
||||
pub dateindex: EagerVec<DateIndex, T>,
|
||||
pub dateindex_extra: ComputedVecBuilder<DateIndex, T>,
|
||||
pub weekindex: ComputedVecBuilder<WeekIndex, T>,
|
||||
pub monthindex: ComputedVecBuilder<MonthIndex, T>,
|
||||
pub quarterindex: ComputedVecBuilder<QuarterIndex, T>,
|
||||
pub yearindex: ComputedVecBuilder<YearIndex, T>,
|
||||
pub decadeindex: ComputedVecBuilder<DecadeIndex, T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedVecsFromDateindex<T>
|
||||
where
|
||||
T: ComputedType + Ord + From<f64>,
|
||||
f64: From<T>,
|
||||
T: ComputedType,
|
||||
{
|
||||
pub fn forced_import(
|
||||
path: &Path,
|
||||
@@ -50,7 +49,7 @@ where
|
||||
let options = options.remove_percentiles();
|
||||
|
||||
Ok(Self {
|
||||
dateindex: ComputedVec::forced_import(
|
||||
dateindex: EagerVec::forced_import(
|
||||
&path.join(format!("dateindex_to_{name}")),
|
||||
version,
|
||||
compressed,
|
||||
@@ -72,17 +71,17 @@ where
|
||||
|
||||
pub fn compute<F>(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
indexes: &mut indexes::Vecs,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> color_eyre::Result<()>
|
||||
where
|
||||
F: FnMut(
|
||||
&mut ComputedVec<Dateindex, T>,
|
||||
&mut Indexer,
|
||||
&mut indexes::Vecs,
|
||||
&mut EagerVec<DateIndex, T>,
|
||||
&Indexer,
|
||||
&indexes::Vecs,
|
||||
&Indexes,
|
||||
&Exit,
|
||||
) -> Result<()>,
|
||||
@@ -96,45 +95,45 @@ where
|
||||
)?;
|
||||
|
||||
self.dateindex_extra
|
||||
.extend(starting_indexes.dateindex, self.dateindex.mut_vec(), exit)?;
|
||||
.extend(starting_indexes.dateindex, self.dateindex.vec(), exit)?;
|
||||
|
||||
self.weekindex.compute(
|
||||
starting_indexes.weekindex,
|
||||
self.dateindex.mut_vec(),
|
||||
indexes.weekindex_to_first_dateindex.mut_vec(),
|
||||
indexes.weekindex_to_last_dateindex.mut_vec(),
|
||||
self.dateindex.vec(),
|
||||
indexes.weekindex_to_first_dateindex.vec(),
|
||||
indexes.weekindex_to_dateindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.monthindex.compute(
|
||||
starting_indexes.monthindex,
|
||||
self.dateindex.mut_vec(),
|
||||
indexes.monthindex_to_first_dateindex.mut_vec(),
|
||||
indexes.monthindex_to_last_dateindex.mut_vec(),
|
||||
self.dateindex.vec(),
|
||||
indexes.monthindex_to_first_dateindex.vec(),
|
||||
indexes.monthindex_to_dateindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.quarterindex.from_aligned(
|
||||
starting_indexes.quarterindex,
|
||||
&mut self.monthindex,
|
||||
indexes.quarterindex_to_first_monthindex.mut_vec(),
|
||||
indexes.quarterindex_to_last_monthindex.mut_vec(),
|
||||
&self.monthindex,
|
||||
indexes.quarterindex_to_first_monthindex.vec(),
|
||||
indexes.quarterindex_to_monthindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.yearindex.from_aligned(
|
||||
starting_indexes.yearindex,
|
||||
&mut self.monthindex,
|
||||
indexes.yearindex_to_first_monthindex.mut_vec(),
|
||||
indexes.yearindex_to_last_monthindex.mut_vec(),
|
||||
&self.monthindex,
|
||||
indexes.yearindex_to_first_monthindex.vec(),
|
||||
indexes.yearindex_to_monthindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.decadeindex.from_aligned(
|
||||
starting_indexes.decadeindex,
|
||||
&mut self.yearindex,
|
||||
indexes.decadeindex_to_first_yearindex.mut_vec(),
|
||||
indexes.decadeindex_to_last_yearindex.mut_vec(),
|
||||
&self.yearindex,
|
||||
indexes.decadeindex_to_first_yearindex.vec(),
|
||||
indexes.decadeindex_to_yearindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{
|
||||
Dateindex, Decadeindex, Difficultyepoch, Height, Monthindex, Quarterindex, Weekindex, Yearindex,
|
||||
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex,
|
||||
};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyStoredVec, Compressed, Result, StoredVec, Version};
|
||||
|
||||
use crate::storage::vecs::{Indexes, base::ComputedVec, indexes};
|
||||
use crate::storage::{ComputedType, EagerVec, Indexes, indexes};
|
||||
|
||||
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
use super::{ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ComputedVecsFromHeight<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
{
|
||||
pub height: Option<ComputedVec<Height, T>>,
|
||||
pub height: Option<EagerVec<Height, T>>,
|
||||
pub height_extra: ComputedVecBuilder<Height, T>,
|
||||
pub dateindex: ComputedVecBuilder<Dateindex, T>,
|
||||
pub weekindex: ComputedVecBuilder<Weekindex, T>,
|
||||
pub difficultyepoch: ComputedVecBuilder<Difficultyepoch, T>,
|
||||
pub monthindex: ComputedVecBuilder<Monthindex, T>,
|
||||
pub quarterindex: ComputedVecBuilder<Quarterindex, T>,
|
||||
pub yearindex: ComputedVecBuilder<Yearindex, T>,
|
||||
pub dateindex: ComputedVecBuilder<DateIndex, T>,
|
||||
pub weekindex: ComputedVecBuilder<WeekIndex, T>,
|
||||
pub difficultyepoch: ComputedVecBuilder<DifficultyEpoch, T>,
|
||||
pub monthindex: ComputedVecBuilder<MonthIndex, T>,
|
||||
pub quarterindex: ComputedVecBuilder<QuarterIndex, T>,
|
||||
pub yearindex: ComputedVecBuilder<YearIndex, T>,
|
||||
// TODO: pub halvingepoch: StorableVecGeneator<Halvingepoch, T>,
|
||||
pub decadeindex: ComputedVecBuilder<Decadeindex, T>,
|
||||
pub decadeindex: ComputedVecBuilder<DecadeIndex, T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
@@ -46,7 +46,7 @@ where
|
||||
let version = VERSION + version;
|
||||
|
||||
let height = compute_source.then(|| {
|
||||
ComputedVec::forced_import(&path.join(format!("height_to_{name}")), version, compressed)
|
||||
EagerVec::forced_import(&path.join(format!("height_to_{name}")), version, compressed)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
@@ -87,20 +87,14 @@ where
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
indexes: &mut indexes::Vecs,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> color_eyre::Result<()>
|
||||
where
|
||||
F: FnMut(
|
||||
&mut ComputedVec<Height, T>,
|
||||
&mut Indexer,
|
||||
&mut indexes::Vecs,
|
||||
&Indexes,
|
||||
&Exit,
|
||||
) -> Result<()>,
|
||||
F: FnMut(&mut EagerVec<Height, T>, &Indexer, &indexes::Vecs, &Indexes, &Exit) -> Result<()>,
|
||||
{
|
||||
compute(
|
||||
self.height.as_mut().unwrap(),
|
||||
@@ -117,12 +111,12 @@ where
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexes: &mut indexes::Vecs,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
height: Option<&mut StoredVec<Height, T>>,
|
||||
height: Option<&StoredVec<Height, T>>,
|
||||
) -> color_eyre::Result<()> {
|
||||
let height = height.unwrap_or_else(|| self.height.as_mut().unwrap().mut_vec());
|
||||
let height = height.unwrap_or_else(|| self.height.as_ref().unwrap().vec());
|
||||
|
||||
self.height_extra
|
||||
.extend(starting_indexes.height, height, exit)?;
|
||||
@@ -130,56 +124,56 @@ where
|
||||
self.dateindex.compute(
|
||||
starting_indexes.dateindex,
|
||||
height,
|
||||
indexes.dateindex_to_first_height.mut_vec(),
|
||||
indexes.dateindex_to_last_height.mut_vec(),
|
||||
indexes.dateindex_to_first_height.vec(),
|
||||
indexes.dateindex_to_height_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.weekindex.from_aligned(
|
||||
starting_indexes.weekindex,
|
||||
&mut self.dateindex,
|
||||
indexes.weekindex_to_first_dateindex.mut_vec(),
|
||||
indexes.weekindex_to_last_dateindex.mut_vec(),
|
||||
&self.dateindex,
|
||||
indexes.weekindex_to_first_dateindex.vec(),
|
||||
indexes.weekindex_to_dateindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.monthindex.from_aligned(
|
||||
starting_indexes.monthindex,
|
||||
&mut self.dateindex,
|
||||
indexes.monthindex_to_first_dateindex.mut_vec(),
|
||||
indexes.monthindex_to_last_dateindex.mut_vec(),
|
||||
&self.dateindex,
|
||||
indexes.monthindex_to_first_dateindex.vec(),
|
||||
indexes.monthindex_to_dateindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.quarterindex.from_aligned(
|
||||
starting_indexes.quarterindex,
|
||||
&mut self.monthindex,
|
||||
indexes.quarterindex_to_first_monthindex.mut_vec(),
|
||||
indexes.quarterindex_to_last_monthindex.mut_vec(),
|
||||
&self.monthindex,
|
||||
indexes.quarterindex_to_first_monthindex.vec(),
|
||||
indexes.quarterindex_to_monthindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.yearindex.from_aligned(
|
||||
starting_indexes.yearindex,
|
||||
&mut self.monthindex,
|
||||
indexes.yearindex_to_first_monthindex.mut_vec(),
|
||||
indexes.yearindex_to_last_monthindex.mut_vec(),
|
||||
&self.monthindex,
|
||||
indexes.yearindex_to_first_monthindex.vec(),
|
||||
indexes.yearindex_to_monthindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.decadeindex.from_aligned(
|
||||
starting_indexes.decadeindex,
|
||||
&mut self.yearindex,
|
||||
indexes.decadeindex_to_first_yearindex.mut_vec(),
|
||||
indexes.decadeindex_to_last_yearindex.mut_vec(),
|
||||
&self.yearindex,
|
||||
indexes.decadeindex_to_first_yearindex.vec(),
|
||||
indexes.decadeindex_to_yearindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.difficultyepoch.compute(
|
||||
starting_indexes.difficultyepoch,
|
||||
height,
|
||||
indexes.difficultyepoch_to_first_height.mut_vec(),
|
||||
indexes.difficultyepoch_to_last_height.mut_vec(),
|
||||
indexes.difficultyepoch_to_first_height.vec(),
|
||||
indexes.difficultyepoch_to_height_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{Difficultyepoch, Height};
|
||||
use brk_core::{DifficultyEpoch, Height};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyStoredVec, Compressed, Result, Version};
|
||||
|
||||
use crate::storage::vecs::{Indexes, base::ComputedVec, indexes};
|
||||
use crate::storage::{ComputedType, EagerVec, Indexes, indexes};
|
||||
|
||||
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
use super::{ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ComputedVecsFromHeightStrict<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
{
|
||||
pub height: ComputedVec<Height, T>,
|
||||
pub height: EagerVec<Height, T>,
|
||||
pub height_extra: ComputedVecBuilder<Height, T>,
|
||||
pub difficultyepoch: ComputedVecBuilder<Difficultyepoch, T>,
|
||||
pub difficultyepoch: ComputedVecBuilder<DifficultyEpoch, T>,
|
||||
// TODO: pub halvingepoch: StorableVecGeneator<Halvingepoch, T>,
|
||||
}
|
||||
|
||||
@@ -36,11 +36,8 @@ where
|
||||
) -> color_eyre::Result<Self> {
|
||||
let version = VERSION + version;
|
||||
|
||||
let height = ComputedVec::forced_import(
|
||||
&path.join(format!("height_to_{name}")),
|
||||
version,
|
||||
compressed,
|
||||
)?;
|
||||
let height =
|
||||
EagerVec::forced_import(&path.join(format!("height_to_{name}")), version, compressed)?;
|
||||
|
||||
let height_extra = ComputedVecBuilder::forced_import(
|
||||
path,
|
||||
@@ -64,31 +61,25 @@ where
|
||||
|
||||
pub fn compute<F>(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
indexes: &mut indexes::Vecs,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> color_eyre::Result<()>
|
||||
where
|
||||
F: FnMut(
|
||||
&mut ComputedVec<Height, T>,
|
||||
&mut Indexer,
|
||||
&mut indexes::Vecs,
|
||||
&Indexes,
|
||||
&Exit,
|
||||
) -> Result<()>,
|
||||
F: FnMut(&mut EagerVec<Height, T>, &Indexer, &indexes::Vecs, &Indexes, &Exit) -> Result<()>,
|
||||
{
|
||||
compute(&mut self.height, indexer, indexes, starting_indexes, exit)?;
|
||||
|
||||
self.height_extra
|
||||
.extend(starting_indexes.height, self.height.mut_vec(), exit)?;
|
||||
.extend(starting_indexes.height, self.height.vec(), exit)?;
|
||||
|
||||
self.difficultyepoch.compute(
|
||||
starting_indexes.difficultyepoch,
|
||||
self.height.mut_vec(),
|
||||
indexes.difficultyepoch_to_first_height.mut_vec(),
|
||||
indexes.difficultyepoch_to_last_height.mut_vec(),
|
||||
self.height.vec(),
|
||||
indexes.difficultyepoch_to_first_height.vec(),
|
||||
indexes.difficultyepoch_to_height_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{
|
||||
Dateindex, Decadeindex, Difficultyepoch, Height, Monthindex, Quarterindex, Txindex, Weekindex,
|
||||
Yearindex,
|
||||
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, TxIndex, WeekIndex,
|
||||
YearIndex,
|
||||
};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyStoredVec, Compressed, Result, StoredVec, Version};
|
||||
|
||||
use crate::storage::vecs::{Indexes, base::ComputedVec, indexes};
|
||||
use crate::storage::{ComputedType, EagerVec, Indexes, indexes};
|
||||
|
||||
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
use super::{ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ComputedVecsFromTxindex<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
{
|
||||
pub txindex: Option<ComputedVec<Txindex, T>>,
|
||||
pub txindex: Option<EagerVec<TxIndex, T>>,
|
||||
pub height: ComputedVecBuilder<Height, T>,
|
||||
pub dateindex: ComputedVecBuilder<Dateindex, T>,
|
||||
pub weekindex: ComputedVecBuilder<Weekindex, T>,
|
||||
pub difficultyepoch: ComputedVecBuilder<Difficultyepoch, T>,
|
||||
pub monthindex: ComputedVecBuilder<Monthindex, T>,
|
||||
pub quarterindex: ComputedVecBuilder<Quarterindex, T>,
|
||||
pub yearindex: ComputedVecBuilder<Yearindex, T>,
|
||||
pub dateindex: ComputedVecBuilder<DateIndex, T>,
|
||||
pub weekindex: ComputedVecBuilder<WeekIndex, T>,
|
||||
pub difficultyepoch: ComputedVecBuilder<DifficultyEpoch, T>,
|
||||
pub monthindex: ComputedVecBuilder<MonthIndex, T>,
|
||||
pub quarterindex: ComputedVecBuilder<QuarterIndex, T>,
|
||||
pub yearindex: ComputedVecBuilder<YearIndex, T>,
|
||||
// TODO: pub halvingepoch: StorableVecGeneator<Halvingepoch, T>,
|
||||
pub decadeindex: ComputedVecBuilder<Decadeindex, T>,
|
||||
pub decadeindex: ComputedVecBuilder<DecadeIndex, T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
@@ -47,7 +47,7 @@ where
|
||||
let version = VERSION + version;
|
||||
|
||||
let txindex = compute_source.then(|| {
|
||||
ComputedVec::forced_import(
|
||||
EagerVec::forced_import(
|
||||
&path.join(format!("txindex_to_{name}")),
|
||||
version,
|
||||
compressed,
|
||||
@@ -83,17 +83,17 @@ where
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
indexes: &mut indexes::Vecs,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> color_eyre::Result<()>
|
||||
where
|
||||
F: FnMut(
|
||||
&mut ComputedVec<Txindex, T>,
|
||||
&mut Indexer,
|
||||
&mut indexes::Vecs,
|
||||
&mut EagerVec<TxIndex, T>,
|
||||
&Indexer,
|
||||
&indexes::Vecs,
|
||||
&Indexes,
|
||||
&Exit,
|
||||
) -> Result<()>,
|
||||
@@ -113,75 +113,75 @@ where
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
indexes: &mut indexes::Vecs,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
txindex: Option<&mut StoredVec<Txindex, T>>,
|
||||
txindex: Option<&StoredVec<TxIndex, T>>,
|
||||
) -> color_eyre::Result<()> {
|
||||
let txindex = txindex.unwrap_or_else(|| self.txindex.as_mut().unwrap().mut_vec());
|
||||
let txindex = txindex.unwrap_or_else(|| self.txindex.as_ref().unwrap().vec());
|
||||
|
||||
self.height.compute(
|
||||
starting_indexes.height,
|
||||
txindex,
|
||||
indexer.mut_vecs().height_to_first_txindex.mut_vec(),
|
||||
indexes.height_to_last_txindex.mut_vec(),
|
||||
indexer.vecs().height_to_first_txindex.vec(),
|
||||
indexes.height_to_txindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.dateindex.from_aligned(
|
||||
starting_indexes.dateindex,
|
||||
&mut self.height,
|
||||
indexes.dateindex_to_first_height.mut_vec(),
|
||||
indexes.dateindex_to_last_height.mut_vec(),
|
||||
&self.height,
|
||||
indexes.dateindex_to_first_height.vec(),
|
||||
indexes.dateindex_to_height_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.weekindex.from_aligned(
|
||||
starting_indexes.weekindex,
|
||||
&mut self.dateindex,
|
||||
indexes.weekindex_to_first_dateindex.mut_vec(),
|
||||
indexes.weekindex_to_last_dateindex.mut_vec(),
|
||||
&self.dateindex,
|
||||
indexes.weekindex_to_first_dateindex.vec(),
|
||||
indexes.weekindex_to_dateindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.monthindex.from_aligned(
|
||||
starting_indexes.monthindex,
|
||||
&mut self.dateindex,
|
||||
indexes.monthindex_to_first_dateindex.mut_vec(),
|
||||
indexes.monthindex_to_last_dateindex.mut_vec(),
|
||||
&self.dateindex,
|
||||
indexes.monthindex_to_first_dateindex.vec(),
|
||||
indexes.monthindex_to_dateindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.quarterindex.from_aligned(
|
||||
starting_indexes.quarterindex,
|
||||
&mut self.monthindex,
|
||||
indexes.quarterindex_to_first_monthindex.mut_vec(),
|
||||
indexes.quarterindex_to_last_monthindex.mut_vec(),
|
||||
&self.monthindex,
|
||||
indexes.quarterindex_to_first_monthindex.vec(),
|
||||
indexes.quarterindex_to_monthindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.yearindex.from_aligned(
|
||||
starting_indexes.yearindex,
|
||||
&mut self.monthindex,
|
||||
indexes.yearindex_to_first_monthindex.mut_vec(),
|
||||
indexes.yearindex_to_last_monthindex.mut_vec(),
|
||||
&self.monthindex,
|
||||
indexes.yearindex_to_first_monthindex.vec(),
|
||||
indexes.yearindex_to_monthindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.decadeindex.from_aligned(
|
||||
starting_indexes.decadeindex,
|
||||
&mut self.yearindex,
|
||||
indexes.decadeindex_to_first_yearindex.mut_vec(),
|
||||
indexes.decadeindex_to_last_yearindex.mut_vec(),
|
||||
&self.yearindex,
|
||||
indexes.decadeindex_to_first_yearindex.vec(),
|
||||
indexes.decadeindex_to_yearindex_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.difficultyepoch.from_aligned(
|
||||
starting_indexes.difficultyepoch,
|
||||
&mut self.height,
|
||||
indexes.difficultyepoch_to_first_height.mut_vec(),
|
||||
indexes.difficultyepoch_to_last_height.mut_vec(),
|
||||
&self.height,
|
||||
indexes.difficultyepoch_to_first_height.vec(),
|
||||
indexes.difficultyepoch_to_height_count.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ mod from_dateindex;
|
||||
mod from_height;
|
||||
mod from_height_strict;
|
||||
mod from_txindex;
|
||||
mod stored_type;
|
||||
mod value_from_height;
|
||||
mod value_from_txindex;
|
||||
|
||||
@@ -12,6 +11,5 @@ pub use from_dateindex::*;
|
||||
pub use from_height::*;
|
||||
pub use from_height_strict::*;
|
||||
pub use from_txindex::*;
|
||||
pub use stored_type::*;
|
||||
pub use value_from_height::*;
|
||||
pub use value_from_txindex::*;
|
||||
|
||||
@@ -6,8 +6,7 @@ use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyStoredVec, Compressed, Result, StoredVec, Version};
|
||||
|
||||
use crate::storage::{
|
||||
base::ComputedVec,
|
||||
marketprice,
|
||||
EagerVec, marketprice,
|
||||
vecs::{Indexes, indexes},
|
||||
};
|
||||
|
||||
@@ -65,18 +64,18 @@ impl ComputedValueVecsFromHeight {
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
indexes: &mut indexes::Vecs,
|
||||
marketprices: &mut Option<&mut marketprice::Vecs>,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
marketprices: Option<&marketprice::Vecs>,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> color_eyre::Result<()>
|
||||
where
|
||||
F: FnMut(
|
||||
&mut ComputedVec<Height, Sats>,
|
||||
&mut Indexer,
|
||||
&mut indexes::Vecs,
|
||||
&mut EagerVec<Height, Sats>,
|
||||
&Indexer,
|
||||
&indexes::Vecs,
|
||||
&Indexes,
|
||||
&Exit,
|
||||
) -> Result<()>,
|
||||
@@ -96,14 +95,14 @@ impl ComputedValueVecsFromHeight {
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
indexes: &mut indexes::Vecs,
|
||||
marketprices: &mut Option<&mut marketprice::Vecs>,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
marketprices: Option<&marketprice::Vecs>,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
mut height: Option<&mut StoredVec<Height, Sats>>,
|
||||
height: Option<&StoredVec<Height, Sats>>,
|
||||
) -> color_eyre::Result<()> {
|
||||
if let Some(height) = height.as_mut() {
|
||||
if let Some(height) = height.as_ref() {
|
||||
self.sats
|
||||
.compute_rest(indexes, starting_indexes, exit, Some(height))?;
|
||||
} else {
|
||||
@@ -111,7 +110,7 @@ impl ComputedValueVecsFromHeight {
|
||||
.compute_rest(indexes, starting_indexes, exit, None)?;
|
||||
}
|
||||
|
||||
let height = height.unwrap_or_else(|| self.sats.height.as_mut().unwrap().mut_vec());
|
||||
let height = height.unwrap_or_else(|| self.sats.height.as_ref().unwrap().vec());
|
||||
|
||||
self.bitcoin.compute_all(
|
||||
indexer,
|
||||
@@ -123,13 +122,13 @@ impl ComputedValueVecsFromHeight {
|
||||
},
|
||||
)?;
|
||||
|
||||
let txindex = self.bitcoin.height.as_mut().unwrap().mut_vec();
|
||||
let txindex = self.bitcoin.height.as_ref().unwrap().vec();
|
||||
let price = marketprices
|
||||
.as_mut()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.chainindexes_to_close
|
||||
.height
|
||||
.mut_vec();
|
||||
.vec();
|
||||
|
||||
if let Some(dollars) = self.dollars.as_mut() {
|
||||
dollars.compute_all(
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{Bitcoin, Dollars, Sats, Txindex};
|
||||
use brk_core::{Bitcoin, Dollars, Sats, TxIndex};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyStoredVec, Compressed, Result, StoredVec, Version};
|
||||
|
||||
use crate::storage::{
|
||||
base::ComputedVec,
|
||||
marketprice,
|
||||
EagerVec, marketprice,
|
||||
vecs::{Indexes, indexes},
|
||||
};
|
||||
|
||||
@@ -65,18 +64,18 @@ impl ComputedValueVecsFromTxindex {
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
indexes: &mut indexes::Vecs,
|
||||
marketprices: &mut Option<&mut marketprice::Vecs>,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
marketprices: Option<&marketprice::Vecs>,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> color_eyre::Result<()>
|
||||
where
|
||||
F: FnMut(
|
||||
&mut ComputedVec<Txindex, Sats>,
|
||||
&mut Indexer,
|
||||
&mut indexes::Vecs,
|
||||
&mut EagerVec<TxIndex, Sats>,
|
||||
&Indexer,
|
||||
&indexes::Vecs,
|
||||
&Indexes,
|
||||
&Exit,
|
||||
) -> Result<()>,
|
||||
@@ -96,14 +95,14 @@ impl ComputedValueVecsFromTxindex {
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
indexes: &mut indexes::Vecs,
|
||||
marketprices: &mut Option<&mut marketprice::Vecs>,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
marketprices: Option<&marketprice::Vecs>,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
mut txindex: Option<&mut StoredVec<Txindex, Sats>>,
|
||||
txindex: Option<&StoredVec<TxIndex, Sats>>,
|
||||
) -> color_eyre::Result<()> {
|
||||
if let Some(txindex) = txindex.as_mut() {
|
||||
if let Some(txindex) = txindex.as_ref() {
|
||||
self.sats
|
||||
.compute_rest(indexer, indexes, starting_indexes, exit, Some(txindex))?;
|
||||
} else {
|
||||
@@ -111,7 +110,7 @@ impl ComputedValueVecsFromTxindex {
|
||||
.compute_rest(indexer, indexes, starting_indexes, exit, None)?;
|
||||
}
|
||||
|
||||
let txindex = txindex.unwrap_or_else(|| self.sats.txindex.as_mut().unwrap().mut_vec());
|
||||
let txindex = txindex.unwrap_or_else(|| self.sats.txindex.as_ref().unwrap().vec());
|
||||
|
||||
self.bitcoin.compute_all(
|
||||
indexer,
|
||||
@@ -124,24 +123,20 @@ impl ComputedValueVecsFromTxindex {
|
||||
)?;
|
||||
|
||||
let txindex = self.bitcoin.txindex.as_mut().unwrap().mut_vec();
|
||||
let price = marketprices
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.chainindexes_to_close
|
||||
.height
|
||||
.mut_vec();
|
||||
|
||||
if let Some(dollars) = self.dollars.as_mut() {
|
||||
let price = marketprices.unwrap().chainindexes_to_close.height.vec();
|
||||
|
||||
dollars.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
|v, _, indexes, starting_indexes, exit| {
|
||||
v.compute_from_bitcoin(
|
||||
starting_indexes.txindex,
|
||||
txindex,
|
||||
indexer.mut_vecs().txindex_to_height.mut_vec(),
|
||||
indexes.txindex_to_height.vec(),
|
||||
price,
|
||||
exit,
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,124 @@
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use brk_core::{DifficultyEpoch, HalvingEpoch, StoredF64};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{Compressed, Version};
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
grouped::{ComputedVecsFromDateindex, ComputedVecsFromHeight, StorableVecGeneatorOptions},
|
||||
indexes,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_difficultyepoch: ComputedVecsFromDateindex<DifficultyEpoch>,
|
||||
pub indexes_to_halvingepoch: ComputedVecsFromDateindex<HalvingEpoch>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(path: &Path, compressed: Compressed) -> color_eyre::Result<Self> {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
Ok(Self {
|
||||
indexes_to_difficulty: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"difficulty",
|
||||
false,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_difficultyepoch: ComputedVecsFromDateindex::forced_import(
|
||||
path,
|
||||
"difficultyepoch",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_halvingepoch: ComputedVecsFromDateindex::forced_import(
|
||||
path,
|
||||
"halvingepoch",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
let mut height_to_difficultyepoch_iter = indexes.height_to_difficultyepoch.iter();
|
||||
self.indexes_to_difficultyepoch.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
let mut height_count_iter = indexes.dateindex_to_height_count.iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
indexes.dateindex_to_first_height.vec(),
|
||||
|(di, height, ..)| {
|
||||
(
|
||||
di,
|
||||
height_to_difficultyepoch_iter.unwrap_get_inner(
|
||||
height + (*height_count_iter.unwrap_get_inner(di) - 1),
|
||||
),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut height_to_halvingepoch_iter = indexes.height_to_halvingepoch.iter();
|
||||
self.indexes_to_halvingepoch.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
let mut height_count_iter = indexes.dateindex_to_height_count.iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
indexes.dateindex_to_first_height.vec(),
|
||||
|(di, height, ..)| {
|
||||
(
|
||||
di,
|
||||
height_to_halvingepoch_iter.unwrap_get_inner(
|
||||
height + (*height_count_iter.unwrap_get_inner(di) - 1),
|
||||
),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_difficulty.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(indexer.vecs().height_to_difficulty.vec()),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn as_any_vecs(&self) -> Vec<&dyn brk_vec::AnyStoredVec> {
|
||||
[
|
||||
self.indexes_to_difficulty.any_vecs(),
|
||||
self.indexes_to_difficultyepoch.any_vecs(),
|
||||
self.indexes_to_halvingepoch.any_vecs(),
|
||||
]
|
||||
.concat()
|
||||
}
|
||||
}
|
||||
@@ -5,20 +5,22 @@ use brk_fetcher::Fetcher;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyStoredVec, Compressed};
|
||||
|
||||
pub mod base;
|
||||
pub mod blocks;
|
||||
pub mod grouped;
|
||||
pub mod indexes;
|
||||
pub mod marketprice;
|
||||
pub mod mining;
|
||||
pub mod transactions;
|
||||
pub mod vec;
|
||||
|
||||
use base::*;
|
||||
use indexes::*;
|
||||
pub use indexes::Indexes;
|
||||
pub use vec::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
pub blocks: blocks::Vecs,
|
||||
pub indexes: indexes::Vecs,
|
||||
pub blocks: blocks::Vecs,
|
||||
pub mining: mining::Vecs,
|
||||
pub transactions: transactions::Vecs,
|
||||
pub marketprice: Option<marketprice::Vecs>,
|
||||
}
|
||||
@@ -30,6 +32,7 @@ impl Vecs {
|
||||
Ok(Self {
|
||||
blocks: blocks::Vecs::forced_import(path, compressed)?,
|
||||
indexes: indexes::Vecs::forced_import(path, compressed)?,
|
||||
mining: mining::Vecs::forced_import(path, compressed)?,
|
||||
transactions: transactions::Vecs::forced_import(path, compressed, fetch)?,
|
||||
marketprice: fetch.then(|| marketprice::Vecs::forced_import(path, compressed).unwrap()),
|
||||
})
|
||||
@@ -37,7 +40,7 @@ impl Vecs {
|
||||
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
indexer: &Indexer,
|
||||
starting_indexes: brk_indexer::Indexes,
|
||||
fetcher: Option<&mut Fetcher>,
|
||||
exit: &Exit,
|
||||
@@ -45,12 +48,15 @@ impl Vecs {
|
||||
let starting_indexes = self.indexes.compute(indexer, starting_indexes, exit)?;
|
||||
|
||||
self.blocks
|
||||
.compute(indexer, &mut self.indexes, &starting_indexes, exit)?;
|
||||
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
||||
|
||||
self.mining
|
||||
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
||||
|
||||
if let Some(marketprice) = self.marketprice.as_mut() {
|
||||
marketprice.compute(
|
||||
indexer,
|
||||
&mut self.indexes,
|
||||
&self.indexes,
|
||||
&starting_indexes,
|
||||
fetcher.unwrap(),
|
||||
exit,
|
||||
@@ -59,9 +65,9 @@ impl Vecs {
|
||||
|
||||
self.transactions.compute(
|
||||
indexer,
|
||||
&mut self.indexes,
|
||||
&self.indexes,
|
||||
&starting_indexes,
|
||||
&mut self.marketprice.as_mut(),
|
||||
self.marketprice.as_ref(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -72,6 +78,7 @@ impl Vecs {
|
||||
[
|
||||
self.indexes.as_any_vecs(),
|
||||
self.blocks.as_any_vecs(),
|
||||
self.mining.as_any_vecs(),
|
||||
self.transactions.as_any_vecs(),
|
||||
self.marketprice
|
||||
.as_ref()
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use brk_core::{
|
||||
CheckedSub, Feerate, Sats, StoredU32, StoredU64, StoredUsize, TxVersion, Txindex, Txinindex,
|
||||
Txoutindex, Weight,
|
||||
CheckedSub, Feerate, InputIndex, OutputIndex, Sats, StoredUsize, TxIndex, TxVersion, Weight,
|
||||
};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
@@ -10,7 +9,7 @@ use brk_parser::bitcoin;
|
||||
use brk_vec::{Compressed, DynamicVec, StoredIndex, Version};
|
||||
|
||||
use super::{
|
||||
ComputedVec, Indexes,
|
||||
EagerVec, Indexes,
|
||||
grouped::{
|
||||
ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromHeight,
|
||||
ComputedVecsFromTxindex, StorableVecGeneatorOptions,
|
||||
@@ -20,28 +19,40 @@ use super::{
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
pub indexes_to_tx_count: ComputedVecsFromHeight<StoredU64>,
|
||||
// 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 indexes_to_coinbase: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_emptyoutput_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_fee: ComputedValueVecsFromTxindex,
|
||||
pub indexes_to_feerate: ComputedVecsFromTxindex<Feerate>,
|
||||
/// Value == 0 when Coinbase
|
||||
pub indexes_to_input_value: ComputedVecsFromTxindex<Sats>,
|
||||
pub indexes_to_opreturn_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_output_value: ComputedVecsFromTxindex<Sats>,
|
||||
// pub txindex_to_is_v1: ComputedVec<Txindex, bool>,
|
||||
pub indexes_to_tx_v1: ComputedVecsFromHeight<StoredU32>,
|
||||
// pub txindex_to_is_v2: ComputedVec<Txindex, bool>,
|
||||
pub indexes_to_tx_v2: ComputedVecsFromHeight<StoredU32>,
|
||||
// pub txindex_to_is_v3: ComputedVec<Txindex, bool>,
|
||||
pub indexes_to_tx_v3: ComputedVecsFromHeight<StoredU32>,
|
||||
pub indexes_to_p2a_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_p2ms_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_p2pk33_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_p2pk65_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_p2pkh_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_p2sh_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_p2tr_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_p2wpkh_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_p2wsh_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_subsidy: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_tx_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_tx_v1: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_tx_v2: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_tx_v3: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_tx_vsize: ComputedVecsFromTxindex<StoredUsize>,
|
||||
pub indexes_to_tx_weight: ComputedVecsFromTxindex<Weight>,
|
||||
pub txindex_to_input_count: ComputedVecsFromTxindex<StoredU64>,
|
||||
pub txindex_to_is_coinbase: ComputedVec<Txindex, bool>,
|
||||
pub txindex_to_output_count: ComputedVecsFromTxindex<StoredU64>,
|
||||
pub txindex_to_vsize: ComputedVec<Txindex, StoredUsize>,
|
||||
pub txindex_to_weight: ComputedVec<Txindex, Weight>,
|
||||
/// Value == 0 when Coinbase
|
||||
pub txinindex_to_value: ComputedVec<Txinindex, Sats>,
|
||||
pub indexes_to_subsidy: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_coinbase: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_unknownoutput_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub inputindex_to_value: EagerVec<InputIndex, Sats>,
|
||||
pub indexes_to_input_count: ComputedVecsFromTxindex<StoredUsize>,
|
||||
pub txindex_to_is_coinbase: EagerVec<TxIndex, bool>,
|
||||
pub indexes_to_output_count: ComputedVecsFromTxindex<StoredUsize>,
|
||||
pub txindex_to_vsize: EagerVec<TxIndex, StoredUsize>,
|
||||
pub txindex_to_weight: EagerVec<TxIndex, Weight>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -67,12 +78,12 @@ impl Vecs {
|
||||
.add_total(),
|
||||
)?,
|
||||
// height_to_subsidy: StorableVec::forced_import(&path.join("height_to_subsidy"), Version::ZERO)?,
|
||||
txindex_to_is_coinbase: ComputedVec::forced_import(
|
||||
txindex_to_is_coinbase: EagerVec::forced_import(
|
||||
&path.join("txindex_to_is_coinbase"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_input_count: ComputedVecsFromTxindex::forced_import(
|
||||
indexes_to_input_count: ComputedVecsFromTxindex::forced_import(
|
||||
path,
|
||||
"input_count",
|
||||
true,
|
||||
@@ -85,7 +96,7 @@ impl Vecs {
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
txindex_to_output_count: ComputedVecsFromTxindex::forced_import(
|
||||
indexes_to_output_count: ComputedVecsFromTxindex::forced_import(
|
||||
path,
|
||||
"output_count",
|
||||
true,
|
||||
@@ -98,8 +109,8 @@ impl Vecs {
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
txinindex_to_value: ComputedVec::forced_import(
|
||||
&path.join("txinindex_to_value"),
|
||||
inputindex_to_value: EagerVec::forced_import(
|
||||
&path.join("inputindex_to_value"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
@@ -174,12 +185,12 @@ impl Vecs {
|
||||
.add_minmax()
|
||||
.add_average(),
|
||||
)?,
|
||||
txindex_to_weight: ComputedVec::forced_import(
|
||||
txindex_to_weight: EagerVec::forced_import(
|
||||
&path.join("txindex_to_weight"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_vsize: ComputedVec::forced_import(
|
||||
txindex_to_vsize: EagerVec::forced_import(
|
||||
&path.join("txindex_to_vsize"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
@@ -234,15 +245,171 @@ impl Vecs {
|
||||
.add_average(),
|
||||
compute_dollars,
|
||||
)?,
|
||||
indexes_to_p2a_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"p2a_count",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_average()
|
||||
.add_minmax()
|
||||
.add_percentiles()
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
indexes_to_p2ms_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"p2ms_count",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_average()
|
||||
.add_minmax()
|
||||
.add_percentiles()
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
indexes_to_p2pk33_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"p2pk33_count",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_average()
|
||||
.add_minmax()
|
||||
.add_percentiles()
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
indexes_to_p2pk65_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"p2pk65_count",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_average()
|
||||
.add_minmax()
|
||||
.add_percentiles()
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
indexes_to_p2pkh_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"p2pkh_count",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_average()
|
||||
.add_minmax()
|
||||
.add_percentiles()
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
indexes_to_p2sh_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"p2sh_count",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_average()
|
||||
.add_minmax()
|
||||
.add_percentiles()
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
indexes_to_p2tr_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"p2tr_count",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_average()
|
||||
.add_minmax()
|
||||
.add_percentiles()
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
indexes_to_p2wpkh_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"p2wpkh_count",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_average()
|
||||
.add_minmax()
|
||||
.add_percentiles()
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
indexes_to_p2wsh_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"p2wsh_count",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_average()
|
||||
.add_minmax()
|
||||
.add_percentiles()
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
indexes_to_opreturn_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"opreturn_count",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_average()
|
||||
.add_minmax()
|
||||
.add_percentiles()
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
indexes_to_unknownoutput_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"unknownoutput_count",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_average()
|
||||
.add_minmax()
|
||||
.add_percentiles()
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
indexes_to_emptyoutput_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"emptyoutput_count",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_average()
|
||||
.add_minmax()
|
||||
.add_percentiles()
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
indexes: &mut indexes::Vecs,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
marketprices: &mut Option<&mut marketprice::Vecs>,
|
||||
marketprices: Option<&marketprice::Vecs>,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
self.indexes_to_tx_count.compute_all(
|
||||
@@ -250,63 +417,65 @@ impl Vecs {
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, indexes, starting_indexes, exit| {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.mut_vecs().height_to_first_txindex.mut_vec(),
|
||||
indexes.height_to_last_txindex.mut_vec(),
|
||||
indexer.vecs().height_to_first_txindex.vec(),
|
||||
indexer.vecs().txindex_to_txid.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.txindex_to_input_count.compute_all(
|
||||
self.indexes_to_input_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, indexes, starting_indexes, exit| {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.txindex,
|
||||
indexer.mut_vecs().txindex_to_first_txinindex.mut_vec(),
|
||||
indexes.txindex_to_last_txinindex.mut_vec(),
|
||||
indexer.vecs().txindex_to_first_inputindex.vec(),
|
||||
indexer.vecs().inputindex_to_outputindex.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.txindex_to_output_count.compute_all(
|
||||
self.indexes_to_output_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, indexes, starting_indexes, exit| {
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.txindex,
|
||||
indexer.mut_vecs().txindex_to_first_txoutindex.mut_vec(),
|
||||
indexes.txindex_to_last_txoutindex.mut_vec(),
|
||||
indexer.vecs().txindex_to_first_outputindex.vec(),
|
||||
indexer.vecs().outputindex_to_value.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut compute_indexes_to_tx_vany =
|
||||
|indexes_to_tx_vany: &mut ComputedVecsFromHeight<StoredU32>, txversion| {
|
||||
let compute_indexes_to_tx_vany =
|
||||
|indexes_to_tx_vany: &mut ComputedVecsFromHeight<StoredUsize>, txversion| {
|
||||
let mut txindex_to_txversion_iter = indexer.vecs().txindex_to_txversion.iter();
|
||||
indexes_to_tx_vany.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, indexer, indexes, starting_indexes, exit| {
|
||||
let indexer_vecs = indexer.mut_vecs();
|
||||
|vec, indexer, _, starting_indexes, exit| {
|
||||
vec.compute_filtered_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer_vecs.height_to_first_txindex.mut_vec(),
|
||||
indexes.height_to_last_txindex.mut_vec(),
|
||||
indexer.vecs().height_to_first_txindex.vec(),
|
||||
indexer.vecs().txindex_to_txid.vec(),
|
||||
|txindex| {
|
||||
let v = indexer_vecs
|
||||
.txindex_to_txversion
|
||||
.double_unwrap_cached_get(txindex);
|
||||
let v = txindex_to_txversion_iter
|
||||
.get(txindex)
|
||||
.unwrap()
|
||||
.1
|
||||
.into_inner();
|
||||
v == txversion
|
||||
},
|
||||
exit,
|
||||
@@ -318,26 +487,26 @@ impl Vecs {
|
||||
compute_indexes_to_tx_vany(&mut self.indexes_to_tx_v2, TxVersion::TWO)?;
|
||||
compute_indexes_to_tx_vany(&mut self.indexes_to_tx_v3, TxVersion::THREE)?;
|
||||
|
||||
let indexer_vecs = indexer.mut_vecs();
|
||||
|
||||
self.txindex_to_is_coinbase.compute_is_first_ordered(
|
||||
starting_indexes.txindex,
|
||||
indexer_vecs.txindex_to_height.mut_vec(),
|
||||
indexer_vecs.height_to_first_txindex.mut_vec(),
|
||||
indexes.txindex_to_height.vec(),
|
||||
indexer.vecs().height_to_first_txindex.vec(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
let mut txindex_to_total_size_iter = indexer.vecs().txindex_to_total_size.iter();
|
||||
self.txindex_to_weight.compute_transform(
|
||||
starting_indexes.txindex,
|
||||
indexer_vecs.txindex_to_base_size.mut_vec(),
|
||||
indexer.vecs().txindex_to_base_size.vec(),
|
||||
|(txindex, base_size, ..)| {
|
||||
let total_size = indexer_vecs
|
||||
.txindex_to_total_size
|
||||
.mut_vec()
|
||||
.double_unwrap_cached_get(txindex);
|
||||
let total_size = txindex_to_total_size_iter
|
||||
.get(txindex)
|
||||
.unwrap()
|
||||
.1
|
||||
.into_inner();
|
||||
|
||||
// This is the exact definition of a weight unit, as defined by BIP-141 (quote above).
|
||||
let wu = base_size * 3 + total_size;
|
||||
let wu = usize::from(base_size) * 3 + usize::from(total_size);
|
||||
let weight = Weight::from(bitcoin::Weight::from_wu_usize(wu));
|
||||
|
||||
(txindex, weight)
|
||||
@@ -347,7 +516,7 @@ impl Vecs {
|
||||
|
||||
self.txindex_to_vsize.compute_transform(
|
||||
starting_indexes.txindex,
|
||||
self.txindex_to_weight.mut_vec(),
|
||||
self.txindex_to_weight.vec(),
|
||||
|(txindex, weight, ..)| {
|
||||
let vbytes =
|
||||
StoredUsize::from(bitcoin::Weight::from(weight).to_vbytes_ceil() as usize);
|
||||
@@ -356,23 +525,21 @@ impl Vecs {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.txinindex_to_value.compute_transform(
|
||||
starting_indexes.txinindex,
|
||||
indexer_vecs.txinindex_to_txoutindex.mut_vec(),
|
||||
|(txinindex, txoutindex, slf, other)| {
|
||||
let value = if txoutindex == Txoutindex::COINBASE {
|
||||
let mut outputindex_to_value_iter = indexer.vecs().outputindex_to_value.iter();
|
||||
let inputs_len = indexer.vecs().inputindex_to_outputindex.vec().len();
|
||||
self.inputindex_to_value.compute_transform(
|
||||
starting_indexes.inputindex,
|
||||
indexer.vecs().inputindex_to_outputindex.vec(),
|
||||
|(inputindex, outputindex, ..)| {
|
||||
let value = if outputindex == OutputIndex::COINBASE {
|
||||
Sats::ZERO
|
||||
} else if let Some(value) = indexer_vecs
|
||||
.txoutindex_to_value
|
||||
.mut_vec()
|
||||
.unwrap_cached_get(txoutindex)
|
||||
{
|
||||
value
|
||||
} else if let Some((_, value)) = outputindex_to_value_iter.get(outputindex) {
|
||||
value.into_inner()
|
||||
} else {
|
||||
dbg!(txinindex, txoutindex, slf.len(), other.len());
|
||||
dbg!(inputindex, outputindex, inputs_len);
|
||||
panic!()
|
||||
};
|
||||
(txinindex, value)
|
||||
(inputindex, value)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
@@ -382,13 +549,12 @@ impl Vecs {
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, indexer, indexes, starting_indexes, exit| {
|
||||
let indexer_vecs = indexer.mut_vecs();
|
||||
|vec, indexer, _, starting_indexes, exit| {
|
||||
vec.compute_sum_from_indexes(
|
||||
starting_indexes.txindex,
|
||||
indexer_vecs.txindex_to_first_txoutindex.mut_vec(),
|
||||
indexes.txindex_to_last_txoutindex.mut_vec(),
|
||||
indexer_vecs.txoutindex_to_value.mut_vec(),
|
||||
indexer.vecs().txindex_to_first_outputindex.vec(),
|
||||
self.indexes_to_output_count.txindex.as_ref().unwrap().vec(),
|
||||
indexer.vecs().outputindex_to_value.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -399,13 +565,12 @@ impl Vecs {
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, indexer, indexes, starting_indexes, exit| {
|
||||
let indexer_vecs = indexer.mut_vecs();
|
||||
|vec, indexer, _, starting_indexes, exit| {
|
||||
vec.compute_sum_from_indexes(
|
||||
starting_indexes.txindex,
|
||||
indexer_vecs.txindex_to_first_txinindex.mut_vec(),
|
||||
indexes.txindex_to_last_txinindex.mut_vec(),
|
||||
self.txinindex_to_value.mut_vec(),
|
||||
indexer.vecs().txindex_to_first_inputindex.vec(),
|
||||
self.indexes_to_input_count.txindex.as_ref().unwrap().vec(),
|
||||
self.inputindex_to_value.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -418,25 +583,21 @@ impl Vecs {
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let txindex_to_output_value = self
|
||||
let mut txindex_to_output_value_iter = self
|
||||
.indexes_to_output_value
|
||||
.txindex
|
||||
.as_mut()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.mut_vec();
|
||||
.iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.txindex,
|
||||
self.indexes_to_input_value
|
||||
.txindex
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.mut_vec(),
|
||||
self.indexes_to_input_value.txindex.as_ref().unwrap().vec(),
|
||||
|(txindex, input_value, ..)| {
|
||||
if input_value.is_zero() {
|
||||
(txindex, input_value)
|
||||
} else {
|
||||
let output_value =
|
||||
txindex_to_output_value.double_unwrap_cached_get(txindex);
|
||||
txindex_to_output_value_iter.unwrap_get_inner(txindex);
|
||||
(txindex, input_value.checked_sub(output_value).unwrap())
|
||||
}
|
||||
},
|
||||
@@ -451,15 +612,12 @@ impl Vecs {
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut txindex_to_vsize_iter = self.txindex_to_vsize.iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.txindex,
|
||||
self.indexes_to_fee.sats.txindex.as_mut().unwrap().mut_vec(),
|
||||
self.indexes_to_fee.sats.txindex.as_ref().unwrap().vec(),
|
||||
|(txindex, fee, ..)| {
|
||||
let vsize = self
|
||||
.txindex_to_vsize
|
||||
.mut_vec()
|
||||
.double_unwrap_cached_get(txindex);
|
||||
|
||||
let vsize = txindex_to_vsize_iter.unwrap_get_inner(txindex);
|
||||
(txindex, Feerate::from((fee, vsize)))
|
||||
},
|
||||
exit,
|
||||
@@ -472,7 +630,7 @@ impl Vecs {
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.txindex_to_weight.mut_vec()),
|
||||
Some(self.txindex_to_weight.vec()),
|
||||
)?;
|
||||
|
||||
self.indexes_to_tx_vsize.compute_rest(
|
||||
@@ -480,7 +638,7 @@ impl Vecs {
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.txindex_to_vsize.mut_vec()),
|
||||
Some(self.txindex_to_vsize.vec()),
|
||||
)?;
|
||||
|
||||
self.indexes_to_subsidy.compute_all(
|
||||
@@ -489,27 +647,31 @@ impl Vecs {
|
||||
marketprices,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, indexer, indexes, starting_indexes, exit| {
|
||||
let indexer_vecs = indexer.mut_vecs();
|
||||
|vec, indexer, _, starting_indexes, exit| {
|
||||
let mut txindex_to_first_outputindex_iter =
|
||||
indexer.vecs().txindex_to_first_outputindex.iter();
|
||||
let mut txindex_to_output_count_iter = self
|
||||
.indexes_to_output_count
|
||||
.txindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter();
|
||||
let mut outputindex_to_value_iter = indexer.vecs().outputindex_to_value.iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
indexer_vecs.height_to_first_txindex.mut_vec(),
|
||||
indexer.vecs().height_to_first_txindex.vec(),
|
||||
|(height, txindex, ..)| {
|
||||
let first_txoutindex = indexer_vecs
|
||||
.txindex_to_first_txoutindex
|
||||
.double_unwrap_cached_get(txindex)
|
||||
.unwrap_to_usize();
|
||||
let last_txoutindex = indexes
|
||||
.txindex_to_last_txoutindex
|
||||
.mut_vec()
|
||||
.double_unwrap_cached_get(txindex)
|
||||
let first_outputindex = txindex_to_first_outputindex_iter
|
||||
.unwrap_get_inner(txindex)
|
||||
.unwrap_to_usize();
|
||||
let output_count = txindex_to_output_count_iter.unwrap_get_inner(txindex);
|
||||
let mut sats = Sats::ZERO;
|
||||
(first_txoutindex..=last_txoutindex).for_each(|txoutindex| {
|
||||
sats += indexer_vecs
|
||||
.txoutindex_to_value
|
||||
.double_unwrap_cached_get(Txoutindex::from(txoutindex));
|
||||
});
|
||||
(first_outputindex..first_outputindex + *output_count).for_each(
|
||||
|outputindex| {
|
||||
sats += outputindex_to_value_iter
|
||||
.unwrap_get_inner(OutputIndex::from(outputindex));
|
||||
},
|
||||
);
|
||||
(height, sats)
|
||||
},
|
||||
exit,
|
||||
@@ -524,22 +686,13 @@ impl Vecs {
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut indexes_to_fee_sum_iter =
|
||||
self.indexes_to_fee.sats.height.unwrap_sum().iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
self.indexes_to_subsidy
|
||||
.sats
|
||||
.height
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.mut_vec(),
|
||||
self.indexes_to_subsidy.sats.height.as_ref().unwrap().vec(),
|
||||
|(height, subsidy, ..)| {
|
||||
let fees = self
|
||||
.indexes_to_fee
|
||||
.sats
|
||||
.height
|
||||
.unwrap_sum()
|
||||
.mut_vec()
|
||||
.double_unwrap_cached_get(height);
|
||||
let fees = indexes_to_fee_sum_iter.unwrap_get_inner(height);
|
||||
(height, subsidy.checked_sub(fees).unwrap())
|
||||
},
|
||||
exit,
|
||||
@@ -547,6 +700,175 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_p2a_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.vecs().height_to_first_p2aindex.vec(),
|
||||
indexer.vecs().p2aindex_to_p2abytes.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_p2ms_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.vecs().height_to_first_p2msindex.vec(),
|
||||
indexer.vecs().p2msindex_to_txindex.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_p2pk33_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.vecs().height_to_first_p2pk33index.vec(),
|
||||
indexer.vecs().p2pk33index_to_p2pk33bytes.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_p2pk65_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.vecs().height_to_first_p2pk65index.vec(),
|
||||
indexer.vecs().p2pk65index_to_p2pk65bytes.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_p2pkh_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.vecs().height_to_first_p2pkhindex.vec(),
|
||||
indexer.vecs().p2pkhindex_to_p2pkhbytes.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_p2sh_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.vecs().height_to_first_p2shindex.vec(),
|
||||
indexer.vecs().p2shindex_to_p2shbytes.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_p2tr_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.vecs().height_to_first_p2trindex.vec(),
|
||||
indexer.vecs().p2trindex_to_p2trbytes.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_p2wpkh_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.vecs().height_to_first_p2wpkhindex.vec(),
|
||||
indexer.vecs().p2wpkhindex_to_p2wpkhbytes.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_p2wsh_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.vecs().height_to_first_p2wshindex.vec(),
|
||||
indexer.vecs().p2wshindex_to_p2wshbytes.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_opreturn_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.vecs().height_to_first_opreturnindex.vec(),
|
||||
indexer.vecs().opreturnindex_to_txindex.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_unknownoutput_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.vecs().height_to_first_unknownoutputindex.vec(),
|
||||
indexer.vecs().unknownoutputindex_to_txindex.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_emptyoutput_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_count_from_indexes(
|
||||
starting_indexes.height,
|
||||
indexer.vecs().height_to_first_emptyoutputindex.vec(),
|
||||
indexer.vecs().emptyoutputindex_to_txindex.vec(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -554,7 +876,7 @@ impl Vecs {
|
||||
[
|
||||
vec![
|
||||
self.txindex_to_is_coinbase.any_vec(),
|
||||
self.txinindex_to_value.any_vec(),
|
||||
self.inputindex_to_value.any_vec(),
|
||||
self.txindex_to_weight.any_vec(),
|
||||
self.txindex_to_vsize.any_vec(),
|
||||
],
|
||||
@@ -570,8 +892,20 @@ impl Vecs {
|
||||
self.indexes_to_tx_v3.any_vecs(),
|
||||
self.indexes_to_tx_vsize.any_vecs(),
|
||||
self.indexes_to_tx_weight.any_vecs(),
|
||||
self.txindex_to_input_count.any_vecs(),
|
||||
self.txindex_to_output_count.any_vecs(),
|
||||
self.indexes_to_input_count.any_vecs(),
|
||||
self.indexes_to_output_count.any_vecs(),
|
||||
self.indexes_to_p2a_count.any_vecs(),
|
||||
self.indexes_to_p2ms_count.any_vecs(),
|
||||
self.indexes_to_p2pk33_count.any_vecs(),
|
||||
self.indexes_to_p2pk65_count.any_vecs(),
|
||||
self.indexes_to_p2pkh_count.any_vecs(),
|
||||
self.indexes_to_p2sh_count.any_vecs(),
|
||||
self.indexes_to_p2tr_count.any_vecs(),
|
||||
self.indexes_to_p2wpkh_count.any_vecs(),
|
||||
self.indexes_to_p2wsh_count.any_vecs(),
|
||||
self.indexes_to_opreturn_count.any_vecs(),
|
||||
self.indexes_to_unknownoutput_count.any_vecs(),
|
||||
self.indexes_to_emptyoutput_count.any_vecs(),
|
||||
]
|
||||
.concat()
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@ use brk_vec::StoredType;
|
||||
|
||||
pub trait ComputedType
|
||||
where
|
||||
Self: StoredType + From<usize> + Div<usize, Output = Self> + Add<Output = Self>,
|
||||
Self: StoredType + From<usize> + Div<usize, Output = Self> + Add<Output = Self> + Ord,
|
||||
{
|
||||
}
|
||||
impl<T> ComputedType for T where
|
||||
T: StoredType + From<usize> + Div<usize, Output = Self> + Add<Output = Self>
|
||||
T: StoredType + From<usize> + Div<usize, Output = Self> + Add<Output = Self> + Ord
|
||||
{
|
||||
}
|
||||
+169
-134
@@ -6,11 +6,13 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use brk_core::{Bitcoin, CheckedSub, Close, Dollars, Height, Sats, Txindex};
|
||||
use brk_core::{Bitcoin, CheckedSub, Close, Dollars, Height, Sats, StoredUsize, TxIndex};
|
||||
use brk_exit::Exit;
|
||||
use brk_vec::{
|
||||
Compressed, DynamicVec, Error, GenericVec, Result, StoredIndex, StoredType, StoredVec, Version,
|
||||
Compressed, DynamicVec, Error, GenericVec, Result, StoredIndex, StoredType, StoredVec,
|
||||
StoredVecIterator, Value, Version,
|
||||
};
|
||||
use color_eyre::eyre::ContextCompat;
|
||||
use log::info;
|
||||
|
||||
const ONE_KIB: usize = 1024;
|
||||
@@ -18,7 +20,7 @@ const ONE_MIB: usize = ONE_KIB * ONE_KIB;
|
||||
const MAX_CACHE_SIZE: usize = 210 * ONE_MIB;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ComputedVec<I, T>
|
||||
pub struct EagerVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
@@ -27,7 +29,7 @@ where
|
||||
inner: StoredVec<I, T>,
|
||||
}
|
||||
|
||||
impl<I, T> ComputedVec<I, T>
|
||||
impl<I, T> EagerVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
@@ -107,7 +109,7 @@ where
|
||||
&self.inner
|
||||
}
|
||||
|
||||
pub fn mut_vec(&mut self) -> &mut StoredVec<I, T> {
|
||||
pub fn mut_vec(&mut self) -> &StoredVec<I, T> {
|
||||
&mut self.inner
|
||||
}
|
||||
|
||||
@@ -119,18 +121,6 @@ where
|
||||
&mut self.inner
|
||||
}
|
||||
|
||||
pub fn unwrap_cached_get(&mut self, index: I) -> Option<T> {
|
||||
self.inner.unwrap_cached_get(index)
|
||||
}
|
||||
#[inline]
|
||||
pub fn double_unwrap_cached_get(&mut self, index: I) -> T {
|
||||
self.inner.double_unwrap_cached_get(index)
|
||||
}
|
||||
|
||||
pub fn collect_inclusive_range(&self, from: I, to: I) -> Result<Vec<T>> {
|
||||
self.inner.collect_inclusive_range(from, to)
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &Path {
|
||||
self.inner.path()
|
||||
}
|
||||
@@ -154,25 +144,53 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> StoredVecIterator<I, T> {
|
||||
self.into_iter()
|
||||
}
|
||||
|
||||
pub fn compute_range<A, F>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
other: &StoredVec<I, A>,
|
||||
mut t: F,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
A: StoredType,
|
||||
F: FnMut(I) -> (I, T),
|
||||
{
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.version() + other.version(),
|
||||
)?;
|
||||
|
||||
let index = max_from.min(I::from(self.len()));
|
||||
(index.to_usize()?..other.len()).try_for_each(|i| {
|
||||
let (i, v) = t(I::from(i));
|
||||
self.forced_push_at(i, v, exit)
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
|
||||
pub fn compute_transform<A, B, F>(
|
||||
&mut self,
|
||||
max_from: A,
|
||||
other: &mut StoredVec<A, B>,
|
||||
other: &StoredVec<A, B>,
|
||||
mut t: F,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
A: StoredIndex,
|
||||
B: StoredType,
|
||||
F: FnMut((A, B, &mut Self, &mut dyn DynamicVec<I = A, T = B>)) -> (I, T),
|
||||
F: FnMut((A, B, &Self)) -> (I, T),
|
||||
{
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.version() + other.version(),
|
||||
)?;
|
||||
|
||||
let index = max_from.min(A::from(self.len()));
|
||||
other.iter_from(index, |(a, b, other)| {
|
||||
let (i, v) = t((a, b, self, other));
|
||||
other.iter_at(index).try_for_each(|(a, b)| {
|
||||
let (i, v) = t((a, b.into_inner(), self));
|
||||
self.forced_push_at(i, v, exit)
|
||||
})?;
|
||||
|
||||
@@ -182,7 +200,7 @@ where
|
||||
pub fn compute_inverse_more_to_less(
|
||||
&mut self,
|
||||
max_from: T,
|
||||
other: &mut StoredVec<T, I>,
|
||||
other: &StoredVec<T, I>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
@@ -195,15 +213,25 @@ where
|
||||
|
||||
let index = max_from.min(
|
||||
self.inner
|
||||
.cached_get_last()?
|
||||
.map_or_else(T::default, |v| v.into_inner()),
|
||||
.iter()
|
||||
.last()
|
||||
.map_or_else(T::default, |(_, v)| v.into_inner()),
|
||||
);
|
||||
other.iter_from(index, |(v, i, ..)| {
|
||||
if self.unwrap_cached_get(i).is_none_or(|old_v| old_v > v) {
|
||||
self.forced_push_at(i, v, exit)
|
||||
} else {
|
||||
Ok(())
|
||||
let mut prev_i = None;
|
||||
other.iter_at(index).try_for_each(|(v, i)| -> Result<()> {
|
||||
let i = i.into_inner();
|
||||
if prev_i.is_some_and(|prev_i| prev_i == i) {
|
||||
return Ok(());
|
||||
}
|
||||
if self
|
||||
.inner
|
||||
.get(i)?
|
||||
.is_none_or(|old_v| old_v.into_inner() > v)
|
||||
{
|
||||
self.forced_push_at(i, v, exit)?;
|
||||
}
|
||||
prev_i.replace(i);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
@@ -212,8 +240,8 @@ where
|
||||
pub fn compute_inverse_less_to_more(
|
||||
&mut self,
|
||||
max_from: T,
|
||||
first_indexes: &mut StoredVec<T, I>,
|
||||
last_indexes: &mut StoredVec<T, I>,
|
||||
first_indexes: &StoredVec<T, I>,
|
||||
indexes_count: &StoredVec<T, StoredUsize>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
@@ -221,61 +249,29 @@ where
|
||||
T: StoredIndex,
|
||||
{
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.version() + first_indexes.version() + last_indexes.version(),
|
||||
Version::ZERO + self.version() + first_indexes.version() + indexes_count.version(),
|
||||
)?;
|
||||
|
||||
let mut indexes_count_iter = indexes_count.iter();
|
||||
|
||||
let index = max_from.min(T::from(self.len()));
|
||||
first_indexes.iter_from(index, |(value, first_index, ..)| {
|
||||
let first_index = (first_index).to_usize()?;
|
||||
let last_index = (last_indexes.double_unwrap_cached_get(value)).to_usize()?;
|
||||
(first_index..last_index)
|
||||
.try_for_each(|index| self.forced_push_at(I::from(index), value, exit))
|
||||
})?;
|
||||
first_indexes
|
||||
.iter_at(index)
|
||||
.try_for_each(|(value, first_index)| {
|
||||
let first_index = (first_index).to_usize()?;
|
||||
let count = *indexes_count_iter.unwrap_get_inner(value);
|
||||
(first_index..first_index + count)
|
||||
.try_for_each(|index| self.forced_push_at(I::from(index), value, exit))
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
|
||||
pub fn compute_last_index_from_first(
|
||||
pub fn compute_count_from_indexes<T2, T3>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
first_indexes: &mut StoredVec<I, T>,
|
||||
final_len: usize,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
T: Copy + From<usize> + CheckedSub<T> + StoredIndex,
|
||||
{
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.version() + first_indexes.version(),
|
||||
)?;
|
||||
|
||||
let index = max_from.min(I::from(self.len()));
|
||||
let one = T::from(1);
|
||||
let mut prev_index: Option<I> = None;
|
||||
first_indexes.iter_from(index, |(index, v, ..)| {
|
||||
if let Some(prev_index) = prev_index.take() {
|
||||
let value = v.checked_sub(one).unwrap();
|
||||
self.forced_push_at(prev_index, value, exit)?;
|
||||
}
|
||||
prev_index.replace(index);
|
||||
Ok(())
|
||||
})?;
|
||||
if let Some(prev_index) = prev_index {
|
||||
self.forced_push_at(
|
||||
prev_index,
|
||||
T::from(final_len).checked_sub(one).unwrap(),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
|
||||
pub fn compute_count_from_indexes<T2>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
first_indexes: &mut StoredVec<I, T2>,
|
||||
last_indexes: &mut StoredVec<I, T2>,
|
||||
first_indexes: &StoredVec<I, T2>,
|
||||
other_to_else: &StoredVec<T2, T3>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
@@ -288,16 +284,17 @@ where
|
||||
+ TryInto<T>
|
||||
+ Default,
|
||||
<T2 as TryInto<T>>::Error: error::Error + 'static,
|
||||
T3: StoredType,
|
||||
{
|
||||
let opt: Option<Box<dyn FnMut(T2) -> bool>> = None;
|
||||
self.compute_filtered_count_from_indexes_(max_from, first_indexes, last_indexes, opt, exit)
|
||||
self.compute_filtered_count_from_indexes_(max_from, first_indexes, other_to_else, opt, exit)
|
||||
}
|
||||
|
||||
pub fn compute_filtered_count_from_indexes<T2, F>(
|
||||
pub fn compute_filtered_count_from_indexes<T2, T3, F>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
first_indexes: &mut StoredVec<I, T2>,
|
||||
last_indexes: &mut StoredVec<I, T2>,
|
||||
first_indexes: &StoredVec<I, T2>,
|
||||
other_to_else: &StoredVec<T2, T3>,
|
||||
filter: F,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
@@ -311,22 +308,23 @@ where
|
||||
+ TryInto<T>
|
||||
+ Default,
|
||||
<T2 as TryInto<T>>::Error: error::Error + 'static,
|
||||
T3: StoredType,
|
||||
F: FnMut(T2) -> bool,
|
||||
{
|
||||
self.compute_filtered_count_from_indexes_(
|
||||
max_from,
|
||||
first_indexes,
|
||||
last_indexes,
|
||||
other_to_else,
|
||||
Some(Box::new(filter)),
|
||||
exit,
|
||||
)
|
||||
}
|
||||
|
||||
fn compute_filtered_count_from_indexes_<T2>(
|
||||
fn compute_filtered_count_from_indexes_<T2, T3>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
first_indexes: &mut StoredVec<I, T2>,
|
||||
last_indexes: &mut StoredVec<I, T2>,
|
||||
first_indexes: &StoredVec<I, T2>,
|
||||
other_to_else: &StoredVec<T2, T3>,
|
||||
mut filter: Option<Box<dyn FnMut(T2) -> bool + '_>>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
@@ -339,23 +337,31 @@ where
|
||||
+ CheckedSub<T2>
|
||||
+ TryInto<T>
|
||||
+ Default,
|
||||
T3: StoredType,
|
||||
<T2 as TryInto<T>>::Error: error::Error + 'static,
|
||||
{
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.version() + first_indexes.version() + last_indexes.version(),
|
||||
Version::ZERO + self.version() + first_indexes.version(), // + last_indexes.version(),
|
||||
)?;
|
||||
|
||||
let mut other_iter = first_indexes.iter();
|
||||
let index = max_from.min(I::from(self.len()));
|
||||
first_indexes.iter_from(index, |(i, first_index, ..)| {
|
||||
let last_index = last_indexes.double_unwrap_cached_get(i);
|
||||
let range = first_index.unwrap_to_usize()..=last_index.unwrap_to_usize();
|
||||
let count = if let Some(filter) = filter.as_mut() {
|
||||
range.into_iter().filter(|i| filter(T2::from(*i))).count()
|
||||
} else {
|
||||
range.count()
|
||||
};
|
||||
self.forced_push_at(i, T::from(T2::from(count)), exit)
|
||||
})?;
|
||||
first_indexes
|
||||
.iter_at(index)
|
||||
.try_for_each(|(i, first_index)| {
|
||||
let end = other_iter
|
||||
.get(i + 1)
|
||||
.map(|(_, v)| v.into_inner().unwrap_to_usize())
|
||||
.unwrap_or_else(|| other_to_else.len());
|
||||
|
||||
let range = first_index.unwrap_to_usize()..end;
|
||||
let count = if let Some(filter) = filter.as_mut() {
|
||||
range.into_iter().filter(|i| filter(T2::from(*i))).count()
|
||||
} else {
|
||||
range.count()
|
||||
};
|
||||
self.forced_push_at(i, T::from(T2::from(count)), exit)
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
@@ -363,8 +369,8 @@ where
|
||||
pub fn compute_is_first_ordered<A>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
self_to_other: &mut StoredVec<I, A>,
|
||||
other_to_self: &mut StoredVec<A, I>,
|
||||
self_to_other: &StoredVec<I, A>,
|
||||
other_to_self: &StoredVec<A, I>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
@@ -376,11 +382,19 @@ where
|
||||
Version::ZERO + self.version() + self_to_other.version() + other_to_self.version(),
|
||||
)?;
|
||||
|
||||
let mut other_to_self_iter = other_to_self.iter();
|
||||
let index = max_from.min(I::from(self.len()));
|
||||
self_to_other.iter_from(index, |(i, other, ..)| {
|
||||
self_to_other.iter_at(index).try_for_each(|(i, other)| {
|
||||
self.forced_push_at(
|
||||
i,
|
||||
T::from(other_to_self.double_unwrap_cached_get(other) == i),
|
||||
T::from(
|
||||
other_to_self_iter
|
||||
.get(other.into_inner())
|
||||
.unwrap()
|
||||
.1
|
||||
.into_inner()
|
||||
== i,
|
||||
),
|
||||
exit,
|
||||
)
|
||||
})?;
|
||||
@@ -391,9 +405,9 @@ where
|
||||
pub fn compute_sum_from_indexes<T2>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
first_indexes: &mut StoredVec<I, T2>,
|
||||
last_indexes: &mut StoredVec<I, T2>,
|
||||
source: &mut StoredVec<T2, T>,
|
||||
first_indexes: &StoredVec<I, T2>,
|
||||
indexes_count: &StoredVec<I, StoredUsize>,
|
||||
source: &StoredVec<T2, T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
@@ -401,32 +415,37 @@ where
|
||||
T2: StoredIndex + StoredType,
|
||||
{
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.version() + first_indexes.version() + last_indexes.version(),
|
||||
Version::ZERO + self.version() + first_indexes.version() + indexes_count.version(),
|
||||
)?;
|
||||
|
||||
let mut indexes_count_iter = indexes_count.iter();
|
||||
let mut source_iter = source.iter();
|
||||
let index = max_from.min(I::from(self.len()));
|
||||
first_indexes.iter_from(index, |(i, first_index, ..)| {
|
||||
let last_index = last_indexes.double_unwrap_cached_get(i);
|
||||
let range = first_index.unwrap_to_usize()..=last_index.unwrap_to_usize();
|
||||
let mut sum = T::from(0_usize);
|
||||
range.into_iter().for_each(|i| {
|
||||
sum = sum.clone() + source.double_unwrap_cached_get(T2::from(i));
|
||||
});
|
||||
self.forced_push_at(i, sum, exit)
|
||||
})?;
|
||||
first_indexes
|
||||
.iter_at(index)
|
||||
.try_for_each(|(i, first_index)| {
|
||||
let count = *indexes_count_iter.get(i).unwrap().1.into_inner();
|
||||
let first_index = first_index.unwrap_to_usize();
|
||||
let range = first_index..first_index + count;
|
||||
let mut sum = T::from(0_usize);
|
||||
range.into_iter().for_each(|i| {
|
||||
sum = sum.clone() + source_iter.get(T2::from(i)).unwrap().1.into_inner();
|
||||
});
|
||||
self.forced_push_at(i, sum, exit)
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> ComputedVec<I, Bitcoin>
|
||||
impl<I> EagerVec<I, Bitcoin>
|
||||
where
|
||||
I: StoredIndex,
|
||||
{
|
||||
pub fn compute_from_sats(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
sats: &mut StoredVec<I, Sats>,
|
||||
sats: &StoredVec<I, Sats>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.validate_computed_version_or_reset_file(
|
||||
@@ -434,8 +453,8 @@ where
|
||||
)?;
|
||||
|
||||
let index = max_from.min(I::from(self.len()));
|
||||
sats.iter_from(index, |(i, sats, ..)| {
|
||||
let (i, v) = (i, Bitcoin::from(sats));
|
||||
sats.iter_at(index).try_for_each(|(i, sats)| {
|
||||
let (i, v) = (i, Bitcoin::from(sats.into_inner()));
|
||||
self.forced_push_at(i, v, exit)
|
||||
})?;
|
||||
|
||||
@@ -443,22 +462,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedVec<Height, Dollars> {
|
||||
impl EagerVec<Height, Dollars> {
|
||||
pub fn compute_from_bitcoin(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
bitcoin: &mut StoredVec<Height, Bitcoin>,
|
||||
price: &mut StoredVec<Height, Close<Dollars>>,
|
||||
bitcoin: &StoredVec<Height, Bitcoin>,
|
||||
price: &StoredVec<Height, Close<Dollars>>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.version() + bitcoin.version(),
|
||||
)?;
|
||||
|
||||
let mut price_iter = price.iter();
|
||||
let index = max_from.min(Height::from(self.len()));
|
||||
bitcoin.iter_from(index, |(i, bitcoin, ..)| {
|
||||
let dollars = price.double_unwrap_cached_get(i);
|
||||
let (i, v) = (i, *dollars * bitcoin);
|
||||
bitcoin.iter_at(index).try_for_each(|(i, bitcoin)| {
|
||||
let dollars = price_iter.get(i).unwrap().1.into_inner();
|
||||
let (i, v) = (i, *dollars * bitcoin.into_inner());
|
||||
self.forced_push_at(i, v, exit)
|
||||
})?;
|
||||
|
||||
@@ -466,24 +486,26 @@ impl ComputedVec<Height, Dollars> {
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedVec<Txindex, Dollars> {
|
||||
impl EagerVec<TxIndex, Dollars> {
|
||||
pub fn compute_from_bitcoin(
|
||||
&mut self,
|
||||
max_from: Txindex,
|
||||
bitcoin: &mut StoredVec<Txindex, Bitcoin>,
|
||||
i_to_height: &mut StoredVec<Txindex, Height>,
|
||||
price: &mut StoredVec<Height, Close<Dollars>>,
|
||||
max_from: TxIndex,
|
||||
bitcoin: &StoredVec<TxIndex, Bitcoin>,
|
||||
i_to_height: &StoredVec<TxIndex, Height>,
|
||||
price: &StoredVec<Height, Close<Dollars>>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.version() + bitcoin.version(),
|
||||
)?;
|
||||
|
||||
let index = max_from.min(Txindex::from(self.len()));
|
||||
bitcoin.iter_from(index, |(i, bitcoin, ..)| {
|
||||
let height = i_to_height.double_unwrap_cached_get(i);
|
||||
let dollars = price.double_unwrap_cached_get(height);
|
||||
let (i, v) = (i, *dollars * bitcoin);
|
||||
let mut i_to_height_iter = i_to_height.iter();
|
||||
let mut price_iter = price.iter();
|
||||
let index = max_from.min(TxIndex::from(self.len()));
|
||||
bitcoin.iter_at(index).try_for_each(|(i, bitcoin, ..)| {
|
||||
let height = i_to_height_iter.get(i).unwrap().1.into_inner();
|
||||
let dollars = price_iter.get(height).unwrap().1.into_inner();
|
||||
let (i, v) = (i, *dollars * bitcoin.into_inner());
|
||||
self.forced_push_at(i, v, exit)
|
||||
})?;
|
||||
|
||||
@@ -491,7 +513,7 @@ impl ComputedVec<Txindex, Dollars> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T> Clone for ComputedVec<I, T>
|
||||
impl<I, T> Clone for EagerVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
@@ -503,3 +525,16 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I, T> IntoIterator for &'a EagerVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
{
|
||||
type Item = (I, Value<'a, T>);
|
||||
type IntoIter = StoredVecIterator<'a, I, T>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.inner.into_iter()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use brk_vec::{DynamicVec, GenericVec, StoredIndex, StoredType, StoredVec, Version};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LazyVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
{
|
||||
inner: StoredVec<I, T>,
|
||||
}
|
||||
|
||||
impl<I, T> LazyVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
{
|
||||
const SIZE_OF: usize = size_of::<T>();
|
||||
|
||||
fn version(&self) -> Version {
|
||||
self.inner.version()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.inner.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T> Clone for LazyVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
inner: self.inner.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
mod _type;
|
||||
mod eager;
|
||||
mod lazy;
|
||||
|
||||
pub use _type::*;
|
||||
pub use eager::*;
|
||||
pub use lazy::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum Mode {
|
||||
Lazy,
|
||||
Eager,
|
||||
}
|
||||
@@ -29,7 +29,7 @@
|
||||
<a href="https://bsky.app/profile/bitcoinresearchkit.org">
|
||||
<img src="https://img.shields.io/badge/bluesky-blue?link=https%3A%2F%2Fbsky.app%2Fprofile%2Fbitcoinresearchkit.org" alt="Bluesky" />
|
||||
</a>
|
||||
<a href="https://x.com/0xbrk">
|
||||
<a href="https://x.com/brkdotorg">
|
||||
<img src="https://img.shields.io/badge/x.com-black" alt="X" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
+15
-15
@@ -21,9 +21,9 @@ use crate::Error;
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct Addressindex(u32);
|
||||
pub struct AddressIndex(u32);
|
||||
|
||||
impl Addressindex {
|
||||
impl AddressIndex {
|
||||
pub const BYTES: usize = size_of::<Self>();
|
||||
|
||||
pub fn increment(&mut self) {
|
||||
@@ -35,56 +35,56 @@ impl Addressindex {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Addressindex {
|
||||
impl From<u32> for AddressIndex {
|
||||
fn from(value: u32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for Addressindex {
|
||||
impl From<u64> for AddressIndex {
|
||||
fn from(value: u64) -> Self {
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
impl From<Addressindex> for u64 {
|
||||
fn from(value: Addressindex) -> Self {
|
||||
impl From<AddressIndex> for u64 {
|
||||
fn from(value: AddressIndex) -> Self {
|
||||
value.0 as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Addressindex {
|
||||
impl From<usize> for AddressIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
impl From<Addressindex> for usize {
|
||||
fn from(value: Addressindex) -> Self {
|
||||
impl From<AddressIndex> for usize {
|
||||
fn from(value: AddressIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ByteView> for Addressindex {
|
||||
impl TryFrom<ByteView> for AddressIndex {
|
||||
type Error = Error;
|
||||
fn try_from(value: ByteView) -> Result<Self, Self::Error> {
|
||||
Ok(Self::read_from_bytes(&value)?)
|
||||
}
|
||||
}
|
||||
impl From<Addressindex> for ByteView {
|
||||
fn from(value: Addressindex) -> Self {
|
||||
impl From<AddressIndex> for ByteView {
|
||||
fn from(value: AddressIndex) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Addressindex {
|
||||
impl Add<usize> for AddressIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 + rhs as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Addressindex> for Addressindex {
|
||||
impl Add<AddressIndex> for AddressIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Addressindex) -> Self::Output {
|
||||
fn add(self, rhs: AddressIndex) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use byteview::ByteView;
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::Error;
|
||||
|
||||
use super::{AddressIndex, Outputindex};
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Immutable, IntoBytes, KnownLayout, FromBytes,
|
||||
)]
|
||||
#[repr(C)]
|
||||
pub struct AddressIndexOutputIndex {
|
||||
addressindex: AddressIndex,
|
||||
_padding: u32,
|
||||
outputindex: Outputindex,
|
||||
}
|
||||
|
||||
impl TryFrom<ByteView> for AddressIndexOutputIndex {
|
||||
type Error = Error;
|
||||
fn try_from(value: ByteView) -> Result<Self, Self::Error> {
|
||||
Ok(Self::read_from_bytes(&value)?)
|
||||
}
|
||||
}
|
||||
impl From<AddressIndexOutputIndex> for ByteView {
|
||||
fn from(value: AddressIndexOutputIndex) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
use serde::Serialize;
|
||||
use zerocopy::{Immutable, IntoBytes, KnownLayout, TryFromBytes};
|
||||
|
||||
use super::OutputType;
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
TryFromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
#[repr(u8)]
|
||||
pub enum AddressType {
|
||||
P2PK65,
|
||||
P2PK33,
|
||||
P2PKH,
|
||||
P2SH,
|
||||
P2WPKH,
|
||||
P2WSH,
|
||||
P2TR,
|
||||
P2A,
|
||||
}
|
||||
|
||||
impl From<OutputType> for AddressType {
|
||||
fn from(value: OutputType) -> Self {
|
||||
match value {
|
||||
OutputType::P2A => Self::P2A,
|
||||
OutputType::P2PK33 => Self::P2PK33,
|
||||
OutputType::P2PK65 => Self::P2PK65,
|
||||
OutputType::P2PKH => Self::P2PKH,
|
||||
OutputType::P2SH => Self::P2SH,
|
||||
OutputType::P2TR => Self::P2TR,
|
||||
OutputType::P2WPKH => Self::P2WPKH,
|
||||
OutputType::P2WSH => Self::P2WSH,
|
||||
OutputType::Empty | OutputType::OpReturn | OutputType::P2MS | OutputType::Unknown => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,40 +12,42 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::Error;
|
||||
|
||||
use super::Addresstype;
|
||||
use super::OutputType;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Addressbytes {
|
||||
P2PK65(P2PK65AddressBytes),
|
||||
P2PK33(P2PK33AddressBytes),
|
||||
P2PKH(P2PKHAddressBytes),
|
||||
P2SH(P2SHAddressBytes),
|
||||
P2WPKH(P2WPKHAddressBytes),
|
||||
P2WSH(P2WSHAddressBytes),
|
||||
P2TR(P2TRAddressBytes),
|
||||
pub enum AddressBytes {
|
||||
P2PK65(P2PK65Bytes),
|
||||
P2PK33(P2PK33Bytes),
|
||||
P2PKH(P2PKHBytes),
|
||||
P2SH(P2SHBytes),
|
||||
P2WPKH(P2WPKHBytes),
|
||||
P2WSH(P2WSHBytes),
|
||||
P2TR(P2TRBytes),
|
||||
P2A(P2ABytes),
|
||||
}
|
||||
|
||||
impl Addressbytes {
|
||||
impl AddressBytes {
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
match self {
|
||||
Addressbytes::P2PK65(bytes) => &bytes[..],
|
||||
Addressbytes::P2PK33(bytes) => &bytes[..],
|
||||
Addressbytes::P2PKH(bytes) => &bytes[..],
|
||||
Addressbytes::P2SH(bytes) => &bytes[..],
|
||||
Addressbytes::P2WPKH(bytes) => &bytes[..],
|
||||
Addressbytes::P2WSH(bytes) => &bytes[..],
|
||||
Addressbytes::P2TR(bytes) => &bytes[..],
|
||||
AddressBytes::P2PK65(bytes) => &bytes[..],
|
||||
AddressBytes::P2PK33(bytes) => &bytes[..],
|
||||
AddressBytes::P2PKH(bytes) => &bytes[..],
|
||||
AddressBytes::P2SH(bytes) => &bytes[..],
|
||||
AddressBytes::P2WPKH(bytes) => &bytes[..],
|
||||
AddressBytes::P2WSH(bytes) => &bytes[..],
|
||||
AddressBytes::P2TR(bytes) => &bytes[..],
|
||||
AddressBytes::P2A(bytes) => &bytes[..],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<(&ScriptBuf, Addresstype)> for Addressbytes {
|
||||
impl TryFrom<(&ScriptBuf, OutputType)> for AddressBytes {
|
||||
type Error = Error;
|
||||
fn try_from(tuple: (&ScriptBuf, Addresstype)) -> Result<Self, Self::Error> {
|
||||
let (script, addresstype) = tuple;
|
||||
fn try_from(tuple: (&ScriptBuf, OutputType)) -> Result<Self, Self::Error> {
|
||||
let (script, outputtype) = tuple;
|
||||
|
||||
match addresstype {
|
||||
Addresstype::P2PK65 => {
|
||||
match outputtype {
|
||||
OutputType::P2PK65 => {
|
||||
let bytes = script.as_bytes();
|
||||
let bytes = match bytes.len() {
|
||||
67 => &bytes[1..66],
|
||||
@@ -54,9 +56,9 @@ impl TryFrom<(&ScriptBuf, Addresstype)> for Addressbytes {
|
||||
return Err(Error::WrongLength);
|
||||
}
|
||||
};
|
||||
Ok(Self::P2PK65(P2PK65AddressBytes(U8x65::from(bytes))))
|
||||
Ok(Self::P2PK65(P2PK65Bytes(U8x65::from(bytes))))
|
||||
}
|
||||
Addresstype::P2PK33 => {
|
||||
OutputType::P2PK33 => {
|
||||
let bytes = script.as_bytes();
|
||||
let bytes = match bytes.len() {
|
||||
35 => &bytes[1..34],
|
||||
@@ -65,47 +67,50 @@ impl TryFrom<(&ScriptBuf, Addresstype)> for Addressbytes {
|
||||
return Err(Error::WrongLength);
|
||||
}
|
||||
};
|
||||
Ok(Self::P2PK33(P2PK33AddressBytes(U8x33::from(bytes))))
|
||||
Ok(Self::P2PK33(P2PK33Bytes(U8x33::from(bytes))))
|
||||
}
|
||||
Addresstype::P2PKH => {
|
||||
OutputType::P2PKH => {
|
||||
let bytes = &script.as_bytes()[3..23];
|
||||
Ok(Self::P2PKH(P2PKHAddressBytes(U8x20::from(bytes))))
|
||||
Ok(Self::P2PKH(P2PKHBytes(U8x20::from(bytes))))
|
||||
}
|
||||
Addresstype::P2SH => {
|
||||
OutputType::P2SH => {
|
||||
let bytes = &script.as_bytes()[2..22];
|
||||
Ok(Self::P2SH(P2SHAddressBytes(U8x20::from(bytes))))
|
||||
Ok(Self::P2SH(P2SHBytes(U8x20::from(bytes))))
|
||||
}
|
||||
Addresstype::P2WPKH => {
|
||||
OutputType::P2WPKH => {
|
||||
let bytes = &script.as_bytes()[2..];
|
||||
Ok(Self::P2WPKH(P2WPKHAddressBytes(U8x20::from(bytes))))
|
||||
Ok(Self::P2WPKH(P2WPKHBytes(U8x20::from(bytes))))
|
||||
}
|
||||
Addresstype::P2WSH => {
|
||||
OutputType::P2WSH => {
|
||||
let bytes = &script.as_bytes()[2..];
|
||||
Ok(Self::P2WSH(P2WSHAddressBytes(U8x32::from(bytes))))
|
||||
Ok(Self::P2WSH(P2WSHBytes(U8x32::from(bytes))))
|
||||
}
|
||||
Addresstype::P2TR => {
|
||||
OutputType::P2TR => {
|
||||
let bytes = &script.as_bytes()[2..];
|
||||
Ok(Self::P2TR(P2TRAddressBytes(U8x32::from(bytes))))
|
||||
Ok(Self::P2TR(P2TRBytes(U8x32::from(bytes))))
|
||||
}
|
||||
Addresstype::Multisig => Err(Error::WrongAddressType),
|
||||
Addresstype::PushOnly => Err(Error::WrongAddressType),
|
||||
Addresstype::Unknown => Err(Error::WrongAddressType),
|
||||
Addresstype::Empty => Err(Error::WrongAddressType),
|
||||
Addresstype::OpReturn => Err(Error::WrongAddressType),
|
||||
OutputType::P2A => {
|
||||
let bytes = &script.as_bytes()[2..];
|
||||
Ok(Self::P2A(P2ABytes(U8x2::from(bytes))))
|
||||
}
|
||||
OutputType::P2MS => Err(Error::WrongAddressType),
|
||||
OutputType::Unknown => Err(Error::WrongAddressType),
|
||||
OutputType::Empty => Err(Error::WrongAddressType),
|
||||
OutputType::OpReturn => Err(Error::WrongAddressType),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
|
||||
pub struct P2PK65AddressBytes(U8x65);
|
||||
pub struct P2PK65Bytes(U8x65);
|
||||
|
||||
impl fmt::Display for P2PK65AddressBytes {
|
||||
impl fmt::Display for P2PK65Bytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.to_hex_string(Case::Lower))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for P2PK65AddressBytes {
|
||||
impl Serialize for P2PK65Bytes {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -114,22 +119,22 @@ impl Serialize for P2PK65AddressBytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PK65AddressBytes> for Addressbytes {
|
||||
fn from(value: P2PK65AddressBytes) -> Self {
|
||||
impl From<P2PK65Bytes> for AddressBytes {
|
||||
fn from(value: P2PK65Bytes) -> Self {
|
||||
Self::P2PK65(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
|
||||
pub struct P2PK33AddressBytes(U8x33);
|
||||
pub struct P2PK33Bytes(U8x33);
|
||||
|
||||
impl fmt::Display for P2PK33AddressBytes {
|
||||
impl fmt::Display for P2PK33Bytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.to_hex_string(Case::Lower))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for P2PK33AddressBytes {
|
||||
impl Serialize for P2PK33Bytes {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -138,16 +143,16 @@ impl Serialize for P2PK33AddressBytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PK33AddressBytes> for Addressbytes {
|
||||
fn from(value: P2PK33AddressBytes) -> Self {
|
||||
impl From<P2PK33Bytes> for AddressBytes {
|
||||
fn from(value: P2PK33Bytes) -> Self {
|
||||
Self::P2PK33(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
|
||||
pub struct P2PKHAddressBytes(U8x20);
|
||||
pub struct P2PKHBytes(U8x20);
|
||||
|
||||
impl fmt::Display for P2PKHAddressBytes {
|
||||
impl fmt::Display for P2PKHBytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let script = Builder::new()
|
||||
.push_opcode(opcodes::all::OP_DUP)
|
||||
@@ -161,7 +166,7 @@ impl fmt::Display for P2PKHAddressBytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for P2PKHAddressBytes {
|
||||
impl Serialize for P2PKHBytes {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -170,16 +175,16 @@ impl Serialize for P2PKHAddressBytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PKHAddressBytes> for Addressbytes {
|
||||
fn from(value: P2PKHAddressBytes) -> Self {
|
||||
impl From<P2PKHBytes> for AddressBytes {
|
||||
fn from(value: P2PKHBytes) -> Self {
|
||||
Self::P2PKH(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
|
||||
pub struct P2SHAddressBytes(U8x20);
|
||||
pub struct P2SHBytes(U8x20);
|
||||
|
||||
impl fmt::Display for P2SHAddressBytes {
|
||||
impl fmt::Display for P2SHBytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let script = Builder::new()
|
||||
.push_opcode(opcodes::all::OP_HASH160)
|
||||
@@ -191,7 +196,7 @@ impl fmt::Display for P2SHAddressBytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for P2SHAddressBytes {
|
||||
impl Serialize for P2SHBytes {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -200,16 +205,16 @@ impl Serialize for P2SHAddressBytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2SHAddressBytes> for Addressbytes {
|
||||
fn from(value: P2SHAddressBytes) -> Self {
|
||||
impl From<P2SHBytes> for AddressBytes {
|
||||
fn from(value: P2SHBytes) -> Self {
|
||||
Self::P2SH(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
|
||||
pub struct P2WPKHAddressBytes(U8x20);
|
||||
pub struct P2WPKHBytes(U8x20);
|
||||
|
||||
impl fmt::Display for P2WPKHAddressBytes {
|
||||
impl fmt::Display for P2WPKHBytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let script = Builder::new().push_int(0).push_slice(*self.0).into_script();
|
||||
let address = Address::from_script(&script, Network::Bitcoin).unwrap();
|
||||
@@ -217,7 +222,7 @@ impl fmt::Display for P2WPKHAddressBytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for P2WPKHAddressBytes {
|
||||
impl Serialize for P2WPKHBytes {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -226,16 +231,16 @@ impl Serialize for P2WPKHAddressBytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2WPKHAddressBytes> for Addressbytes {
|
||||
fn from(value: P2WPKHAddressBytes) -> Self {
|
||||
impl From<P2WPKHBytes> for AddressBytes {
|
||||
fn from(value: P2WPKHBytes) -> Self {
|
||||
Self::P2WPKH(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
|
||||
pub struct P2WSHAddressBytes(U8x32);
|
||||
pub struct P2WSHBytes(U8x32);
|
||||
|
||||
impl fmt::Display for P2WSHAddressBytes {
|
||||
impl fmt::Display for P2WSHBytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let script = Builder::new().push_int(0).push_slice(*self.0).into_script();
|
||||
let address = Address::from_script(&script, Network::Bitcoin).unwrap();
|
||||
@@ -243,7 +248,7 @@ impl fmt::Display for P2WSHAddressBytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for P2WSHAddressBytes {
|
||||
impl Serialize for P2WSHBytes {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -252,16 +257,16 @@ impl Serialize for P2WSHAddressBytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2WSHAddressBytes> for Addressbytes {
|
||||
fn from(value: P2WSHAddressBytes) -> Self {
|
||||
impl From<P2WSHBytes> for AddressBytes {
|
||||
fn from(value: P2WSHBytes) -> Self {
|
||||
Self::P2WSH(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
|
||||
pub struct P2TRAddressBytes(U8x32);
|
||||
pub struct P2TRBytes(U8x32);
|
||||
|
||||
impl fmt::Display for P2TRAddressBytes {
|
||||
impl fmt::Display for P2TRBytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let script = Builder::new().push_int(1).push_slice(*self.0).into_script();
|
||||
let address = Address::from_script(&script, Network::Bitcoin).unwrap();
|
||||
@@ -269,7 +274,7 @@ impl fmt::Display for P2TRAddressBytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for P2TRAddressBytes {
|
||||
impl Serialize for P2TRBytes {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -278,12 +283,60 @@ impl Serialize for P2TRAddressBytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2TRAddressBytes> for Addressbytes {
|
||||
fn from(value: P2TRAddressBytes) -> Self {
|
||||
impl From<P2TRBytes> for AddressBytes {
|
||||
fn from(value: P2TRBytes) -> Self {
|
||||
Self::P2TR(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
|
||||
pub struct P2ABytes(U8x2);
|
||||
|
||||
impl fmt::Display for P2ABytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let script = Builder::new().push_int(1).push_slice(*self.0).into_script();
|
||||
let address = Address::from_script(&script, Network::Bitcoin).unwrap();
|
||||
write!(f, "{}", address)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for P2ABytes {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.collect_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2ABytes> for AddressBytes {
|
||||
fn from(value: P2ABytes) -> Self {
|
||||
Self::P2A(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Deref,
|
||||
DerefMut,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
FromBytes,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct U8x2([u8; 2]);
|
||||
impl From<&[u8]> for U8x2 {
|
||||
fn from(slice: &[u8]) -> Self {
|
||||
let mut arr = [0; 2];
|
||||
arr.copy_from_slice(slice);
|
||||
Self(arr)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
use std::hash::Hasher;
|
||||
|
||||
use byteview::ByteView;
|
||||
use derive_deref::Deref;
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::Error;
|
||||
|
||||
use super::{AddressBytes, OutputType};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct AddressBytesHash([u8; 8]);
|
||||
|
||||
impl From<(&AddressBytes, OutputType)> for AddressBytesHash {
|
||||
fn from((address_bytes, outputtype): (&AddressBytes, OutputType)) -> Self {
|
||||
let mut hasher = rapidhash::RapidHasher::default();
|
||||
hasher.write(address_bytes.as_slice());
|
||||
let mut slice = hasher.finish().to_le_bytes();
|
||||
slice[0] = slice[0].wrapping_add(outputtype as u8);
|
||||
Self(slice)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 8]> for AddressBytesHash {
|
||||
fn from(value: [u8; 8]) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ByteView> for AddressBytesHash {
|
||||
type Error = Error;
|
||||
fn try_from(value: ByteView) -> Result<Self, Self::Error> {
|
||||
Ok(Self::read_from_bytes(&value)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&AddressBytesHash> for ByteView {
|
||||
fn from(value: &AddressBytesHash) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AddressBytesHash> for ByteView {
|
||||
fn from(value: AddressBytesHash) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
use byteview::ByteView;
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::Error;
|
||||
|
||||
use super::{Addressindex, Txoutindex};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Immutable, IntoBytes, KnownLayout, FromBytes)]
|
||||
#[repr(C)]
|
||||
pub struct AddressindexTxoutindex {
|
||||
addressindex: Addressindex,
|
||||
_padding: u32,
|
||||
txoutindex: Txoutindex,
|
||||
}
|
||||
|
||||
impl TryFrom<ByteView> for AddressindexTxoutindex {
|
||||
type Error = Error;
|
||||
fn try_from(value: ByteView) -> Result<Self, Self::Error> {
|
||||
Ok(Self::read_from_bytes(&value)?)
|
||||
}
|
||||
}
|
||||
impl From<AddressindexTxoutindex> for ByteView {
|
||||
fn from(value: AddressindexTxoutindex) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
@@ -1,560 +0,0 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct Addresstypeindex(u32);
|
||||
|
||||
impl Addresstypeindex {
|
||||
pub fn increment(&mut self) {
|
||||
self.0 += 1;
|
||||
}
|
||||
|
||||
pub fn incremented(self) -> Self {
|
||||
Self(self.0 + 1)
|
||||
}
|
||||
|
||||
pub fn copy_then_increment(&mut self) -> Self {
|
||||
let i = *self;
|
||||
self.increment();
|
||||
i
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Addresstypeindex {
|
||||
fn from(value: u32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for Addresstypeindex {
|
||||
fn from(value: u64) -> Self {
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
impl From<Addresstypeindex> for u64 {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
value.0 as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Addresstypeindex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
impl From<Addresstypeindex> for usize {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Addresstypeindex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 + rhs as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Addresstypeindex> for Addresstypeindex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Addresstypeindex) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct Emptyindex(Addresstypeindex);
|
||||
impl From<Addresstypeindex> for Emptyindex {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<Emptyindex> for usize {
|
||||
fn from(value: Emptyindex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for Emptyindex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(Addresstypeindex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for Emptyindex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct Multisigindex(Addresstypeindex);
|
||||
impl From<Addresstypeindex> for Multisigindex {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<Multisigindex> for usize {
|
||||
fn from(value: Multisigindex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for Multisigindex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(Addresstypeindex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for Multisigindex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct Opreturnindex(Addresstypeindex);
|
||||
impl From<Addresstypeindex> for Opreturnindex {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<Opreturnindex> for usize {
|
||||
fn from(value: Opreturnindex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for Opreturnindex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(Addresstypeindex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for Opreturnindex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct Pushonlyindex(Addresstypeindex);
|
||||
impl From<Addresstypeindex> for Pushonlyindex {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<Pushonlyindex> for usize {
|
||||
fn from(value: Pushonlyindex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for Pushonlyindex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(Addresstypeindex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for Pushonlyindex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct Unknownindex(Addresstypeindex);
|
||||
impl From<Addresstypeindex> for Unknownindex {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<Unknownindex> for usize {
|
||||
fn from(value: Unknownindex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for Unknownindex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(Addresstypeindex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for Unknownindex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2PK33index(Addresstypeindex);
|
||||
impl From<Addresstypeindex> for P2PK33index {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2PK33index> for usize {
|
||||
fn from(value: P2PK33index) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2PK33index {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(Addresstypeindex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2PK33index {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2PK65index(Addresstypeindex);
|
||||
impl From<Addresstypeindex> for P2PK65index {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2PK65index> for usize {
|
||||
fn from(value: P2PK65index) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2PK65index {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(Addresstypeindex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2PK65index {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2PKHindex(Addresstypeindex);
|
||||
impl From<Addresstypeindex> for P2PKHindex {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2PKHindex> for usize {
|
||||
fn from(value: P2PKHindex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2PKHindex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(Addresstypeindex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2PKHindex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2SHindex(Addresstypeindex);
|
||||
impl From<Addresstypeindex> for P2SHindex {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2SHindex> for usize {
|
||||
fn from(value: P2SHindex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2SHindex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(Addresstypeindex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2SHindex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2TRindex(Addresstypeindex);
|
||||
impl From<Addresstypeindex> for P2TRindex {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2TRindex> for usize {
|
||||
fn from(value: P2TRindex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2TRindex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(Addresstypeindex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2TRindex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2WPKHindex(Addresstypeindex);
|
||||
impl From<Addresstypeindex> for P2WPKHindex {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2WPKHindex> for usize {
|
||||
fn from(value: P2WPKHindex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2WPKHindex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(Addresstypeindex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2WPKHindex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2WSHindex(Addresstypeindex);
|
||||
impl From<Addresstypeindex> for P2WSHindex {
|
||||
fn from(value: Addresstypeindex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2WSHindex> for usize {
|
||||
fn from(value: P2WSHindex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2WSHindex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(Addresstypeindex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2WSHindex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
@@ -23,27 +23,27 @@ pub struct Bitcoin(f64);
|
||||
impl Add for Bitcoin {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
Self::from(Sats::from(self) + Sats::from(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Bitcoin {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 * rhs.0)
|
||||
Self::from(Sats::from(self) * Sats::from(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<usize> for Bitcoin {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 / rhs as f64)
|
||||
Self::from(Sats::from(self) / rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Sats> for Bitcoin {
|
||||
fn from(value: Sats) -> Self {
|
||||
Self(u64::from(value) as f64 / (u64::from(Sats::ONE_BTC) as f64))
|
||||
Self(f64::from(value) / (f64::from(Sats::ONE_BTC)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
use byteview::ByteView;
|
||||
use derive_deref::Deref;
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{Error, copy_first_8bytes};
|
||||
|
||||
use super::BlockHash;
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct BlockHashPrefix([u8; 8]);
|
||||
|
||||
impl From<BlockHash> for BlockHashPrefix {
|
||||
fn from(value: BlockHash) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&BlockHash> for BlockHashPrefix {
|
||||
fn from(value: &BlockHash) -> Self {
|
||||
Self(copy_first_8bytes(&value[..]).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ByteView> for BlockHashPrefix {
|
||||
type Error = Error;
|
||||
fn try_from(value: ByteView) -> Result<Self, Self::Error> {
|
||||
Ok(Self::read_from_bytes(&value)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&BlockHashPrefix> for ByteView {
|
||||
fn from(value: &BlockHashPrefix) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BlockHashPrefix> for ByteView {
|
||||
fn from(value: BlockHashPrefix) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::ops::{Add, Div};
|
||||
|
||||
use serde::Serialize;
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
@@ -43,3 +45,17 @@ impl From<Cents> for u64 {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Cents {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<usize> for Cents {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 / rhs as u64)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
use std::hash::Hasher;
|
||||
|
||||
use byteview::ByteView;
|
||||
use derive_deref::Deref;
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::Error;
|
||||
|
||||
use super::{Addressbytes, Addresstype, BlockHash, Txid};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct AddressHash([u8; 8]);
|
||||
impl From<(&Addressbytes, Addresstype)> for AddressHash {
|
||||
fn from((addressbytes, addresstype): (&Addressbytes, Addresstype)) -> Self {
|
||||
let mut hasher = rapidhash::RapidHasher::default();
|
||||
hasher.write(addressbytes.as_slice());
|
||||
let mut slice = hasher.finish().to_le_bytes();
|
||||
slice[0] = slice[0].wrapping_add(addresstype as u8);
|
||||
Self(slice)
|
||||
}
|
||||
}
|
||||
impl From<[u8; 8]> for AddressHash {
|
||||
fn from(value: [u8; 8]) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl TryFrom<ByteView> for AddressHash {
|
||||
type Error = Error;
|
||||
fn try_from(value: ByteView) -> Result<Self, Self::Error> {
|
||||
Ok(Self::read_from_bytes(&value)?)
|
||||
}
|
||||
}
|
||||
impl From<&AddressHash> for ByteView {
|
||||
fn from(value: &AddressHash) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
impl From<AddressHash> for ByteView {
|
||||
fn from(value: AddressHash) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct BlockHashPrefix([u8; 8]);
|
||||
impl From<BlockHash> for BlockHashPrefix {
|
||||
fn from(value: BlockHash) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
impl From<&BlockHash> for BlockHashPrefix {
|
||||
fn from(value: &BlockHash) -> Self {
|
||||
Self(copy_first_8bytes(&value[..]).unwrap())
|
||||
}
|
||||
}
|
||||
impl TryFrom<ByteView> for BlockHashPrefix {
|
||||
type Error = Error;
|
||||
fn try_from(value: ByteView) -> Result<Self, Self::Error> {
|
||||
Ok(Self::read_from_bytes(&value)?)
|
||||
}
|
||||
}
|
||||
impl From<&BlockHashPrefix> for ByteView {
|
||||
fn from(value: &BlockHashPrefix) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
impl From<BlockHashPrefix> for ByteView {
|
||||
fn from(value: BlockHashPrefix) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct TxidPrefix([u8; 8]);
|
||||
impl From<Txid> for TxidPrefix {
|
||||
fn from(value: Txid) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
impl From<&Txid> for TxidPrefix {
|
||||
fn from(value: &Txid) -> Self {
|
||||
Self(copy_first_8bytes(&value[..]).unwrap())
|
||||
}
|
||||
}
|
||||
impl TryFrom<ByteView> for TxidPrefix {
|
||||
type Error = Error;
|
||||
fn try_from(value: ByteView) -> Result<Self, Self::Error> {
|
||||
Ok(Self::read_from_bytes(&value)?)
|
||||
}
|
||||
}
|
||||
impl From<&TxidPrefix> for ByteView {
|
||||
fn from(value: &TxidPrefix) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
impl From<TxidPrefix> for ByteView {
|
||||
fn from(value: TxidPrefix) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
impl From<[u8; 8]> for TxidPrefix {
|
||||
fn from(value: [u8; 8]) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_first_8bytes(slice: &[u8]) -> Result<[u8; 8], ()> {
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
let buf_len = buf.len();
|
||||
if slice.len() < buf_len {
|
||||
return Err(());
|
||||
}
|
||||
slice.iter().take(buf_len).enumerate().for_each(|(i, r)| {
|
||||
buf[i] = *r;
|
||||
});
|
||||
Ok(buf)
|
||||
}
|
||||
@@ -2,7 +2,7 @@ use jiff::{Span, civil::Date as Date_, tz::TimeZone};
|
||||
use serde::{Serialize, Serializer};
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use super::{Dateindex, Timestamp};
|
||||
use super::{DateIndex, Timestamp};
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, FromBytes, Immutable, IntoBytes, KnownLayout,
|
||||
@@ -58,9 +58,9 @@ impl From<Timestamp> for Date {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dateindex> for Date {
|
||||
fn from(value: Dateindex) -> Self {
|
||||
if value == Dateindex::default() {
|
||||
impl From<DateIndex> for Date {
|
||||
fn from(value: DateIndex) -> Self {
|
||||
if value == DateIndex::default() {
|
||||
Date::INDEX_ZERO
|
||||
} else {
|
||||
Self::from(
|
||||
|
||||
@@ -23,38 +23,38 @@ use super::Date;
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct Dateindex(u16);
|
||||
pub struct DateIndex(u16);
|
||||
|
||||
impl Dateindex {
|
||||
impl DateIndex {
|
||||
pub const BYTES: usize = size_of::<Self>();
|
||||
}
|
||||
|
||||
impl From<Dateindex> for usize {
|
||||
fn from(value: Dateindex) -> Self {
|
||||
impl From<DateIndex> for usize {
|
||||
fn from(value: DateIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Dateindex {
|
||||
impl From<usize> for DateIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dateindex> for i64 {
|
||||
fn from(value: Dateindex) -> Self {
|
||||
impl From<DateIndex> for i64 {
|
||||
fn from(value: DateIndex) -> Self {
|
||||
value.0 as i64
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Dateindex {
|
||||
impl Add<usize> for DateIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 + rhs as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Date> for Dateindex {
|
||||
impl TryFrom<Date> for DateIndex {
|
||||
type Error = Error;
|
||||
fn try_from(value: Date) -> Result<Self, Self::Error> {
|
||||
let value_ = jiff::civil::Date::from(value);
|
||||
@@ -72,7 +72,7 @@ impl TryFrom<Date> for Dateindex {
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub for Dateindex {
|
||||
impl CheckedSub for DateIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
use super::{Date, Dateindex, Yearindex};
|
||||
use super::{Date, DateIndex, YearIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
@@ -23,27 +23,27 @@ use super::{Date, Dateindex, Yearindex};
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct Decadeindex(u8);
|
||||
pub struct DecadeIndex(u8);
|
||||
|
||||
impl From<u8> for Decadeindex {
|
||||
impl From<u8> for DecadeIndex {
|
||||
fn from(value: u8) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Decadeindex {
|
||||
impl From<usize> for DecadeIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u8)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Decadeindex> for usize {
|
||||
fn from(value: Decadeindex) -> Self {
|
||||
impl From<DecadeIndex> for usize {
|
||||
fn from(value: DecadeIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Decadeindex {
|
||||
impl Add<usize> for DecadeIndex {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
@@ -51,13 +51,13 @@ impl Add<usize> for Decadeindex {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dateindex> for Decadeindex {
|
||||
fn from(value: Dateindex) -> Self {
|
||||
impl From<DateIndex> for DecadeIndex {
|
||||
fn from(value: DateIndex) -> Self {
|
||||
Self::from(Date::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Date> for Decadeindex {
|
||||
impl From<Date> for DecadeIndex {
|
||||
fn from(value: Date) -> Self {
|
||||
let year = value.year();
|
||||
if year < 2000 {
|
||||
@@ -67,14 +67,14 @@ impl From<Date> for Decadeindex {
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub for Decadeindex {
|
||||
impl CheckedSub for DecadeIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Yearindex> for Decadeindex {
|
||||
fn from(value: Yearindex) -> Self {
|
||||
impl From<YearIndex> for DecadeIndex {
|
||||
fn from(value: YearIndex) -> Self {
|
||||
let v = usize::from(value);
|
||||
if v == 0 {
|
||||
Self(0)
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use std::{fmt::Debug, ops::Add};
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
ops::{Add, Div},
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
@@ -23,27 +26,35 @@ use super::Height;
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct Difficultyepoch(u16);
|
||||
pub struct DifficultyEpoch(u16);
|
||||
|
||||
impl From<u16> for Difficultyepoch {
|
||||
impl From<u16> for DifficultyEpoch {
|
||||
fn from(value: u16) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Difficultyepoch {
|
||||
impl From<usize> for DifficultyEpoch {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Difficultyepoch> for usize {
|
||||
fn from(value: Difficultyepoch) -> Self {
|
||||
impl From<DifficultyEpoch> for usize {
|
||||
fn from(value: DifficultyEpoch) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Difficultyepoch {
|
||||
impl Add for DifficultyEpoch {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self::from(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for DifficultyEpoch {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
@@ -51,13 +62,20 @@ impl Add<usize> for Difficultyepoch {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Height> for Difficultyepoch {
|
||||
impl Div<usize> for DifficultyEpoch {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
Self::from(self.0 as usize / rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Height> for DifficultyEpoch {
|
||||
fn from(value: Height) -> Self {
|
||||
Self((u32::from(value) / 2016) as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub for Difficultyepoch {
|
||||
impl CheckedSub for DifficultyEpoch {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
|
||||
@@ -49,14 +49,14 @@ impl From<usize> for Dollars {
|
||||
impl Add for Dollars {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
Self::from(Cents::from(self) + Cents::from(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<usize> for Dollars {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 / rhs as f64)
|
||||
Self::from(Cents::from(self) / rhs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use std::{fmt::Debug, ops::Add};
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
ops::{Add, Div},
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
@@ -23,27 +26,35 @@ use super::Height;
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct Halvingepoch(u8);
|
||||
pub struct HalvingEpoch(u8);
|
||||
|
||||
impl From<u8> for Halvingepoch {
|
||||
impl From<u8> for HalvingEpoch {
|
||||
fn from(value: u8) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Halvingepoch {
|
||||
impl From<usize> for HalvingEpoch {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u8)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Halvingepoch> for usize {
|
||||
fn from(value: Halvingepoch) -> Self {
|
||||
impl From<HalvingEpoch> for usize {
|
||||
fn from(value: HalvingEpoch) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Halvingepoch {
|
||||
impl Add for HalvingEpoch {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self::from(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for HalvingEpoch {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
@@ -51,14 +62,21 @@ impl Add<usize> for Halvingepoch {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Height> for Halvingepoch {
|
||||
impl From<Height> for HalvingEpoch {
|
||||
fn from(value: Height) -> Self {
|
||||
Self((u32::from(value) / 210_000) as u8)
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub for Halvingepoch {
|
||||
impl CheckedSub for HalvingEpoch {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<usize> for HalvingEpoch {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
Self::from(self.0 as usize / rhs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ use crate::CheckedSub;
|
||||
pub struct Height(u32);
|
||||
|
||||
impl Height {
|
||||
pub const ZERO: Self = Height(0);
|
||||
pub const MAX: Self = Height(u32::MAX);
|
||||
pub const ZERO: Self = Self(0);
|
||||
pub const MAX: Self = Self(u32::MAX);
|
||||
|
||||
pub fn new(height: u32) -> Self {
|
||||
Self(height)
|
||||
@@ -181,12 +181,6 @@ impl From<bitcoin::locktime::absolute::Height> for Height {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Height> for bitcoin::locktime::absolute::Height {
|
||||
fn from(value: Height) -> Self {
|
||||
bitcoin::locktime::absolute::Height::from_consensus(value.0).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&std::path::Path> for Height {
|
||||
type Error = crate::Error;
|
||||
fn try_from(value: &std::path::Path) -> Result<Self, Self::Error> {
|
||||
|
||||
+17
-17
@@ -25,49 +25,49 @@ use super::Vin;
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct Txinindex(u64);
|
||||
pub struct InputIndex(u64);
|
||||
|
||||
impl Txinindex {
|
||||
impl InputIndex {
|
||||
pub fn incremented(self) -> Self {
|
||||
Self(*self + 1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Txinindex> for Txinindex {
|
||||
impl Add<InputIndex> for InputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Txinindex) -> Self::Output {
|
||||
fn add(self, rhs: InputIndex) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Vin> for Txinindex {
|
||||
impl Add<Vin> for InputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Vin) -> Self::Output {
|
||||
Self(self.0 + u64::from(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Txinindex {
|
||||
impl Add<usize> for InputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 + rhs as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<Txinindex> for Txinindex {
|
||||
fn add_assign(&mut self, rhs: Txinindex) {
|
||||
impl AddAssign<InputIndex> for InputIndex {
|
||||
fn add_assign(&mut self, rhs: InputIndex) {
|
||||
self.0 += rhs.0
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub<Txinindex> for Txinindex {
|
||||
impl CheckedSub<InputIndex> for InputIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self::from)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Txinindex> for u32 {
|
||||
fn from(value: Txinindex) -> Self {
|
||||
impl From<InputIndex> for u32 {
|
||||
fn from(value: InputIndex) -> Self {
|
||||
if value.0 > u32::MAX as u64 {
|
||||
panic!()
|
||||
}
|
||||
@@ -75,24 +75,24 @@ impl From<Txinindex> for u32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for Txinindex {
|
||||
impl From<u64> for InputIndex {
|
||||
fn from(value: u64) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<Txinindex> for u64 {
|
||||
fn from(value: Txinindex) -> Self {
|
||||
impl From<InputIndex> for u64 {
|
||||
fn from(value: InputIndex) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Txinindex {
|
||||
impl From<usize> for InputIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u64)
|
||||
}
|
||||
}
|
||||
impl From<Txinindex> for usize {
|
||||
fn from(value: Txinindex) -> Self {
|
||||
impl From<InputIndex> for usize {
|
||||
fn from(value: InputIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
use serde::Serialize;
|
||||
use zerocopy::{Immutable, IntoBytes, KnownLayout, TryFromBytes};
|
||||
|
||||
use super::{Height, Timestamp};
|
||||
|
||||
#[derive(Debug, Immutable, Clone, Copy, IntoBytes, KnownLayout, TryFromBytes, Serialize)]
|
||||
#[repr(C)]
|
||||
#[allow(warnings)]
|
||||
pub enum LockTime {
|
||||
Height(Height),
|
||||
Timestamp(Timestamp),
|
||||
}
|
||||
|
||||
impl From<bitcoin::absolute::LockTime> for LockTime {
|
||||
fn from(value: bitcoin::absolute::LockTime) -> Self {
|
||||
match value {
|
||||
bitcoin::absolute::LockTime::Blocks(h) => LockTime::Height(h.into()),
|
||||
bitcoin::absolute::LockTime::Seconds(t) => LockTime::Timestamp(t.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LockTime> for bitcoin::absolute::LockTime {
|
||||
fn from(value: LockTime) -> Self {
|
||||
match value {
|
||||
LockTime::Height(h) => bitcoin::absolute::LockTime::Blocks(h.into()),
|
||||
LockTime::Timestamp(t) => bitcoin::absolute::LockTime::Seconds(t.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
mod addressbytes;
|
||||
mod addressindex;
|
||||
mod addressindextxoutindex;
|
||||
mod addresstype;
|
||||
mod addresstypeindex;
|
||||
mod addressbyteshash;
|
||||
// mod addressindex;
|
||||
// mod addressindexoutputindex;
|
||||
// mod addresstype;
|
||||
mod bitcoin;
|
||||
mod blockhash;
|
||||
mod blockhashprefix;
|
||||
mod cents;
|
||||
mod compressed;
|
||||
mod date;
|
||||
mod dateindex;
|
||||
mod decadeindex;
|
||||
@@ -15,20 +15,24 @@ mod dollars;
|
||||
mod feerate;
|
||||
mod halvingepoch;
|
||||
mod height;
|
||||
mod locktime;
|
||||
mod inputindex;
|
||||
mod monthindex;
|
||||
mod ohlc;
|
||||
mod outputindex;
|
||||
mod outputtype;
|
||||
mod outputtypeindex;
|
||||
mod quarterindex;
|
||||
mod rawlocktime;
|
||||
mod sats;
|
||||
mod stored_f64;
|
||||
mod stored_u32;
|
||||
mod stored_u64;
|
||||
mod stored_u8;
|
||||
mod stored_usize;
|
||||
mod timestamp;
|
||||
mod txid;
|
||||
mod txidprefix;
|
||||
mod txindex;
|
||||
mod txinindex;
|
||||
mod txoutindex;
|
||||
mod txversion;
|
||||
mod unit;
|
||||
mod vin;
|
||||
@@ -38,14 +42,14 @@ mod weight;
|
||||
mod yearindex;
|
||||
|
||||
pub use addressbytes::*;
|
||||
pub use addressindex::*;
|
||||
pub use addressindextxoutindex::*;
|
||||
pub use addresstype::*;
|
||||
pub use addresstypeindex::*;
|
||||
pub use addressbyteshash::*;
|
||||
// pub use addressindex::*;
|
||||
// pub use addressindexoutputindex::*;
|
||||
// pub use addresstype::*;
|
||||
pub use bitcoin::*;
|
||||
pub use blockhash::*;
|
||||
pub use blockhashprefix::*;
|
||||
pub use cents::*;
|
||||
pub use compressed::*;
|
||||
pub use date::*;
|
||||
pub use dateindex::*;
|
||||
pub use decadeindex::*;
|
||||
@@ -54,20 +58,24 @@ pub use dollars::*;
|
||||
pub use feerate::*;
|
||||
pub use halvingepoch::*;
|
||||
pub use height::*;
|
||||
pub use locktime::*;
|
||||
pub use inputindex::*;
|
||||
pub use monthindex::*;
|
||||
pub use ohlc::*;
|
||||
pub use outputindex::*;
|
||||
pub use outputtype::*;
|
||||
pub use outputtypeindex::*;
|
||||
pub use quarterindex::*;
|
||||
pub use rawlocktime::*;
|
||||
pub use sats::*;
|
||||
pub use stored_f64::*;
|
||||
pub use stored_u8::*;
|
||||
pub use stored_u32::*;
|
||||
pub use stored_u64::*;
|
||||
pub use stored_usize::*;
|
||||
pub use timestamp::*;
|
||||
pub use txid::*;
|
||||
pub use txidprefix::*;
|
||||
pub use txindex::*;
|
||||
pub use txinindex::*;
|
||||
pub use txoutindex::*;
|
||||
pub use txversion::*;
|
||||
pub use unit::*;
|
||||
pub use vin::*;
|
||||
|
||||
@@ -5,7 +5,7 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
use super::{Date, Dateindex, Yearindex};
|
||||
use super::{Date, DateIndex, YearIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
@@ -23,27 +23,27 @@ use super::{Date, Dateindex, Yearindex};
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct Monthindex(u16);
|
||||
pub struct MonthIndex(u16);
|
||||
|
||||
impl From<u16> for Monthindex {
|
||||
impl From<u16> for MonthIndex {
|
||||
fn from(value: u16) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Monthindex {
|
||||
impl From<usize> for MonthIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Monthindex> for usize {
|
||||
fn from(value: Monthindex) -> Self {
|
||||
impl From<MonthIndex> for usize {
|
||||
fn from(value: MonthIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Monthindex {
|
||||
impl Add<usize> for MonthIndex {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
@@ -51,19 +51,19 @@ impl Add<usize> for Monthindex {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dateindex> for Monthindex {
|
||||
fn from(value: Dateindex) -> Self {
|
||||
impl From<DateIndex> for MonthIndex {
|
||||
fn from(value: DateIndex) -> Self {
|
||||
Self::from(Date::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Date> for Monthindex {
|
||||
impl From<Date> for MonthIndex {
|
||||
fn from(value: Date) -> Self {
|
||||
Self(u16::from(Yearindex::from(value)) * 12 + value.month() as u16 - 1)
|
||||
Self(u16::from(YearIndex::from(value)) * 12 + value.month() as u16 - 1)
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub for Monthindex {
|
||||
impl CheckedSub for MonthIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use super::{Cents, Dollars, Sats};
|
||||
|
||||
#[derive(Debug, Default, Clone, FromBytes, Immutable, IntoBytes, KnownLayout, Serialize)]
|
||||
#[derive(Debug, Default, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
|
||||
#[repr(C)]
|
||||
pub struct OHLCCents {
|
||||
pub open: Open<Cents>,
|
||||
@@ -37,6 +37,20 @@ impl From<Close<Cents>> for OHLCCents {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for OHLCCents {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut tup = serializer.serialize_tuple(4)?;
|
||||
tup.serialize_element(&self.open)?;
|
||||
tup.serialize_element(&self.high)?;
|
||||
tup.serialize_element(&self.low)?;
|
||||
tup.serialize_element(&self.close)?;
|
||||
tup.end()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
|
||||
#[repr(C)]
|
||||
pub struct OHLCDollars {
|
||||
|
||||
+17
-17
@@ -25,9 +25,9 @@ use super::Vout;
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct Txoutindex(u64);
|
||||
pub struct OutputIndex(u64);
|
||||
|
||||
impl Txoutindex {
|
||||
impl OutputIndex {
|
||||
pub const COINBASE: Self = Self(u64::MAX);
|
||||
|
||||
pub fn incremented(self) -> Self {
|
||||
@@ -39,41 +39,41 @@ impl Txoutindex {
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Txoutindex> for Txoutindex {
|
||||
impl Add<OutputIndex> for OutputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Txoutindex) -> Self::Output {
|
||||
fn add(self, rhs: OutputIndex) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Vout> for Txoutindex {
|
||||
impl Add<Vout> for OutputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Vout) -> Self::Output {
|
||||
Self(self.0 + u64::from(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Txoutindex {
|
||||
impl Add<usize> for OutputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 + rhs as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<Txoutindex> for Txoutindex {
|
||||
fn add_assign(&mut self, rhs: Txoutindex) {
|
||||
impl AddAssign<OutputIndex> for OutputIndex {
|
||||
fn add_assign(&mut self, rhs: OutputIndex) {
|
||||
self.0 += rhs.0
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub<Txoutindex> for Txoutindex {
|
||||
impl CheckedSub<OutputIndex> for OutputIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self::from)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Txoutindex> for u32 {
|
||||
fn from(value: Txoutindex) -> Self {
|
||||
impl From<OutputIndex> for u32 {
|
||||
fn from(value: OutputIndex) -> Self {
|
||||
if value.0 > u32::MAX as u64 {
|
||||
panic!()
|
||||
}
|
||||
@@ -81,24 +81,24 @@ impl From<Txoutindex> for u32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for Txoutindex {
|
||||
impl From<u64> for OutputIndex {
|
||||
fn from(value: u64) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<Txoutindex> for u64 {
|
||||
fn from(value: Txoutindex) -> Self {
|
||||
impl From<OutputIndex> for u64 {
|
||||
fn from(value: OutputIndex) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Txoutindex {
|
||||
impl From<usize> for OutputIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u64)
|
||||
}
|
||||
}
|
||||
impl From<Txoutindex> for usize {
|
||||
fn from(value: Txoutindex) -> Self {
|
||||
impl From<OutputIndex> for usize {
|
||||
fn from(value: OutputIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
+28
-13
@@ -1,27 +1,38 @@
|
||||
use bitcoin::ScriptBuf;
|
||||
use bitcoin::{ScriptBuf, opcodes::all::OP_PUSHBYTES_2};
|
||||
use serde::Serialize;
|
||||
use zerocopy::{Immutable, IntoBytes, KnownLayout, TryFromBytes};
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, TryFromBytes, Immutable, IntoBytes, KnownLayout, Serialize,
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
TryFromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
#[repr(u8)]
|
||||
pub enum Addresstype {
|
||||
pub enum OutputType {
|
||||
P2PK65,
|
||||
P2PK33,
|
||||
P2PKH,
|
||||
P2MS,
|
||||
P2SH,
|
||||
OpReturn,
|
||||
P2WPKH,
|
||||
P2WSH,
|
||||
P2TR,
|
||||
Multisig = 251,
|
||||
PushOnly = 252,
|
||||
OpReturn = 253,
|
||||
P2A,
|
||||
Empty = 254,
|
||||
Unknown = 255,
|
||||
}
|
||||
|
||||
impl From<&ScriptBuf> for Addresstype {
|
||||
impl From<&ScriptBuf> for OutputType {
|
||||
fn from(script: &ScriptBuf) -> Self {
|
||||
if script.is_p2pk() {
|
||||
let bytes = script.as_bytes();
|
||||
@@ -36,22 +47,26 @@ impl From<&ScriptBuf> for Addresstype {
|
||||
}
|
||||
} else if script.is_p2pkh() {
|
||||
Self::P2PKH
|
||||
} else if script.is_multisig() {
|
||||
Self::P2MS
|
||||
} else if script.is_p2sh() {
|
||||
Self::P2SH
|
||||
} else if script.is_op_return() {
|
||||
Self::OpReturn
|
||||
} else if script.is_p2wpkh() {
|
||||
Self::P2WPKH
|
||||
} else if script.is_p2wsh() {
|
||||
Self::P2WSH
|
||||
} else if script.is_p2tr() {
|
||||
Self::P2TR
|
||||
} else if script.witness_version() == Some(bitcoin::WitnessVersion::V1)
|
||||
&& script.len() == 4
|
||||
&& script.as_bytes()[1] == OP_PUSHBYTES_2.to_u8()
|
||||
&& script.as_bytes()[2..4] == [78, 115]
|
||||
{
|
||||
Self::P2A
|
||||
} else if script.is_empty() {
|
||||
Self::Empty
|
||||
} else if script.is_op_return() {
|
||||
Self::OpReturn
|
||||
} else if script.is_push_only() {
|
||||
Self::PushOnly
|
||||
} else if script.is_multisig() {
|
||||
Self::Multisig
|
||||
} else {
|
||||
Self::Unknown
|
||||
}
|
||||
@@ -0,0 +1,634 @@
|
||||
use std::ops::Add;
|
||||
|
||||
use byteview::ByteView;
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, Error};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct OutputTypeIndex(u32);
|
||||
|
||||
impl OutputTypeIndex {
|
||||
pub fn increment(&mut self) {
|
||||
self.0 += 1;
|
||||
}
|
||||
|
||||
pub fn incremented(self) -> Self {
|
||||
Self(self.0 + 1)
|
||||
}
|
||||
|
||||
pub fn copy_then_increment(&mut self) -> Self {
|
||||
let i = *self;
|
||||
self.increment();
|
||||
i
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for OutputTypeIndex {
|
||||
fn from(value: u32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for OutputTypeIndex {
|
||||
fn from(value: u64) -> Self {
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
impl From<OutputTypeIndex> for u64 {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
value.0 as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for OutputTypeIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
impl From<OutputTypeIndex> for usize {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for OutputTypeIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 + rhs as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<OutputTypeIndex> for OutputTypeIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: OutputTypeIndex) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
impl TryFrom<ByteView> for OutputTypeIndex {
|
||||
type Error = Error;
|
||||
fn try_from(value: ByteView) -> Result<Self, Self::Error> {
|
||||
Ok(Self::read_from_bytes(&value)?)
|
||||
}
|
||||
}
|
||||
impl From<OutputTypeIndex> for ByteView {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct EmptyOutputIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for EmptyOutputIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<EmptyOutputIndex> for usize {
|
||||
fn from(value: EmptyOutputIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for EmptyOutputIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for EmptyOutputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<EmptyOutputIndex> for EmptyOutputIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2MSIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2MSIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2MSIndex> for usize {
|
||||
fn from(value: P2MSIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2MSIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2MSIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2MSIndex> for P2MSIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2AIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2AIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2AIndex> for usize {
|
||||
fn from(value: P2AIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2AIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2AIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2AIndex> for P2AIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct OpReturnIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for OpReturnIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<OpReturnIndex> for usize {
|
||||
fn from(value: OpReturnIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for OpReturnIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for OpReturnIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<OpReturnIndex> for OpReturnIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct UnknownOutputIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for UnknownOutputIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<UnknownOutputIndex> for usize {
|
||||
fn from(value: UnknownOutputIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for UnknownOutputIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for UnknownOutputIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<UnknownOutputIndex> for UnknownOutputIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2PK33Index(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2PK33Index {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2PK33Index> for usize {
|
||||
fn from(value: P2PK33Index) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2PK33Index {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2PK33Index {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2PK33Index> for P2PK33Index {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2PK65Index(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2PK65Index {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2PK65Index> for usize {
|
||||
fn from(value: P2PK65Index) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2PK65Index {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2PK65Index {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2PK65Index> for P2PK65Index {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2PKHIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2PKHIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2PKHIndex> for usize {
|
||||
fn from(value: P2PKHIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2PKHIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2PKHIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2PKHIndex> for P2PKHIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2SHIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2SHIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2SHIndex> for usize {
|
||||
fn from(value: P2SHIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2SHIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2SHIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2SHIndex> for P2SHIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2TRIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2TRIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2TRIndex> for usize {
|
||||
fn from(value: P2TRIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2TRIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2TRIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2TRIndex> for P2TRIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2WPKHIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2WPKHIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2WPKHIndex> for usize {
|
||||
fn from(value: P2WPKHIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2WPKHIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2WPKHIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2WPKHIndex> for P2WPKHIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Copy,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Default,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct P2WSHIndex(OutputTypeIndex);
|
||||
impl From<OutputTypeIndex> for P2WSHIndex {
|
||||
fn from(value: OutputTypeIndex) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<P2WSHIndex> for usize {
|
||||
fn from(value: P2WSHIndex) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
impl From<usize> for P2WSHIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(OutputTypeIndex::from(value))
|
||||
}
|
||||
}
|
||||
impl Add<usize> for P2WSHIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(*self + rhs)
|
||||
}
|
||||
}
|
||||
impl CheckedSub<P2WSHIndex> for P2WSHIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.0.checked_sub(rhs.0.0).map(OutputTypeIndex).map(Self)
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
use super::Monthindex;
|
||||
use super::MonthIndex;
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
@@ -23,27 +23,27 @@ use super::Monthindex;
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct Quarterindex(u16);
|
||||
pub struct QuarterIndex(u16);
|
||||
|
||||
impl From<u16> for Quarterindex {
|
||||
impl From<u16> for QuarterIndex {
|
||||
fn from(value: u16) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Quarterindex {
|
||||
impl From<usize> for QuarterIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Quarterindex> for usize {
|
||||
fn from(value: Quarterindex) -> Self {
|
||||
impl From<QuarterIndex> for usize {
|
||||
fn from(value: QuarterIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Quarterindex {
|
||||
impl Add<usize> for QuarterIndex {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
@@ -51,13 +51,13 @@ impl Add<usize> for Quarterindex {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Monthindex> for Quarterindex {
|
||||
fn from(value: Monthindex) -> Self {
|
||||
impl From<MonthIndex> for QuarterIndex {
|
||||
fn from(value: MonthIndex) -> Self {
|
||||
Self((usize::from(value) / 3) as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub for Quarterindex {
|
||||
impl CheckedSub for QuarterIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
use bitcoin::absolute::LockTime;
|
||||
use serde::Serialize;
|
||||
use zerocopy::{Immutable, IntoBytes, KnownLayout, TryFromBytes};
|
||||
|
||||
#[derive(Debug, Immutable, Clone, Copy, IntoBytes, KnownLayout, TryFromBytes, Serialize)]
|
||||
pub struct RawLockTime(u32);
|
||||
|
||||
impl From<LockTime> for RawLockTime {
|
||||
fn from(value: LockTime) -> Self {
|
||||
Self(value.to_consensus_u32())
|
||||
}
|
||||
}
|
||||
|
||||
const CONSENSUS_DELIMITER: u32 = 500_000_000;
|
||||
|
||||
impl From<RawLockTime> for LockTime {
|
||||
fn from(value: RawLockTime) -> Self {
|
||||
let value = value.0;
|
||||
if value >= CONSENSUS_DELIMITER {
|
||||
bitcoin::locktime::absolute::Height::from_consensus(value)
|
||||
.unwrap()
|
||||
.into()
|
||||
} else {
|
||||
bitcoin::locktime::absolute::Time::from_consensus(value)
|
||||
.unwrap()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
use super::{Bitcoin, Dollars, Height};
|
||||
use super::{Bitcoin, Cents, Dollars, Height};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
@@ -30,6 +30,7 @@ pub struct Sats(u64);
|
||||
|
||||
impl Sats {
|
||||
pub const ZERO: Self = Self(0);
|
||||
pub const MAX: Self = Self(u64::MAX);
|
||||
pub const ONE_BTC: Self = Self(100_000_000);
|
||||
|
||||
pub fn is_zero(&self) -> bool {
|
||||
@@ -39,8 +40,8 @@ impl Sats {
|
||||
|
||||
impl Add for Sats {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Sats) -> Self::Output {
|
||||
Sats::from(self.0 + rhs.0)
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self::from(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +94,12 @@ impl Sum for Sats {
|
||||
impl Div<Dollars> for Sats {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: Dollars) -> Self::Output {
|
||||
Self((self.0 as f64 / f64::from(rhs)) as u64)
|
||||
let raw_cents = u64::from(Cents::from(rhs));
|
||||
if raw_cents != 0 {
|
||||
Self(self.0 * 100 / raw_cents)
|
||||
} else {
|
||||
Self::MAX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +124,7 @@ impl From<usize> for Sats {
|
||||
|
||||
impl From<f64> for Sats {
|
||||
fn from(value: f64) -> Self {
|
||||
Self(value as u64)
|
||||
Self(value.round() as u64)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +147,7 @@ impl From<Sats> for Amount {
|
||||
|
||||
impl From<Bitcoin> for Sats {
|
||||
fn from(value: Bitcoin) -> Self {
|
||||
Self((f64::from(value) * (u64::from(Sats::ONE_BTC) as f64)).round() as u64)
|
||||
Self((f64::from(value) * (Sats::ONE_BTC.0 as f64)).round() as u64)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
use std::ops::{Add, Div};
|
||||
|
||||
use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct StoredF64(f64);
|
||||
|
||||
impl From<f64> for StoredF64 {
|
||||
fn from(value: f64) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for StoredF64 {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub<StoredF64> for StoredF64 {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
Some(Self(self.0 - rhs.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<usize> for StoredF64 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 / rhs as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for StoredF64 {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoredF64> for f64 {
|
||||
fn from(value: StoredF64) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for StoredF64 {}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl Ord for StoredF64 {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.0.partial_cmp(&other.0).unwrap()
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,11 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
use super::{
|
||||
EmptyOutputIndex, OpReturnIndex, P2AIndex, P2MSIndex, P2PK33Index, P2PK65Index, P2PKHIndex,
|
||||
P2SHIndex, P2TRIndex, P2WPKHIndex, P2WSHIndex, UnknownOutputIndex,
|
||||
};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
@@ -39,6 +44,9 @@ impl From<u32> for StoredU32 {
|
||||
|
||||
impl From<usize> for StoredU32 {
|
||||
fn from(value: usize) -> Self {
|
||||
if value > u32::MAX as usize {
|
||||
panic!("usize too big (value = {value})")
|
||||
}
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
@@ -77,3 +85,81 @@ impl From<StoredU32> for f64 {
|
||||
value.0 as f64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoredU32> for usize {
|
||||
fn from(value: StoredU32) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PK65Index> for StoredU32 {
|
||||
fn from(value: P2PK65Index) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PK33Index> for StoredU32 {
|
||||
fn from(value: P2PK33Index) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PKHIndex> for StoredU32 {
|
||||
fn from(value: P2PKHIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OpReturnIndex> for StoredU32 {
|
||||
fn from(value: OpReturnIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2MSIndex> for StoredU32 {
|
||||
fn from(value: P2MSIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2SHIndex> for StoredU32 {
|
||||
fn from(value: P2SHIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2WSHIndex> for StoredU32 {
|
||||
fn from(value: P2WSHIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2WPKHIndex> for StoredU32 {
|
||||
fn from(value: P2WPKHIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2TRIndex> for StoredU32 {
|
||||
fn from(value: P2TRIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2AIndex> for StoredU32 {
|
||||
fn from(value: P2AIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnknownOutputIndex> for StoredU32 {
|
||||
fn from(value: UnknownOutputIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EmptyOutputIndex> for StoredU32 {
|
||||
fn from(value: EmptyOutputIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
use super::{Txindex, Txinindex, Txoutindex};
|
||||
use super::{InputIndex, OutputIndex, TxIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
@@ -80,20 +80,20 @@ impl From<StoredU64> for f64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Txindex> for StoredU64 {
|
||||
fn from(value: Txindex) -> Self {
|
||||
impl From<TxIndex> for StoredU64 {
|
||||
fn from(value: TxIndex) -> Self {
|
||||
Self(*value as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Txinindex> for StoredU64 {
|
||||
fn from(value: Txinindex) -> Self {
|
||||
impl From<InputIndex> for StoredU64 {
|
||||
fn from(value: InputIndex) -> Self {
|
||||
Self(*value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Txoutindex> for StoredU64 {
|
||||
fn from(value: Txoutindex) -> Self {
|
||||
impl From<OutputIndex> for StoredU64 {
|
||||
fn from(value: OutputIndex) -> Self {
|
||||
Self(*value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,12 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
use super::{
|
||||
DateIndex, EmptyOutputIndex, Height, InputIndex, MonthIndex, OpReturnIndex, OutputIndex,
|
||||
P2AIndex, P2MSIndex, P2PK33Index, P2PK65Index, P2PKHIndex, P2SHIndex, P2TRIndex, P2WPKHIndex,
|
||||
P2WSHIndex, TxIndex, UnknownOutputIndex, YearIndex,
|
||||
};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
@@ -71,3 +77,117 @@ impl From<StoredUsize> for f64 {
|
||||
value.0 as f64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Height> for StoredUsize {
|
||||
fn from(value: Height) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DateIndex> for StoredUsize {
|
||||
fn from(value: DateIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MonthIndex> for StoredUsize {
|
||||
fn from(value: MonthIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<YearIndex> for StoredUsize {
|
||||
fn from(value: YearIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OutputIndex> for StoredUsize {
|
||||
fn from(value: OutputIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InputIndex> for StoredUsize {
|
||||
fn from(value: InputIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TxIndex> for StoredUsize {
|
||||
fn from(value: TxIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PK65Index> for StoredUsize {
|
||||
fn from(value: P2PK65Index) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PK33Index> for StoredUsize {
|
||||
fn from(value: P2PK33Index) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2PKHIndex> for StoredUsize {
|
||||
fn from(value: P2PKHIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OpReturnIndex> for StoredUsize {
|
||||
fn from(value: OpReturnIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2MSIndex> for StoredUsize {
|
||||
fn from(value: P2MSIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2SHIndex> for StoredUsize {
|
||||
fn from(value: P2SHIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2WSHIndex> for StoredUsize {
|
||||
fn from(value: P2WSHIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2WPKHIndex> for StoredUsize {
|
||||
fn from(value: P2WPKHIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2TRIndex> for StoredUsize {
|
||||
fn from(value: P2TRIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<P2AIndex> for StoredUsize {
|
||||
fn from(value: P2AIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnknownOutputIndex> for StoredUsize {
|
||||
fn from(value: UnknownOutputIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EmptyOutputIndex> for StoredUsize {
|
||||
fn from(value: EmptyOutputIndex) -> Self {
|
||||
Self::from(usize::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,12 +65,6 @@ impl From<bitcoin::locktime::absolute::Time> for Timestamp {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Timestamp> for bitcoin::locktime::absolute::Time {
|
||||
fn from(value: Timestamp) -> Self {
|
||||
bitcoin::locktime::absolute::Time::from_consensus(*value).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Timestamp {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u32)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
use byteview::ByteView;
|
||||
use derive_deref::Deref;
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{Error, copy_first_8bytes};
|
||||
|
||||
use super::Txid;
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct TxidPrefix([u8; 8]);
|
||||
|
||||
impl From<Txid> for TxidPrefix {
|
||||
fn from(value: Txid) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Txid> for TxidPrefix {
|
||||
fn from(value: &Txid) -> Self {
|
||||
Self(copy_first_8bytes(&value[..]).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ByteView> for TxidPrefix {
|
||||
type Error = Error;
|
||||
fn try_from(value: ByteView) -> Result<Self, Self::Error> {
|
||||
Ok(Self::read_from_bytes(&value)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&TxidPrefix> for ByteView {
|
||||
fn from(value: &TxidPrefix) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TxidPrefix> for ByteView {
|
||||
fn from(value: TxidPrefix) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 8]> for TxidPrefix {
|
||||
fn from(value: [u8; 8]) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
@@ -26,82 +26,88 @@ use super::StoredU32;
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct Txindex(u32);
|
||||
pub struct TxIndex(u32);
|
||||
|
||||
impl TxIndex {
|
||||
pub const ZERO: Self = Self(0);
|
||||
|
||||
pub fn new(txindex: u32) -> Self {
|
||||
Self(txindex)
|
||||
}
|
||||
|
||||
impl Txindex {
|
||||
pub fn incremented(self) -> Self {
|
||||
Self(*self + 1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Txindex> for Txindex {
|
||||
impl Add<TxIndex> for TxIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Txindex) -> Self::Output {
|
||||
fn add(self, rhs: TxIndex) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Txindex {
|
||||
impl Add<usize> for TxIndex {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 + rhs as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<Txindex> for Txindex {
|
||||
fn add_assign(&mut self, rhs: Txindex) {
|
||||
impl AddAssign<TxIndex> for TxIndex {
|
||||
fn add_assign(&mut self, rhs: TxIndex) {
|
||||
self.0 += rhs.0
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub<Txindex> for Txindex {
|
||||
fn checked_sub(self, rhs: Txindex) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Txindex::from)
|
||||
impl CheckedSub<TxIndex> for TxIndex {
|
||||
fn checked_sub(self, rhs: TxIndex) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(TxIndex::from)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Txindex {
|
||||
impl From<u32> for TxIndex {
|
||||
fn from(value: u32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for Txindex {
|
||||
impl From<u64> for TxIndex {
|
||||
fn from(value: u64) -> Self {
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
impl From<Txindex> for u64 {
|
||||
fn from(value: Txindex) -> Self {
|
||||
impl From<TxIndex> for u64 {
|
||||
fn from(value: TxIndex) -> Self {
|
||||
value.0 as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Txindex {
|
||||
impl From<usize> for TxIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u32)
|
||||
}
|
||||
}
|
||||
impl From<Txindex> for usize {
|
||||
fn from(value: Txindex) -> Self {
|
||||
impl From<TxIndex> for usize {
|
||||
fn from(value: TxIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ByteView> for Txindex {
|
||||
impl TryFrom<ByteView> for TxIndex {
|
||||
type Error = Error;
|
||||
fn try_from(value: ByteView) -> Result<Self, Self::Error> {
|
||||
Ok(Self::read_from_bytes(&value)?)
|
||||
}
|
||||
}
|
||||
impl From<Txindex> for ByteView {
|
||||
fn from(value: Txindex) -> Self {
|
||||
impl From<TxIndex> for ByteView {
|
||||
fn from(value: TxIndex) -> Self {
|
||||
Self::new(value.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Txindex> for StoredU32 {
|
||||
fn from(value: Txindex) -> Self {
|
||||
impl From<TxIndex> for StoredU32 {
|
||||
fn from(value: TxIndex) -> Self {
|
||||
Self::from(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,28 +19,34 @@ use super::StoredU8;
|
||||
FromBytes,
|
||||
Serialize,
|
||||
)]
|
||||
pub struct TxVersion(i32);
|
||||
pub struct TxVersion(u8);
|
||||
|
||||
impl TxVersion {
|
||||
pub const ONE: Self = Self(1);
|
||||
pub const TWO: Self = Self(2);
|
||||
pub const THREE: Self = Self(3);
|
||||
pub const NON_STANDARD: Self = Self(u8::MAX);
|
||||
}
|
||||
|
||||
impl From<bitcoin::transaction::Version> for TxVersion {
|
||||
fn from(value: bitcoin::transaction::Version) -> Self {
|
||||
Self(value.0)
|
||||
match value.0 {
|
||||
1 => Self::ONE,
|
||||
2 => Self::TWO,
|
||||
3 => Self::THREE,
|
||||
_ => Self::NON_STANDARD,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TxVersion> for bitcoin::transaction::Version {
|
||||
fn from(value: TxVersion) -> Self {
|
||||
Self(value.0)
|
||||
Self(value.0 as i32)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TxVersion> for StoredU8 {
|
||||
fn from(value: TxVersion) -> Self {
|
||||
Self::from(value.0 as u8)
|
||||
Self::from(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
use super::{Date, Dateindex};
|
||||
use super::{Date, DateIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
@@ -23,27 +23,27 @@ use super::{Date, Dateindex};
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct Weekindex(u16);
|
||||
pub struct WeekIndex(u16);
|
||||
|
||||
impl From<u16> for Weekindex {
|
||||
impl From<u16> for WeekIndex {
|
||||
fn from(value: u16) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Weekindex {
|
||||
impl From<usize> for WeekIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Weekindex> for usize {
|
||||
fn from(value: Weekindex) -> Self {
|
||||
impl From<WeekIndex> for usize {
|
||||
fn from(value: WeekIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Weekindex {
|
||||
impl Add<usize> for WeekIndex {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
@@ -51,13 +51,13 @@ impl Add<usize> for Weekindex {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dateindex> for Weekindex {
|
||||
fn from(value: Dateindex) -> Self {
|
||||
impl From<DateIndex> for WeekIndex {
|
||||
fn from(value: DateIndex) -> Self {
|
||||
Self::from(Date::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Date> for Weekindex {
|
||||
impl From<Date> for WeekIndex {
|
||||
fn from(value: Date) -> Self {
|
||||
let date = jiff::civil::Date::from(value).iso_week_date();
|
||||
|
||||
@@ -81,7 +81,7 @@ impl From<Date> for Weekindex {
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub for Weekindex {
|
||||
impl CheckedSub for WeekIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ impl From<bitcoin::Weight> for Weight {
|
||||
|
||||
impl From<Weight> for bitcoin::Weight {
|
||||
fn from(value: Weight) -> Self {
|
||||
Self::from_wu(*value)
|
||||
Self::from_wu(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,3 +64,10 @@ impl Div<usize> for Weight {
|
||||
Self::from(self.0 as usize / rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Weight> for Weight {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 / rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
use super::{Date, Dateindex, Monthindex};
|
||||
use super::{Date, DateIndex, MonthIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
@@ -23,27 +23,27 @@ use super::{Date, Dateindex, Monthindex};
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
pub struct Yearindex(u8);
|
||||
pub struct YearIndex(u8);
|
||||
|
||||
impl From<u8> for Yearindex {
|
||||
impl From<u8> for YearIndex {
|
||||
fn from(value: u8) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Yearindex {
|
||||
impl From<usize> for YearIndex {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u8)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Yearindex> for usize {
|
||||
fn from(value: Yearindex) -> Self {
|
||||
impl From<YearIndex> for usize {
|
||||
fn from(value: YearIndex) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for Yearindex {
|
||||
impl Add<usize> for YearIndex {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
@@ -51,32 +51,32 @@ impl Add<usize> for Yearindex {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dateindex> for Yearindex {
|
||||
fn from(value: Dateindex) -> Self {
|
||||
impl From<DateIndex> for YearIndex {
|
||||
fn from(value: DateIndex) -> Self {
|
||||
Self::from(Date::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Date> for Yearindex {
|
||||
impl From<Date> for YearIndex {
|
||||
fn from(value: Date) -> Self {
|
||||
Self((value.year() - 2009) as u8)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Yearindex> for u16 {
|
||||
fn from(value: Yearindex) -> Self {
|
||||
impl From<YearIndex> for u16 {
|
||||
fn from(value: YearIndex) -> Self {
|
||||
value.0 as u16
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub for Yearindex {
|
||||
impl CheckedSub for YearIndex {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Monthindex> for Yearindex {
|
||||
fn from(value: Monthindex) -> Self {
|
||||
impl From<MonthIndex> for YearIndex {
|
||||
fn from(value: MonthIndex) -> Self {
|
||||
Self((usize::from(value) / 12) as u8)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#[allow(clippy::result_unit_err)]
|
||||
pub fn copy_first_8bytes(slice: &[u8]) -> Result<[u8; 8], ()> {
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
let buf_len = buf.len();
|
||||
if slice.len() < buf_len {
|
||||
return Err(());
|
||||
}
|
||||
slice.iter().take(buf_len).enumerate().for_each(|(i, r)| {
|
||||
buf[i] = *r;
|
||||
});
|
||||
Ok(buf)
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
mod bytes;
|
||||
mod checked_sub;
|
||||
mod paths;
|
||||
mod pause;
|
||||
mod rlimit;
|
||||
|
||||
pub use bytes::*;
|
||||
pub use checked_sub::*;
|
||||
pub use paths::*;
|
||||
pub use pause::*;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a href="https://bsky.app/profile/bitcoinresearchkit.org">
|
||||
<img src="https://img.shields.io/badge/bluesky-blue?link=https%3A%2F%2Fbsky.app%2Fprofile%2Fbitcoinresearchkit.org" alt="Bluesky" />
|
||||
</a>
|
||||
<a href="https://x.com/0xbrk">
|
||||
<a href="https://x.com/brkdotorg">
|
||||
<img src="https://img.shields.io/badge/x.com-black" alt="X" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a href="https://bsky.app/profile/bitcoinresearchkit.org">
|
||||
<img src="https://img.shields.io/badge/bluesky-blue?link=https%3A%2F%2Fbsky.app%2Fprofile%2Fbitcoinresearchkit.org" alt="Bluesky" />
|
||||
</a>
|
||||
<a href="https://x.com/0xbrk">
|
||||
<a href="https://x.com/brkdotorg">
|
||||
<img src="https://img.shields.io/badge/x.com-black" alt="X" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a href="https://bsky.app/profile/bitcoinresearchkit.org">
|
||||
<img src="https://img.shields.io/badge/bluesky-blue?link=https%3A%2F%2Fbsky.app%2Fprofile%2Fbitcoinresearchkit.org" alt="Bluesky" />
|
||||
</a>
|
||||
<a href="https://x.com/0xbrk">
|
||||
<a href="https://x.com/brkdotorg">
|
||||
<img src="https://img.shields.io/badge/x.com-black" alt="X" />
|
||||
</a>
|
||||
</p>
|
||||
@@ -58,10 +58,9 @@ Stores: `src/storage/stores/mod.rs`
|
||||
|
||||
## Benchmark
|
||||
|
||||
### Result 1 - 2025-04-12
|
||||
### `v0.0.21`
|
||||
|
||||
- version: `v0.0.21`
|
||||
- machine: `Macbook Pro M3 Pro (36GB RAM)`
|
||||
- machine: `MBP M3 Pro (36GB RAM)`
|
||||
- mode: `raw`
|
||||
- from: `0`
|
||||
- to: `892_098`
|
||||
@@ -69,3 +68,11 @@ Stores: `src/storage/stores/mod.rs`
|
||||
- peak memory: `6.1GB`
|
||||
- disk usage: `270 GB`
|
||||
- overhead: `36%` (`270 GB / 741 GB`)
|
||||
|
||||
### `v0.0.31`
|
||||
|
||||
- machine: `MBP M3 Pro (36GB RAM)`
|
||||
- mode: `raw`
|
||||
- disk usage: `208 GB`
|
||||
- overhead: `28%` (`208 GB / 744 GB`)
|
||||
- peak memory: `5.7GB`
|
||||
|
||||
@@ -24,7 +24,7 @@ fn main() -> color_eyre::Result<()> {
|
||||
|
||||
let outputs = Path::new("../../_outputs");
|
||||
|
||||
let mut indexer = Indexer::new(outputs.join("indexed").to_owned(), true, true)?;
|
||||
let mut indexer = Indexer::new(outputs, false, true)?;
|
||||
|
||||
indexer.import_stores()?;
|
||||
indexer.import_vecs()?;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use bitcoincore_rpc::Client;
|
||||
use brk_core::{
|
||||
Addressindex, BlockHash, CheckedSub, Emptyindex, Height, Multisigindex, Opreturnindex,
|
||||
P2PK33index, P2PK65index, P2PKHindex, P2SHindex, P2TRindex, P2WPKHindex, P2WSHindex,
|
||||
Pushonlyindex, Txindex, Txinindex, Txoutindex, Unknownindex,
|
||||
BlockHash, CheckedSub, EmptyOutputIndex, Height, InputIndex, OpReturnIndex, OutputIndex,
|
||||
OutputType, OutputTypeIndex, P2AIndex, P2MSIndex, P2PK33Index, P2PK65Index, P2PKHIndex,
|
||||
P2SHIndex, P2TRIndex, P2WPKHIndex, P2WSHIndex, TxIndex, UnknownOutputIndex,
|
||||
};
|
||||
use brk_parser::NUMBER_OF_UNSAFE_BLOCKS;
|
||||
use brk_vec::{Result, StoredIndex, StoredType, Value};
|
||||
@@ -12,46 +12,60 @@ use crate::{IndexedVec, Stores, Vecs};
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Indexes {
|
||||
pub addressindex: Addressindex,
|
||||
pub emptyindex: Emptyindex,
|
||||
pub emptyoutputindex: EmptyOutputIndex,
|
||||
pub height: Height,
|
||||
pub multisigindex: Multisigindex,
|
||||
pub opreturnindex: Opreturnindex,
|
||||
pub p2pk33index: P2PK33index,
|
||||
pub p2pk65index: P2PK65index,
|
||||
pub p2pkhindex: P2PKHindex,
|
||||
pub p2shindex: P2SHindex,
|
||||
pub p2trindex: P2TRindex,
|
||||
pub p2wpkhindex: P2WPKHindex,
|
||||
pub p2wshindex: P2WSHindex,
|
||||
pub pushonlyindex: Pushonlyindex,
|
||||
pub txindex: Txindex,
|
||||
pub txinindex: Txinindex,
|
||||
pub txoutindex: Txoutindex,
|
||||
pub unknownindex: Unknownindex,
|
||||
pub opreturnindex: OpReturnIndex,
|
||||
pub p2msindex: P2MSIndex,
|
||||
pub p2pk33index: P2PK33Index,
|
||||
pub p2pk65index: P2PK65Index,
|
||||
pub p2pkhindex: P2PKHIndex,
|
||||
pub p2shindex: P2SHIndex,
|
||||
pub p2trindex: P2TRIndex,
|
||||
pub p2wpkhindex: P2WPKHIndex,
|
||||
pub p2wshindex: P2WSHIndex,
|
||||
pub p2aindex: P2AIndex,
|
||||
pub txindex: TxIndex,
|
||||
pub inputindex: InputIndex,
|
||||
pub outputindex: OutputIndex,
|
||||
pub unknownoutputindex: UnknownOutputIndex,
|
||||
}
|
||||
|
||||
impl Indexes {
|
||||
pub fn outputtypeindex(&self, outputtype: OutputType) -> OutputTypeIndex {
|
||||
match outputtype {
|
||||
OutputType::Empty => *self.emptyoutputindex,
|
||||
OutputType::OpReturn => *self.opreturnindex,
|
||||
OutputType::P2A => *self.p2aindex,
|
||||
OutputType::P2MS => *self.p2msindex,
|
||||
OutputType::P2PK33 => *self.p2pkhindex,
|
||||
OutputType::P2PK65 => *self.p2pk65index,
|
||||
OutputType::P2PKH => *self.p2pkhindex,
|
||||
OutputType::P2SH => *self.p2shindex,
|
||||
OutputType::P2TR => *self.p2trindex,
|
||||
OutputType::P2WPKH => *self.p2wpkhindex,
|
||||
OutputType::P2WSH => *self.p2wshindex,
|
||||
OutputType::Unknown => *self.unknownoutputindex,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_if_needed(&self, vecs: &mut Vecs) -> brk_vec::Result<()> {
|
||||
let height = self.height;
|
||||
vecs.height_to_first_txindex
|
||||
.push_if_needed(height, self.txindex)?;
|
||||
vecs.height_to_first_txinindex
|
||||
.push_if_needed(height, self.txinindex)?;
|
||||
vecs.height_to_first_txoutindex
|
||||
.push_if_needed(height, self.txoutindex)?;
|
||||
vecs.height_to_first_addressindex
|
||||
.push_if_needed(height, self.addressindex)?;
|
||||
vecs.height_to_first_emptyindex
|
||||
.push_if_needed(height, self.emptyindex)?;
|
||||
vecs.height_to_first_multisigindex
|
||||
.push_if_needed(height, self.multisigindex)?;
|
||||
vecs.height_to_first_inputindex
|
||||
.push_if_needed(height, self.inputindex)?;
|
||||
vecs.height_to_first_outputindex
|
||||
.push_if_needed(height, self.outputindex)?;
|
||||
vecs.height_to_first_emptyoutputindex
|
||||
.push_if_needed(height, self.emptyoutputindex)?;
|
||||
vecs.height_to_first_p2msindex
|
||||
.push_if_needed(height, self.p2msindex)?;
|
||||
vecs.height_to_first_opreturnindex
|
||||
.push_if_needed(height, self.opreturnindex)?;
|
||||
vecs.height_to_first_pushonlyindex
|
||||
.push_if_needed(height, self.pushonlyindex)?;
|
||||
vecs.height_to_first_unknownindex
|
||||
.push_if_needed(height, self.unknownindex)?;
|
||||
vecs.height_to_first_p2aindex
|
||||
.push_if_needed(height, self.p2aindex)?;
|
||||
vecs.height_to_first_unknownoutputindex
|
||||
.push_if_needed(height, self.unknownoutputindex)?;
|
||||
vecs.height_to_first_p2pk33index
|
||||
.push_if_needed(height, self.p2pk33index)?;
|
||||
vecs.height_to_first_p2pk65index
|
||||
@@ -106,100 +120,90 @@ impl TryFrom<(&mut Vecs, &Stores, &Client)> for Indexes {
|
||||
.unwrap_or(starting_height);
|
||||
|
||||
Ok(Self {
|
||||
addressindex: *starting_index(
|
||||
&vecs.height_to_first_addressindex,
|
||||
&vecs.addressindex_to_height,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
emptyindex: *starting_index(
|
||||
&vecs.height_to_first_emptyindex,
|
||||
&vecs.emptyindex_to_height,
|
||||
emptyoutputindex: *starting_index(
|
||||
&vecs.height_to_first_emptyoutputindex,
|
||||
&vecs.emptyoutputindex_to_txindex,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
height,
|
||||
multisigindex: *starting_index(
|
||||
&vecs.height_to_first_multisigindex,
|
||||
&vecs.multisigindex_to_height,
|
||||
p2msindex: *starting_index(
|
||||
&vecs.height_to_first_p2msindex,
|
||||
&vecs.p2msindex_to_txindex,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
opreturnindex: *starting_index(
|
||||
&vecs.height_to_first_opreturnindex,
|
||||
&vecs.opreturnindex_to_height,
|
||||
&vecs.opreturnindex_to_txindex,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
p2pk33index: *starting_index(
|
||||
&vecs.height_to_first_p2pk33index,
|
||||
&vecs.p2pk33index_to_height,
|
||||
&vecs.p2pk33index_to_p2pk33bytes,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
p2pk65index: *starting_index(
|
||||
&vecs.height_to_first_p2pk65index,
|
||||
&vecs.p2pk65index_to_height,
|
||||
&vecs.p2pk65index_to_p2pk65bytes,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
p2pkhindex: *starting_index(
|
||||
&vecs.height_to_first_p2pkhindex,
|
||||
&vecs.p2pkhindex_to_height,
|
||||
&vecs.p2pkhindex_to_p2pkhbytes,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
p2shindex: *starting_index(
|
||||
&vecs.height_to_first_p2shindex,
|
||||
&vecs.p2shindex_to_height,
|
||||
&vecs.p2shindex_to_p2shbytes,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
p2trindex: *starting_index(
|
||||
&vecs.height_to_first_p2trindex,
|
||||
&vecs.p2trindex_to_height,
|
||||
&vecs.p2trindex_to_p2trbytes,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
p2wpkhindex: *starting_index(
|
||||
&vecs.height_to_first_p2wpkhindex,
|
||||
&vecs.p2wpkhindex_to_height,
|
||||
&vecs.p2wpkhindex_to_p2wpkhbytes,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
p2wshindex: *starting_index(
|
||||
&vecs.height_to_first_p2wshindex,
|
||||
&vecs.p2wshindex_to_height,
|
||||
&vecs.p2wshindex_to_p2wshbytes,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
pushonlyindex: *starting_index(
|
||||
&vecs.height_to_first_pushonlyindex,
|
||||
&vecs.pushonlyindex_to_height,
|
||||
p2aindex: *starting_index(
|
||||
&vecs.height_to_first_p2aindex,
|
||||
&vecs.p2aindex_to_p2abytes,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
txindex: *starting_index(
|
||||
&vecs.height_to_first_txindex,
|
||||
&vecs.txindex_to_height,
|
||||
txindex: *starting_index(&vecs.height_to_first_txindex, &vecs.txindex_to_txid, height)?
|
||||
.context("")?,
|
||||
inputindex: *starting_index(
|
||||
&vecs.height_to_first_inputindex,
|
||||
&vecs.inputindex_to_outputindex,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
txinindex: *starting_index(
|
||||
&vecs.height_to_first_txinindex,
|
||||
&vecs.txinindex_to_height,
|
||||
outputindex: *starting_index(
|
||||
&vecs.height_to_first_outputindex,
|
||||
&vecs.outputindex_to_value,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
txoutindex: *starting_index(
|
||||
&vecs.height_to_first_txoutindex,
|
||||
&vecs.txoutindex_to_height,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
unknownindex: *starting_index(
|
||||
&vecs.height_to_first_unknownindex,
|
||||
&vecs.unknownindex_to_height,
|
||||
unknownoutputindex: *starting_index(
|
||||
&vecs.height_to_first_unknownoutputindex,
|
||||
&vecs.unknownoutputindex_to_txindex,
|
||||
height,
|
||||
)?
|
||||
.context("")?,
|
||||
@@ -207,19 +211,20 @@ impl TryFrom<(&mut Vecs, &Stores, &Client)> for Indexes {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn starting_index<'a, I>(
|
||||
pub fn starting_index<'a, I, T>(
|
||||
height_to_index: &'a IndexedVec<Height, I>,
|
||||
index_to_height: &'a IndexedVec<I, Height>,
|
||||
index_to_else: &'a IndexedVec<I, T>,
|
||||
starting_height: Height,
|
||||
) -> Result<Option<Value<'a, I>>>
|
||||
where
|
||||
I: StoredType + StoredIndex + From<usize>,
|
||||
T: StoredType,
|
||||
{
|
||||
if height_to_index
|
||||
.height()
|
||||
.is_ok_and(|h| h + 1_u32 == starting_height)
|
||||
{
|
||||
Ok(Some(Value::Owned(I::from(index_to_height.len()))))
|
||||
Ok(Some(Value::Owned(I::from(index_to_else.len()))))
|
||||
} else {
|
||||
height_to_index.get(starting_height)
|
||||
}
|
||||
|
||||
+151
-188
@@ -11,8 +11,8 @@ use std::{
|
||||
};
|
||||
|
||||
use brk_core::{
|
||||
AddressHash, Addressbytes, Addressindex, Addresstype, BlockHash, BlockHashPrefix, Height, Sats,
|
||||
Timestamp, Txid, TxidPrefix, Txindex, Txinindex, Txoutindex, Vin, Vout, setrlimit,
|
||||
AddressBytes, AddressBytesHash, BlockHash, BlockHashPrefix, Height, InputIndex, OutputIndex,
|
||||
OutputType, OutputTypeIndex, Sats, Timestamp, TxIndex, Txid, TxidPrefix, Vin, Vout, setrlimit,
|
||||
};
|
||||
pub use brk_parser::*;
|
||||
|
||||
@@ -20,7 +20,8 @@ use bitcoin::{Transaction, TxIn, TxOut};
|
||||
use brk_exit::Exit;
|
||||
use brk_vec::Compressed;
|
||||
use color_eyre::eyre::{ContextCompat, eyre};
|
||||
use log::info;
|
||||
use fjall::TransactionalKeyspace;
|
||||
use log::{error, info};
|
||||
use rayon::prelude::*;
|
||||
mod indexes;
|
||||
mod stores;
|
||||
@@ -31,7 +32,7 @@ pub use stores::*;
|
||||
pub use vecs::*;
|
||||
|
||||
const SNAPSHOT_BLOCK_RANGE: usize = 1000;
|
||||
const COLLISIONS_CHECKED_UP_TO: u32 = 890_000;
|
||||
const COLLISIONS_CHECKED_UP_TO: u32 = 893_000;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Indexer {
|
||||
@@ -44,13 +45,13 @@ pub struct Indexer {
|
||||
|
||||
impl Indexer {
|
||||
pub fn new(
|
||||
indexes_dir: PathBuf,
|
||||
outputs_dir: &Path,
|
||||
compressed: bool,
|
||||
check_collisions: bool,
|
||||
) -> color_eyre::Result<Self> {
|
||||
setrlimit()?;
|
||||
Ok(Self {
|
||||
path: indexes_dir,
|
||||
path: outputs_dir.to_owned(),
|
||||
vecs: None,
|
||||
stores: None,
|
||||
compressed: Compressed::from(compressed),
|
||||
@@ -59,14 +60,17 @@ impl Indexer {
|
||||
}
|
||||
|
||||
pub fn import_vecs(&mut self) -> color_eyre::Result<()> {
|
||||
self.vecs = Some(Vecs::import(&self.path.join("vecs"), self.compressed)?);
|
||||
self.vecs = Some(Vecs::forced_import(
|
||||
&self.path.join("vecs/indexed"),
|
||||
self.compressed,
|
||||
)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Do NOT import multiple times are things will break !!!
|
||||
/// Clone struct instead
|
||||
pub fn import_stores(&mut self) -> color_eyre::Result<()> {
|
||||
self.stores = Some(Stores::import(&self.path.join("stores"))?);
|
||||
self.stores = Some(Stores::forced_import(&self.path.join("stores"))?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -146,23 +150,23 @@ impl Indexer {
|
||||
let blockhash_prefix = BlockHashPrefix::from(&blockhash);
|
||||
|
||||
if stores
|
||||
.blockhash_prefix_to_height
|
||||
.blockhashprefix_to_height
|
||||
.get(&blockhash_prefix)?
|
||||
.is_some_and(|prev_height| *prev_height != height)
|
||||
{
|
||||
dbg!(blockhash);
|
||||
error!("BlockHash: {blockhash}");
|
||||
return Err(eyre!("Collision, expect prefix to need be set yet"));
|
||||
}
|
||||
|
||||
idxs.push_if_needed(vecs)?;
|
||||
|
||||
stores
|
||||
.blockhash_prefix_to_height
|
||||
.blockhashprefix_to_height
|
||||
.insert_if_needed(blockhash_prefix, height, height);
|
||||
|
||||
vecs.height_to_blockhash.push_if_needed(height, blockhash)?;
|
||||
vecs.height_to_difficulty
|
||||
.push_if_needed(height, block.header.difficulty_float())?;
|
||||
.push_if_needed(height, block.header.difficulty_float().into())?;
|
||||
vecs.height_to_timestamp
|
||||
.push_if_needed(height, Timestamp::from(block.header.time))?;
|
||||
vecs.height_to_total_size.push_if_needed(height, block.total_size().into())?;
|
||||
@@ -176,7 +180,7 @@ impl Indexer {
|
||||
tx.input
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(move |(vin, txin)| (Txindex::from(index), Vin::from(vin), txin, tx))
|
||||
.map(move |(vin, txin)| (TxIndex::from(index), Vin::from(vin), txin, tx))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -188,7 +192,7 @@ impl Indexer {
|
||||
tx.output
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(move |(vout, txout)| (Txindex::from(index), Vout::from(vout), txout, tx))
|
||||
.map(move |(vout, txout)| (TxIndex::from(index), Vout::from(vout), txout, tx))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -199,7 +203,7 @@ impl Indexer {
|
||||
let (
|
||||
txid_prefix_to_txid_and_block_txindex_and_prev_txindex_join_handle,
|
||||
input_source_vec_handle,
|
||||
txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt_handle,
|
||||
outputindex_to_txout_outputtype_addressbytes_res_addressindex_opt_handle,
|
||||
) = thread::scope(|scope| {
|
||||
let txid_prefix_to_txid_and_block_txindex_and_prev_txindex_handle =
|
||||
scope.spawn(|| -> color_eyre::Result<_> {
|
||||
@@ -213,14 +217,14 @@ impl Indexer {
|
||||
let txid_prefix = TxidPrefix::from(&txid);
|
||||
|
||||
let prev_txindex_opt =
|
||||
if check_collisions && stores.txid_prefix_to_txindex.needs(height) {
|
||||
if check_collisions && stores.txidprefix_to_txindex.needs(height) {
|
||||
// Should only find collisions for two txids (duplicates), see below
|
||||
stores.txid_prefix_to_txindex.get(&txid_prefix)?.map(|v| *v)
|
||||
stores.txidprefix_to_txindex.get(&txid_prefix)?.map(|v| *v)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok((txid_prefix, (tx, txid, Txindex::from(index), prev_txindex_opt)))
|
||||
Ok((txid_prefix, (tx, txid, TxIndex::from(index), prev_txindex_opt)))
|
||||
})
|
||||
.try_fold(BTreeMap::new, |mut map, tuple| {
|
||||
let (key, value) = tuple?;
|
||||
@@ -242,19 +246,19 @@ impl Indexer {
|
||||
inputs
|
||||
.into_par_iter()
|
||||
.enumerate()
|
||||
.map(|(block_txinindex, (block_txindex, vin, txin, tx))| -> color_eyre::Result<(Txinindex, InputSource)> {
|
||||
.map(|(block_inputindex, (block_txindex, vin, txin, tx))| -> color_eyre::Result<(InputIndex, InputSource)> {
|
||||
let txindex = idxs.txindex + block_txindex;
|
||||
let txinindex = idxs.txinindex + Txinindex::from(block_txinindex);
|
||||
let inputindex = idxs.inputindex + InputIndex::from(block_inputindex);
|
||||
|
||||
let outpoint = txin.previous_output;
|
||||
let txid = Txid::from(outpoint.txid);
|
||||
|
||||
if tx.is_coinbase() {
|
||||
return Ok((txinindex, InputSource::SameBlock((tx, txindex, txin, vin))));
|
||||
return Ok((inputindex, InputSource::SameBlock((tx, txindex, txin, vin))));
|
||||
}
|
||||
|
||||
let prev_txindex = if let Some(txindex) = stores
|
||||
.txid_prefix_to_txindex
|
||||
.txidprefix_to_txindex
|
||||
.get(&TxidPrefix::from(&txid))?
|
||||
.map(|v| *v)
|
||||
.and_then(|txindex| {
|
||||
@@ -264,24 +268,24 @@ impl Indexer {
|
||||
txindex
|
||||
} else {
|
||||
// dbg!(indexes.txindex + block_txindex, txindex, txin, vin);
|
||||
return Ok((txinindex, InputSource::SameBlock((tx, txindex, txin, vin))));
|
||||
return Ok((inputindex, InputSource::SameBlock((tx, txindex, txin, vin))));
|
||||
};
|
||||
|
||||
let vout = Vout::from(outpoint.vout);
|
||||
|
||||
let txoutindex = *vecs
|
||||
.txindex_to_first_txoutindex
|
||||
let outputindex = *vecs
|
||||
.txindex_to_first_outputindex
|
||||
.get(prev_txindex)?
|
||||
.context("Expect txoutindex to not be none")
|
||||
.context("Expect outputindex to not be none")
|
||||
.inspect_err(|_| {
|
||||
dbg!(outpoint.txid, prev_txindex, vout);
|
||||
})?
|
||||
+ vout;
|
||||
|
||||
Ok((txinindex, InputSource::PreviousBlock((
|
||||
Ok((inputindex, InputSource::PreviousBlock((
|
||||
vin,
|
||||
txindex,
|
||||
txoutindex,
|
||||
outputindex,
|
||||
))))
|
||||
})
|
||||
.try_fold(BTreeMap::new, |mut map, tuple| -> color_eyre::Result<_> {
|
||||
@@ -300,71 +304,58 @@ impl Indexer {
|
||||
})
|
||||
});
|
||||
|
||||
let txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt_handle = scope.spawn(|| {
|
||||
let outputindex_to_txout_outputtype_addressbytes_res_addressindex_opt_handle = scope.spawn(|| {
|
||||
outputs
|
||||
.into_par_iter()
|
||||
.enumerate()
|
||||
.map(
|
||||
#[allow(clippy::type_complexity)]
|
||||
|(block_txoutindex, (block_txindex, vout, txout, tx))| -> color_eyre::Result<(
|
||||
Txoutindex,
|
||||
|(block_outputindex, (block_txindex, vout, txout, tx))| -> color_eyre::Result<(
|
||||
OutputIndex,
|
||||
(
|
||||
&TxOut,
|
||||
Txindex,
|
||||
TxIndex,
|
||||
Vout,
|
||||
Addresstype,
|
||||
brk_core::Result<Addressbytes>,
|
||||
Option<Addressindex>,
|
||||
OutputType,
|
||||
brk_core::Result<AddressBytes>,
|
||||
Option<OutputTypeIndex>,
|
||||
&Transaction,
|
||||
),
|
||||
)> {
|
||||
let txindex = idxs.txindex + block_txindex;
|
||||
let txoutindex = idxs.txoutindex + Txoutindex::from(block_txoutindex);
|
||||
let outputindex = idxs.outputindex + OutputIndex::from(block_outputindex);
|
||||
|
||||
let script = &txout.script_pubkey;
|
||||
|
||||
let addresstype = Addresstype::from(script);
|
||||
let outputtype = OutputType::from(script);
|
||||
|
||||
let addressbytes_res =
|
||||
Addressbytes::try_from((script, addresstype)).inspect_err(|_| {
|
||||
let address_bytes_res =
|
||||
AddressBytes::try_from((script, outputtype)).inspect_err(|_| {
|
||||
// dbg!(&txout, height, txi, &tx.compute_txid());
|
||||
});
|
||||
|
||||
let addressindex_opt = addressbytes_res.as_ref().ok().and_then(|addressbytes| {
|
||||
let outputtypeindex_opt = address_bytes_res.as_ref().ok().and_then(|addressbytes| {
|
||||
stores
|
||||
.addresshash_to_addressindex
|
||||
.get(&AddressHash::from((addressbytes, addresstype)))
|
||||
.addressbyteshash_to_outputtypeindex
|
||||
.get(&AddressBytesHash::from((addressbytes, outputtype)))
|
||||
.unwrap()
|
||||
.map(|v| *v)
|
||||
// Checking if not in the future
|
||||
.and_then(|addressindex_local| {
|
||||
(addressindex_local < idxs.addressindex).then_some(addressindex_local)
|
||||
.and_then(|outputtypeindex_local| {
|
||||
(outputtypeindex_local < idxs.outputtypeindex(outputtype)).then_some(outputtypeindex_local)
|
||||
})
|
||||
});
|
||||
|
||||
if let Some(Some(addressindex)) = check_collisions.then_some(addressindex_opt) {
|
||||
let addressbytes = addressbytes_res.as_ref().unwrap();
|
||||
|
||||
let prev_addresstype = *vecs
|
||||
.addressindex_to_addresstype
|
||||
.get(addressindex)?
|
||||
.context("Expect to have address type")?;
|
||||
|
||||
let addresstypeindex = *vecs
|
||||
.addressindex_to_addresstypeindex
|
||||
.get(addressindex)?
|
||||
.context("Expect to have address type index")?;
|
||||
if let Some(Some(outputtypeindex)) = check_collisions.then_some(outputtypeindex_opt) {
|
||||
let addressbytes = address_bytes_res.as_ref().unwrap();
|
||||
|
||||
let prev_addressbytes_opt =
|
||||
vecs.get_addressbytes(prev_addresstype, addresstypeindex)?;
|
||||
|
||||
vecs.get_addressbytes(outputtype, outputtypeindex)?;
|
||||
let prev_addressbytes =
|
||||
prev_addressbytes_opt.as_ref().context("Expect to have addressbytes")?;
|
||||
|
||||
if (vecs.addressindex_to_addresstype.hasnt(addressindex)?
|
||||
&& addresstype != prev_addresstype)
|
||||
|| (stores.addresshash_to_addressindex.needs(height)
|
||||
&& prev_addressbytes != addressbytes)
|
||||
if stores.addressbyteshash_to_outputtypeindex.needs(height)
|
||||
&& prev_addressbytes != addressbytes
|
||||
{
|
||||
let txid = tx.compute_txid();
|
||||
dbg!(
|
||||
@@ -372,30 +363,28 @@ impl Indexer {
|
||||
txid,
|
||||
vout,
|
||||
block_txindex,
|
||||
addresstype,
|
||||
prev_addresstype,
|
||||
outputtype,
|
||||
prev_addressbytes,
|
||||
addressbytes,
|
||||
idxs.addressindex,
|
||||
addressindex,
|
||||
addresstypeindex,
|
||||
&idxs,
|
||||
outputtypeindex,
|
||||
outputtypeindex,
|
||||
txout,
|
||||
AddressHash::from((addressbytes, addresstype)),
|
||||
AddressHash::from((prev_addressbytes, prev_addresstype))
|
||||
AddressBytesHash::from((addressbytes, outputtype)),
|
||||
);
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
Ok((
|
||||
txoutindex,
|
||||
outputindex,
|
||||
(
|
||||
txout,
|
||||
txindex,
|
||||
vout,
|
||||
addresstype,
|
||||
addressbytes_res,
|
||||
addressindex_opt,
|
||||
outputtype,
|
||||
address_bytes_res,
|
||||
outputtypeindex_opt,
|
||||
tx,
|
||||
),
|
||||
))
|
||||
@@ -420,7 +409,7 @@ impl Indexer {
|
||||
(
|
||||
txid_prefix_to_txid_and_block_txindex_and_prev_txindex_handle.join(),
|
||||
input_source_vec_handle.join(),
|
||||
txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt_handle.join(),
|
||||
outputindex_to_txout_outputtype_addressbytes_res_addressindex_opt_handle.join(),
|
||||
)
|
||||
});
|
||||
|
||||
@@ -435,158 +424,139 @@ impl Indexer {
|
||||
.ok()
|
||||
.context("Export input_source_vec_handle to join")??;
|
||||
|
||||
let txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt =
|
||||
txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt_handle
|
||||
let outputindex_to_txout_outputtype_addressbytes_res_addressindex_opt =
|
||||
outputindex_to_txout_outputtype_addressbytes_res_addressindex_opt_handle
|
||||
.ok()
|
||||
.context(
|
||||
"Expect txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt_handle to join",
|
||||
"Expect outputindex_to_txout_outputtype_addressbytes_res_addressindex_opt_handle to join",
|
||||
)??;
|
||||
|
||||
let mut new_txindexvout_to_txoutindex: BTreeMap<
|
||||
(Txindex, Vout),
|
||||
Txoutindex,
|
||||
let mut new_txindexvout_to_outputindex: BTreeMap<
|
||||
(TxIndex, Vout),
|
||||
OutputIndex,
|
||||
> = BTreeMap::new();
|
||||
|
||||
let mut already_added_addresshash: BTreeMap<AddressHash, Addressindex> = BTreeMap::new();
|
||||
let mut already_added_addressbyteshash: BTreeMap<AddressBytesHash, OutputTypeIndex> = BTreeMap::new();
|
||||
|
||||
txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt
|
||||
outputindex_to_txout_outputtype_addressbytes_res_addressindex_opt
|
||||
.into_iter()
|
||||
.try_for_each(
|
||||
|(
|
||||
txoutindex,
|
||||
(txout, txindex, vout, addresstype, addressbytes_res, addressindex_opt, _tx),
|
||||
outputindex,
|
||||
(txout, txindex, vout, outputtype, addressbytes_res, outputtypeindex_opt, _tx),
|
||||
)|
|
||||
-> color_eyre::Result<()> {
|
||||
let sats = Sats::from(txout.value);
|
||||
|
||||
if vout.is_zero() {
|
||||
vecs.txindex_to_first_txoutindex.push_if_needed(txindex, txoutindex)?;
|
||||
vecs.txindex_to_first_outputindex.push_if_needed(txindex, outputindex)?;
|
||||
}
|
||||
|
||||
vecs.txoutindex_to_value.push_if_needed(txoutindex, sats)?;
|
||||
vecs.outputindex_to_value.push_if_needed(outputindex, sats)?;
|
||||
|
||||
vecs.txoutindex_to_height
|
||||
.push_if_needed(txoutindex, height)?;
|
||||
vecs.outputindex_to_outputtype
|
||||
.push_if_needed(outputindex, outputtype)?;
|
||||
|
||||
let mut addressindex = idxs.addressindex;
|
||||
let mut addressbyteshash = None;
|
||||
|
||||
let mut addresshash = None;
|
||||
let outputtypeindex;
|
||||
|
||||
if let Some(addressindex_local) = addressindex_opt.or_else(|| {
|
||||
if let Some(outputtypeindex_local) = outputtypeindex_opt.or_else(|| {
|
||||
addressbytes_res.as_ref().ok().and_then(|addressbytes| {
|
||||
// Check if address was first seen before in this iterator
|
||||
// Example: https://mempool.space/address/046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0c
|
||||
addresshash.replace(AddressHash::from((addressbytes, addresstype)));
|
||||
already_added_addresshash
|
||||
.get(addresshash.as_ref().unwrap())
|
||||
addressbyteshash.replace(AddressBytesHash::from((addressbytes, outputtype)));
|
||||
already_added_addressbyteshash
|
||||
.get(addressbyteshash.as_ref().unwrap())
|
||||
.cloned()
|
||||
})
|
||||
}) {
|
||||
addressindex = addressindex_local;
|
||||
outputtypeindex = outputtypeindex_local;
|
||||
} else {
|
||||
idxs.addressindex.increment();
|
||||
|
||||
let addresstypeindex = match addresstype {
|
||||
Addresstype::Empty => {
|
||||
vecs.emptyindex_to_height
|
||||
.push_if_needed(idxs.emptyindex, height)?;
|
||||
idxs.emptyindex.copy_then_increment()
|
||||
},
|
||||
Addresstype::Multisig => {
|
||||
vecs.multisigindex_to_height.push_if_needed(idxs.multisigindex, height)?;
|
||||
idxs.multisigindex.copy_then_increment()
|
||||
},
|
||||
Addresstype::OpReturn => {
|
||||
vecs.opreturnindex_to_height.push_if_needed(idxs.opreturnindex, height)?;
|
||||
idxs.opreturnindex.copy_then_increment()
|
||||
},
|
||||
Addresstype::PushOnly => {
|
||||
vecs.pushonlyindex_to_height.push_if_needed(idxs.pushonlyindex, height)?;
|
||||
idxs.pushonlyindex.copy_then_increment()
|
||||
},
|
||||
Addresstype::Unknown => {
|
||||
vecs.unknownindex_to_height.push_if_needed(idxs.unknownindex, height)?;
|
||||
idxs.unknownindex.copy_then_increment()
|
||||
},
|
||||
Addresstype::P2PK65 => {
|
||||
vecs.p2pk65index_to_height.push_if_needed(idxs.p2pk65index, height)?;
|
||||
outputtypeindex = match outputtype {
|
||||
OutputType::P2PK65 => {
|
||||
idxs.p2pk65index.copy_then_increment()
|
||||
},
|
||||
Addresstype::P2PK33 => {
|
||||
vecs.p2pk33index_to_height.push_if_needed(idxs.p2pk33index, height)?;
|
||||
OutputType::P2PK33 => {
|
||||
idxs.p2pk33index.copy_then_increment()
|
||||
},
|
||||
Addresstype::P2PKH => {
|
||||
vecs.p2pkhindex_to_height.push_if_needed(idxs.p2pkhindex, height)?;
|
||||
OutputType::P2PKH => {
|
||||
idxs.p2pkhindex.copy_then_increment()
|
||||
},
|
||||
Addresstype::P2SH => {
|
||||
vecs.p2shindex_to_height.push_if_needed(idxs.p2shindex, height)?;
|
||||
OutputType::P2MS => {
|
||||
vecs.p2msindex_to_txindex.push_if_needed(idxs.p2msindex, txindex)?;
|
||||
idxs.p2msindex.copy_then_increment()
|
||||
},
|
||||
OutputType::P2SH => {
|
||||
idxs.p2shindex.copy_then_increment()
|
||||
},
|
||||
Addresstype::P2WPKH => {
|
||||
vecs.p2wpkhindex_to_height.push_if_needed(idxs.p2wpkhindex, height)?;
|
||||
OutputType::OpReturn => {
|
||||
vecs.opreturnindex_to_txindex.push_if_needed(idxs.opreturnindex, txindex)?;
|
||||
idxs.opreturnindex.copy_then_increment()
|
||||
},
|
||||
OutputType::P2WPKH => {
|
||||
idxs.p2wpkhindex.copy_then_increment()
|
||||
},
|
||||
Addresstype::P2WSH => {
|
||||
vecs.p2wshindex_to_height.push_if_needed(idxs.p2wshindex, height)?;
|
||||
OutputType::P2WSH => {
|
||||
idxs.p2wshindex.copy_then_increment()
|
||||
},
|
||||
Addresstype::P2TR => {
|
||||
vecs.p2trindex_to_height.push_if_needed(idxs.p2trindex, height)?;
|
||||
OutputType::P2TR => {
|
||||
idxs.p2trindex.copy_then_increment()
|
||||
},
|
||||
OutputType::P2A => {
|
||||
idxs.p2aindex.copy_then_increment()
|
||||
},
|
||||
OutputType::Empty => {
|
||||
vecs.emptyoutputindex_to_txindex
|
||||
.push_if_needed(idxs.emptyoutputindex, txindex)?;
|
||||
idxs.emptyoutputindex.copy_then_increment()
|
||||
},
|
||||
OutputType::Unknown => {
|
||||
vecs.unknownoutputindex_to_txindex.push_if_needed(idxs.unknownoutputindex, txindex)?;
|
||||
idxs.unknownoutputindex.copy_then_increment()
|
||||
},
|
||||
};
|
||||
|
||||
vecs.addressindex_to_addresstype
|
||||
.push_if_needed(addressindex, addresstype)?;
|
||||
|
||||
vecs.addressindex_to_addresstypeindex
|
||||
.push_if_needed(addressindex, addresstypeindex)?;
|
||||
|
||||
vecs.addressindex_to_height
|
||||
.push_if_needed(addressindex, height)?;
|
||||
|
||||
if let Ok(addressbytes) = addressbytes_res {
|
||||
let addresshash = addresshash.unwrap();
|
||||
let addressbyteshash = addressbyteshash.unwrap();
|
||||
|
||||
already_added_addresshash
|
||||
.insert(addresshash, addressindex);
|
||||
already_added_addressbyteshash
|
||||
.insert(addressbyteshash, outputtypeindex);
|
||||
|
||||
stores.addresshash_to_addressindex.insert_if_needed(
|
||||
addresshash,
|
||||
addressindex,
|
||||
stores.addressbyteshash_to_outputtypeindex.insert_if_needed(
|
||||
addressbyteshash,
|
||||
outputtypeindex,
|
||||
height,
|
||||
);
|
||||
|
||||
vecs.push_addressbytes_if_needed(addresstypeindex, addressbytes)?;
|
||||
vecs.push_bytes_if_needed(outputtypeindex, addressbytes)?;
|
||||
}
|
||||
}
|
||||
|
||||
new_txindexvout_to_txoutindex
|
||||
.insert((txindex, vout), txoutindex);
|
||||
vecs.outputindex_to_outputtypeindex
|
||||
.push_if_needed(outputindex, outputtypeindex)?;
|
||||
|
||||
vecs.txoutindex_to_addressindex
|
||||
.push_if_needed(txoutindex, addressindex)?;
|
||||
new_txindexvout_to_outputindex
|
||||
.insert((txindex, vout), outputindex);
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
drop(already_added_addresshash);
|
||||
drop(already_added_addressbyteshash);
|
||||
|
||||
input_source_vec
|
||||
.into_iter()
|
||||
.map(
|
||||
#[allow(clippy::type_complexity)]
|
||||
|(txinindex, input_source)| -> color_eyre::Result<(
|
||||
Txinindex, Vin, Txindex, Txoutindex
|
||||
|(inputindex, input_source)| -> color_eyre::Result<(
|
||||
InputIndex, Vin, TxIndex, OutputIndex
|
||||
)> {
|
||||
match input_source {
|
||||
InputSource::PreviousBlock((vin, txindex, txoutindex)) => Ok((txinindex, vin, txindex, txoutindex)),
|
||||
InputSource::PreviousBlock((vin, txindex, outputindex)) => Ok((inputindex, vin, txindex, outputindex)),
|
||||
InputSource::SameBlock((tx, txindex, txin, vin)) => {
|
||||
if tx.is_coinbase() {
|
||||
return Ok((txinindex, vin, txindex, Txoutindex::COINBASE));
|
||||
return Ok((inputindex, vin, txindex, OutputIndex::COINBASE));
|
||||
}
|
||||
|
||||
let outpoint = txin.previous_output;
|
||||
@@ -602,37 +572,33 @@ impl Indexer {
|
||||
.2;
|
||||
let prev_txindex = idxs.txindex + block_txindex;
|
||||
|
||||
let prev_txoutindex = new_txindexvout_to_txoutindex
|
||||
let prev_outputindex = new_txindexvout_to_outputindex
|
||||
.remove(&(prev_txindex, vout))
|
||||
.context("should have found addressindex from same block")
|
||||
.inspect_err(|_| {
|
||||
dbg!(&new_txindexvout_to_txoutindex, txin, prev_txindex, vout, txid);
|
||||
dbg!(&new_txindexvout_to_outputindex, txin, prev_txindex, vout, txid);
|
||||
})?;
|
||||
|
||||
Ok((txinindex, vin, txindex, prev_txoutindex))
|
||||
Ok((inputindex, vin, txindex, prev_outputindex))
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
.try_for_each(|res| -> color_eyre::Result<()> {
|
||||
let (txinindex, vin, txindex, txoutindex) = res?;
|
||||
let (inputindex, vin, txindex, outputindex) = res?;
|
||||
|
||||
if vin.is_zero() {
|
||||
vecs.txindex_to_first_txinindex.push_if_needed(txindex, txinindex)?;
|
||||
vecs.txindex_to_first_inputindex.push_if_needed(txindex, inputindex)?;
|
||||
}
|
||||
|
||||
vecs.txinindex_to_txoutindex.push_if_needed(txinindex, txoutindex)?;
|
||||
|
||||
vecs.txinindex_to_height
|
||||
.push_if_needed(txinindex, height)?;
|
||||
|
||||
vecs.inputindex_to_outputindex.push_if_needed(inputindex, outputindex)?;
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
drop(new_txindexvout_to_txoutindex);
|
||||
drop(new_txindexvout_to_outputindex);
|
||||
|
||||
let mut txindex_to_tx_and_txid: BTreeMap<Txindex, (&Transaction, Txid)> = BTreeMap::default();
|
||||
let mut txindex_to_tx_and_txid: BTreeMap<TxIndex, (&Transaction, Txid)> = BTreeMap::default();
|
||||
|
||||
txid_prefix_to_txid_and_block_txindex_and_prev_txindex
|
||||
.into_iter()
|
||||
@@ -645,7 +611,7 @@ impl Indexer {
|
||||
match prev_txindex_opt {
|
||||
None => {
|
||||
stores
|
||||
.txid_prefix_to_txindex
|
||||
.txidprefix_to_txindex
|
||||
.insert_if_needed(txid_prefix, txindex, height);
|
||||
}
|
||||
Some(prev_txindex) => {
|
||||
@@ -655,7 +621,7 @@ impl Indexer {
|
||||
}
|
||||
|
||||
if !check_collisions {
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let len = vecs.txindex_to_txid.len();
|
||||
@@ -686,9 +652,7 @@ impl Indexer {
|
||||
let is_dup = only_known_dup_txids.contains(prev_txid);
|
||||
|
||||
if !is_dup {
|
||||
let prev_height =
|
||||
vecs.txindex_to_height.get(prev_txindex)?.expect("To have height");
|
||||
dbg!(height, txindex, prev_height, prev_txid, prev_txindex);
|
||||
dbg!(height, txindex, prev_txid, prev_txindex);
|
||||
return Err(eyre!("Expect none"));
|
||||
}
|
||||
}
|
||||
@@ -703,17 +667,16 @@ impl Indexer {
|
||||
.try_for_each(|(txindex, (tx, txid))| -> color_eyre::Result<()> {
|
||||
vecs.txindex_to_txversion.push_if_needed(txindex, tx.version.into())?;
|
||||
vecs.txindex_to_txid.push_if_needed(txindex, txid)?;
|
||||
vecs.txindex_to_height.push_if_needed(txindex, height)?;
|
||||
vecs.txindex_to_locktime.push_if_needed(txindex, tx.lock_time.into())?;
|
||||
vecs.txindex_to_base_size.push_if_needed(txindex, tx.base_size())?;
|
||||
vecs.txindex_to_total_size.push_if_needed(txindex, tx.total_size())?;
|
||||
vecs.txindex_to_rawlocktime.push_if_needed(txindex, tx.lock_time.into())?;
|
||||
vecs.txindex_to_base_size.push_if_needed(txindex, tx.base_size().into())?;
|
||||
vecs.txindex_to_total_size.push_if_needed(txindex, tx.total_size().into())?;
|
||||
vecs.txindex_to_is_explicitly_rbf.push_if_needed(txindex, tx.is_explicitly_rbf())?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
idxs.txindex += Txindex::from(tx_len);
|
||||
idxs.txinindex += Txinindex::from(inputs_len);
|
||||
idxs.txoutindex += Txoutindex::from(outputs_len);
|
||||
idxs.txindex += TxIndex::from(tx_len);
|
||||
idxs.inputindex += InputIndex::from(inputs_len);
|
||||
idxs.outputindex += OutputIndex::from(outputs_len);
|
||||
|
||||
export_if_needed(stores, vecs, height, false, exit)?;
|
||||
|
||||
@@ -728,10 +691,6 @@ impl Indexer {
|
||||
Ok(starting_indexes)
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> &Vecs {
|
||||
self.vecs.as_ref().unwrap()
|
||||
}
|
||||
@@ -747,10 +706,14 @@ impl Indexer {
|
||||
pub fn mut_stores(&mut self) -> &mut Stores {
|
||||
self.stores.as_mut().unwrap()
|
||||
}
|
||||
|
||||
pub fn keyspace(&self) -> &TransactionalKeyspace {
|
||||
&self.stores().keyspace
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum InputSource<'a> {
|
||||
PreviousBlock((Vin, Txindex, Txoutindex)),
|
||||
SameBlock((&'a Transaction, Txindex, &'a TxIn, Vin)),
|
||||
PreviousBlock((Vin, TxIndex, OutputIndex)),
|
||||
SameBlock((&'a Transaction, TxIndex, &'a TxIn, Vin)),
|
||||
}
|
||||
|
||||
@@ -19,8 +19,9 @@ use super::StoreMeta;
|
||||
|
||||
pub struct Store<Key, Value> {
|
||||
meta: StoreMeta,
|
||||
name: String,
|
||||
keyspace: TransactionalKeyspace,
|
||||
part: TransactionalPartitionHandle,
|
||||
partition: TransactionalPartitionHandle,
|
||||
rtx: ReadTransaction,
|
||||
puts: BTreeMap<Key, Value>,
|
||||
dels: BTreeSet<Key>,
|
||||
@@ -35,36 +36,32 @@ where
|
||||
V: Debug + Clone + Into<ByteView> + TryFrom<ByteView>,
|
||||
<V as TryFrom<ByteView>>::Error: error::Error + Send + Sync + 'static,
|
||||
{
|
||||
pub fn import(path: &Path, version: Version) -> color_eyre::Result<Self> {
|
||||
pub fn import(
|
||||
keyspace: TransactionalKeyspace,
|
||||
path: &Path,
|
||||
name: &str,
|
||||
version: Version,
|
||||
) -> color_eyre::Result<Self> {
|
||||
let version = MAJOR_FJALL_VERSION + version;
|
||||
|
||||
let meta = StoreMeta::checked_open(path, version)?;
|
||||
|
||||
let keyspace = match Self::open_keyspace(path) {
|
||||
Ok(keyspace) => keyspace,
|
||||
Err(e) => {
|
||||
dbg!(e);
|
||||
meta.reset()?;
|
||||
return Self::import(path, version);
|
||||
}
|
||||
};
|
||||
|
||||
let part = match Self::open_partition_handle(&keyspace) {
|
||||
Ok(part) => part,
|
||||
Err(e) => {
|
||||
dbg!(e);
|
||||
drop(keyspace);
|
||||
meta.reset()?;
|
||||
return Self::import(path, version);
|
||||
}
|
||||
};
|
||||
let (meta, partition) = StoreMeta::checked_open(
|
||||
&keyspace,
|
||||
&path.join(format!("meta/{name}")),
|
||||
version,
|
||||
|| {
|
||||
Self::open_partition_handle(&keyspace, name).inspect_err(|_| {
|
||||
eprintln!("Delete {path:?} and try again");
|
||||
})
|
||||
},
|
||||
)?;
|
||||
|
||||
let rtx = keyspace.read_tx();
|
||||
|
||||
Ok(Self {
|
||||
meta,
|
||||
name: name.to_owned(),
|
||||
keyspace,
|
||||
part,
|
||||
partition,
|
||||
rtx,
|
||||
puts: BTreeMap::new(),
|
||||
dels: BTreeSet::new(),
|
||||
@@ -74,7 +71,7 @@ where
|
||||
pub fn get(&self, key: &K) -> color_eyre::Result<Option<Value<V>>> {
|
||||
if let Some(v) = self.puts.get(key) {
|
||||
Ok(Some(Value::Ref(v)))
|
||||
} else if let Some(slice) = self.rtx.get(&self.part, key.as_bytes())? {
|
||||
} else if let Some(slice) = self.rtx.get(&self.partition, key.as_bytes())? {
|
||||
Ok(Some(Value::Owned(V::try_from(slice.as_bytes().into())?)))
|
||||
} else {
|
||||
Ok(None)
|
||||
@@ -117,25 +114,25 @@ where
|
||||
|
||||
mem::take(&mut self.dels)
|
||||
.into_iter()
|
||||
.for_each(|key| wtx.remove(&self.part, key.as_bytes()));
|
||||
.for_each(|key| wtx.remove(&self.partition, key.as_bytes()));
|
||||
|
||||
mem::take(&mut self.puts)
|
||||
.into_iter()
|
||||
.for_each(|(key, value)| {
|
||||
if CHECK_COLLISISONS {
|
||||
#[allow(unused_must_use)]
|
||||
if let Ok(Some(value)) = wtx.get(&self.part, key.as_bytes()) {
|
||||
if let Ok(Some(value)) = wtx.get(&self.partition, key.as_bytes()) {
|
||||
dbg!(
|
||||
&key,
|
||||
V::try_from(value.as_bytes().into()).unwrap(),
|
||||
&self.meta,
|
||||
self.rtx.get(&self.part, key.as_bytes())
|
||||
self.rtx.get(&self.partition, key.as_bytes())
|
||||
);
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
wtx.insert(
|
||||
&self.part,
|
||||
&self.partition,
|
||||
key.as_bytes(),
|
||||
&*ByteView::try_from(value).unwrap(),
|
||||
)
|
||||
@@ -143,15 +140,13 @@ where
|
||||
|
||||
wtx.commit()?;
|
||||
|
||||
self.keyspace.persist(PersistMode::SyncAll)?;
|
||||
|
||||
self.rtx = self.keyspace.read_tx();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn rotate_memtable(&self) {
|
||||
let _ = self.part.inner().rotate_memtable();
|
||||
let _ = self.partition.inner().rotate_memtable();
|
||||
}
|
||||
|
||||
pub fn height(&self) -> Option<Height> {
|
||||
@@ -172,23 +167,25 @@ where
|
||||
self.meta.needs(height)
|
||||
}
|
||||
|
||||
fn open_keyspace(path: &Path) -> Result<TransactionalKeyspace> {
|
||||
fjall::Config::new(path.join("fjall"))
|
||||
.max_write_buffer_size(32 * 1024 * 1024)
|
||||
.open_transactional()
|
||||
}
|
||||
|
||||
fn open_partition_handle(
|
||||
keyspace: &TransactionalKeyspace,
|
||||
name: &str,
|
||||
) -> Result<TransactionalPartitionHandle> {
|
||||
keyspace.open_partition(
|
||||
"partition",
|
||||
name,
|
||||
PartitionCreateOptions::default()
|
||||
.bloom_filter_bits(Some(5))
|
||||
.max_memtable_size(8 * 1024 * 1024)
|
||||
.manual_journal_persist(true),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn reset_partition(&mut self) -> Result<()> {
|
||||
self.keyspace.delete_partition(self.partition.clone())?;
|
||||
self.keyspace.persist(PersistMode::SyncAll)?;
|
||||
self.partition = Self::open_partition_handle(&self.keyspace, &self.name)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Key, Value> Clone for Store<Key, Value>
|
||||
@@ -199,8 +196,9 @@ where
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
meta: self.meta.clone(),
|
||||
name: self.name.clone(),
|
||||
keyspace: self.keyspace.clone(),
|
||||
part: self.part.clone(),
|
||||
partition: self.partition.clone(),
|
||||
rtx: self.keyspace.read_tx(),
|
||||
puts: self.puts.clone(),
|
||||
dels: self.dels.clone(),
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::{
|
||||
};
|
||||
|
||||
use brk_vec::Version;
|
||||
use fjall::{TransactionalKeyspace, TransactionalPartitionHandle};
|
||||
use zerocopy::{FromBytes, IntoBytes};
|
||||
|
||||
use super::Height;
|
||||
@@ -17,14 +18,27 @@ pub struct StoreMeta {
|
||||
}
|
||||
|
||||
impl StoreMeta {
|
||||
pub fn checked_open(path: &Path, version: Version) -> color_eyre::Result<Self> {
|
||||
pub fn checked_open<F>(
|
||||
keyspace: &TransactionalKeyspace,
|
||||
path: &Path,
|
||||
version: Version,
|
||||
open_partition_handle: F,
|
||||
) -> color_eyre::Result<(Self, TransactionalPartitionHandle)>
|
||||
where
|
||||
F: Fn() -> fjall::Result<TransactionalPartitionHandle>,
|
||||
{
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
let is_same_version = Version::try_from(Self::path_version_(path).as_path())
|
||||
.is_ok_and(|prev_version| version == prev_version);
|
||||
|
||||
let mut partition = open_partition_handle()?;
|
||||
|
||||
if !is_same_version {
|
||||
Self::reset_(path)?;
|
||||
keyspace.delete_partition(partition)?;
|
||||
keyspace.persist(fjall::PersistMode::SyncAll)?;
|
||||
partition = open_partition_handle()?;
|
||||
}
|
||||
|
||||
let slf = Self {
|
||||
@@ -36,7 +50,7 @@ impl StoreMeta {
|
||||
|
||||
slf.version.write(&slf.path_version())?;
|
||||
|
||||
Ok(slf)
|
||||
Ok((slf, partition))
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use std::{path::Path, thread};
|
||||
use std::{fs, path::Path, thread};
|
||||
|
||||
use brk_core::{
|
||||
AddressHash, Addressbytes, Addressindex, Addresstype, BlockHashPrefix, Height, TxidPrefix,
|
||||
Txindex,
|
||||
AddressBytes, AddressBytesHash, BlockHashPrefix, Height, OutputType, OutputTypeIndex, TxIndex,
|
||||
TxidPrefix,
|
||||
};
|
||||
use brk_vec::{Value, Version};
|
||||
use fjall::{PersistMode, TransactionalKeyspace};
|
||||
|
||||
use crate::Indexes;
|
||||
|
||||
@@ -18,25 +19,57 @@ use super::Vecs;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Stores {
|
||||
pub addresshash_to_addressindex: Store<AddressHash, Addressindex>,
|
||||
pub blockhash_prefix_to_height: Store<BlockHashPrefix, Height>,
|
||||
pub txid_prefix_to_txindex: Store<TxidPrefix, Txindex>,
|
||||
pub keyspace: TransactionalKeyspace,
|
||||
pub addressbyteshash_to_outputtypeindex: Store<AddressBytesHash, OutputTypeIndex>,
|
||||
pub blockhashprefix_to_height: Store<BlockHashPrefix, Height>,
|
||||
pub txidprefix_to_txindex: Store<TxidPrefix, TxIndex>,
|
||||
}
|
||||
|
||||
impl Stores {
|
||||
pub fn import(path: &Path) -> color_eyre::Result<Self> {
|
||||
pub fn forced_import(path: &Path) -> color_eyre::Result<Self> {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
let keyspace = match Self::open_keyspace(path) {
|
||||
Ok(keyspace) => keyspace,
|
||||
Err(_) => {
|
||||
fs::remove_dir_all(path)?;
|
||||
return Self::forced_import(path);
|
||||
}
|
||||
};
|
||||
|
||||
thread::scope(|scope| {
|
||||
let addresshash_to_addressindex = scope
|
||||
.spawn(|| Store::import(&path.join("addresshash_to_addressindex"), Version::ZERO));
|
||||
let blockhash_prefix_to_height = scope
|
||||
.spawn(|| Store::import(&path.join("blockhash_prefix_to_height"), Version::ZERO));
|
||||
let txid_prefix_to_txindex =
|
||||
scope.spawn(|| Store::import(&path.join("txid_prefix_to_txindex"), Version::ZERO));
|
||||
let addressbyteshash_to_outputtypeindex = scope.spawn(|| {
|
||||
Store::import(
|
||||
keyspace.clone(),
|
||||
path,
|
||||
"addressbyteshash_to_outputtypeindex",
|
||||
Version::ZERO,
|
||||
)
|
||||
});
|
||||
let blockhashprefix_to_height = scope.spawn(|| {
|
||||
Store::import(
|
||||
keyspace.clone(),
|
||||
path,
|
||||
"blockhashprefix_to_height",
|
||||
Version::ZERO,
|
||||
)
|
||||
});
|
||||
let txidprefix_to_txindex = scope.spawn(|| {
|
||||
Store::import(
|
||||
keyspace.clone(),
|
||||
path,
|
||||
"txidprefix_to_txindex",
|
||||
Version::ZERO,
|
||||
)
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
addresshash_to_addressindex: addresshash_to_addressindex.join().unwrap()?,
|
||||
blockhash_prefix_to_height: blockhash_prefix_to_height.join().unwrap()?,
|
||||
txid_prefix_to_txindex: txid_prefix_to_txindex.join().unwrap()?,
|
||||
keyspace: keyspace.clone(),
|
||||
addressbyteshash_to_outputtypeindex: addressbyteshash_to_outputtypeindex
|
||||
.join()
|
||||
.unwrap()?,
|
||||
blockhashprefix_to_height: blockhashprefix_to_height.join().unwrap()?,
|
||||
txidprefix_to_txindex: txidprefix_to_txindex.join().unwrap()?,
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -46,144 +79,179 @@ impl Stores {
|
||||
vecs: &mut Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
) -> color_eyre::Result<()> {
|
||||
if self.addresshash_to_addressindex.is_empty()
|
||||
&& self.blockhash_prefix_to_height.is_empty()
|
||||
&& self.txid_prefix_to_txindex.is_empty()
|
||||
if self.addressbyteshash_to_outputtypeindex.is_empty()
|
||||
&& self.blockhashprefix_to_height.is_empty()
|
||||
&& self.txidprefix_to_txindex.is_empty()
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
vecs.height_to_blockhash
|
||||
.iter_from(starting_indexes.height, |(_, blockhash, ..)| {
|
||||
let blockhash_prefix = BlockHashPrefix::from(blockhash);
|
||||
self.blockhash_prefix_to_height.remove(blockhash_prefix);
|
||||
Ok(())
|
||||
})?;
|
||||
if starting_indexes.height != Height::ZERO {
|
||||
vecs.height_to_blockhash
|
||||
.iter_at(starting_indexes.height)
|
||||
.for_each(|(_, v)| {
|
||||
let blockhashprefix = BlockHashPrefix::from(Value::into_inner(v));
|
||||
self.blockhashprefix_to_height.remove(blockhashprefix);
|
||||
});
|
||||
|
||||
vecs.txindex_to_txid
|
||||
.iter_from(starting_indexes.txindex, |(_txindex, txid, ..)| {
|
||||
let txid_prefix = TxidPrefix::from(txid);
|
||||
self.txid_prefix_to_txindex.remove(txid_prefix);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
if let Some(index) = vecs
|
||||
.height_to_first_p2pk65index
|
||||
.get(starting_indexes.height)?
|
||||
{
|
||||
let mut index = index.into_inner();
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2pk65index_to_p2pk65addressbytes
|
||||
.get(index)?
|
||||
if let Some(mut index) = vecs
|
||||
.height_to_first_p2pk65index
|
||||
.get(starting_indexes.height)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = Addressbytes::from(typedbytes);
|
||||
let hash = AddressHash::from((&bytes, Addresstype::P2PK65));
|
||||
self.addresshash_to_addressindex.remove(hash);
|
||||
index.increment();
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2pk65index_to_p2pk65bytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = AddressBytes::from(typedbytes);
|
||||
let hash = AddressBytesHash::from((&bytes, OutputType::P2PK65));
|
||||
self.addressbyteshash_to_outputtypeindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut index) = vecs
|
||||
.height_to_first_p2pk33index
|
||||
.get(starting_indexes.height)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2pk33index_to_p2pk33bytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = AddressBytes::from(typedbytes);
|
||||
let hash = AddressBytesHash::from((&bytes, OutputType::P2PK33));
|
||||
self.addressbyteshash_to_outputtypeindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut index) = vecs
|
||||
.height_to_first_p2pkhindex
|
||||
.get(starting_indexes.height)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2pkhindex_to_p2pkhbytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = AddressBytes::from(typedbytes);
|
||||
let hash = AddressBytesHash::from((&bytes, OutputType::P2PKH));
|
||||
self.addressbyteshash_to_outputtypeindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut index) = vecs
|
||||
.height_to_first_p2shindex
|
||||
.get(starting_indexes.height)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2shindex_to_p2shbytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = AddressBytes::from(typedbytes);
|
||||
let hash = AddressBytesHash::from((&bytes, OutputType::P2SH));
|
||||
self.addressbyteshash_to_outputtypeindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut index) = vecs
|
||||
.height_to_first_p2trindex
|
||||
.get(starting_indexes.height)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2trindex_to_p2trbytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = AddressBytes::from(typedbytes);
|
||||
let hash = AddressBytesHash::from((&bytes, OutputType::P2TR));
|
||||
self.addressbyteshash_to_outputtypeindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut index) = vecs
|
||||
.height_to_first_p2wpkhindex
|
||||
.get(starting_indexes.height)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2wpkhindex_to_p2wpkhbytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = AddressBytes::from(typedbytes);
|
||||
let hash = AddressBytesHash::from((&bytes, OutputType::P2WPKH));
|
||||
self.addressbyteshash_to_outputtypeindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut index) = vecs
|
||||
.height_to_first_p2wshindex
|
||||
.get(starting_indexes.height)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2wshindex_to_p2wshbytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = AddressBytes::from(typedbytes);
|
||||
let hash = AddressBytesHash::from((&bytes, OutputType::P2WSH));
|
||||
self.addressbyteshash_to_outputtypeindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut index) = vecs
|
||||
.height_to_first_p2aindex
|
||||
.get(starting_indexes.height)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
while let Some(typedbytes) =
|
||||
vecs.p2aindex_to_p2abytes.get(index)?.map(Value::into_inner)
|
||||
{
|
||||
let bytes = AddressBytes::from(typedbytes);
|
||||
let hash = AddressBytesHash::from((&bytes, OutputType::P2A));
|
||||
self.addressbyteshash_to_outputtypeindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.blockhashprefix_to_height.reset_partition()?;
|
||||
self.addressbyteshash_to_outputtypeindex.reset_partition()?;
|
||||
}
|
||||
|
||||
if let Some(index) = vecs
|
||||
.height_to_first_p2pk33index
|
||||
.get(starting_indexes.height)?
|
||||
{
|
||||
let mut index = index.into_inner();
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2pk33index_to_p2pk33addressbytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = Addressbytes::from(typedbytes);
|
||||
let hash = AddressHash::from((&bytes, Addresstype::P2PK33));
|
||||
self.addresshash_to_addressindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
if starting_indexes.txindex != TxIndex::ZERO {
|
||||
vecs.txindex_to_txid
|
||||
.iter_at(starting_indexes.txindex)
|
||||
.for_each(|(txindex, txid)| {
|
||||
let txidprefix = TxidPrefix::from(&txid.into_inner());
|
||||
|
||||
if let Some(index) = vecs
|
||||
.height_to_first_p2pkhindex
|
||||
.get(starting_indexes.height)?
|
||||
{
|
||||
let mut index = index.into_inner();
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2pkhindex_to_p2pkhaddressbytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = Addressbytes::from(typedbytes);
|
||||
let hash = AddressHash::from((&bytes, Addresstype::P2PKH));
|
||||
self.addresshash_to_addressindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
// "d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599"
|
||||
let is_not_first_dup = txindex != TxIndex::new(142783)
|
||||
|| txidprefix != TxidPrefix::from([153, 133, 216, 41, 84, 225, 15, 34]);
|
||||
|
||||
if let Some(index) = vecs
|
||||
.height_to_first_p2shindex
|
||||
.get(starting_indexes.height)?
|
||||
{
|
||||
let mut index = index.into_inner();
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2shindex_to_p2shaddressbytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = Addressbytes::from(typedbytes);
|
||||
let hash = AddressHash::from((&bytes, Addresstype::P2SH));
|
||||
self.addresshash_to_addressindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
// "e3bf3d07d4b0375638d5f1db5255fe07ba2c4cb067cd81b84ee974b6585fb468"
|
||||
let is_not_second_dup = txindex != TxIndex::new(142841)
|
||||
|| txidprefix != TxidPrefix::from([104, 180, 95, 88, 182, 116, 233, 78]);
|
||||
|
||||
if let Some(index) = vecs
|
||||
.height_to_first_p2trindex
|
||||
.get(starting_indexes.height)?
|
||||
{
|
||||
let mut index = index.into_inner();
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2trindex_to_p2traddressbytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = Addressbytes::from(typedbytes);
|
||||
let hash = AddressHash::from((&bytes, Addresstype::P2TR));
|
||||
self.addresshash_to_addressindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(index) = vecs
|
||||
.height_to_first_p2wpkhindex
|
||||
.get(starting_indexes.height)?
|
||||
{
|
||||
let mut index = index.into_inner();
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2wpkhindex_to_p2wpkhaddressbytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = Addressbytes::from(typedbytes);
|
||||
let hash = AddressHash::from((&bytes, Addresstype::P2WPKH));
|
||||
self.addresshash_to_addressindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(index) = vecs
|
||||
.height_to_first_p2wshindex
|
||||
.get(starting_indexes.height)?
|
||||
{
|
||||
let mut index = index.into_inner();
|
||||
while let Some(typedbytes) = vecs
|
||||
.p2wshindex_to_p2wshaddressbytes
|
||||
.get(index)?
|
||||
.map(Value::into_inner)
|
||||
{
|
||||
let bytes = Addressbytes::from(typedbytes);
|
||||
let hash = AddressHash::from((&bytes, Addresstype::P2WSH));
|
||||
self.addresshash_to_addressindex.remove(hash);
|
||||
index.increment();
|
||||
}
|
||||
if is_not_first_dup && is_not_second_dup {
|
||||
self.txidprefix_to_txindex.remove(txidprefix);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
self.txidprefix_to_txindex.reset_partition()?;
|
||||
}
|
||||
|
||||
self.commit(starting_indexes.height.decremented().unwrap_or_default())?;
|
||||
@@ -193,9 +261,9 @@ impl Stores {
|
||||
|
||||
pub fn starting_height(&self) -> Height {
|
||||
[
|
||||
self.addresshash_to_addressindex.height(),
|
||||
self.blockhash_prefix_to_height.height(),
|
||||
self.txid_prefix_to_txindex.height(),
|
||||
self.addressbyteshash_to_outputtypeindex.height(),
|
||||
self.blockhashprefix_to_height.height(),
|
||||
self.txidprefix_to_txindex.height(),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|height| height.map(Height::incremented).unwrap_or_default())
|
||||
@@ -204,25 +272,35 @@ impl Stores {
|
||||
}
|
||||
|
||||
pub fn commit(&mut self, height: Height) -> fjall::Result<()> {
|
||||
thread::scope(|scope| {
|
||||
let addresshash_to_addressindex_commit_handle =
|
||||
scope.spawn(|| self.addresshash_to_addressindex.commit(height));
|
||||
let blockhash_prefix_to_height_commit_handle =
|
||||
scope.spawn(|| self.blockhash_prefix_to_height.commit(height));
|
||||
let txid_prefix_to_txindex_commit_handle =
|
||||
scope.spawn(|| self.txid_prefix_to_txindex.commit(height));
|
||||
thread::scope(|scope| -> fjall::Result<()> {
|
||||
let addressbyteshash_to_outputtypeindex_commit_handle =
|
||||
scope.spawn(|| self.addressbyteshash_to_outputtypeindex.commit(height));
|
||||
let blockhashprefix_to_height_commit_handle =
|
||||
scope.spawn(|| self.blockhashprefix_to_height.commit(height));
|
||||
let txidprefix_to_txindex_commit_handle =
|
||||
scope.spawn(|| self.txidprefix_to_txindex.commit(height));
|
||||
|
||||
addresshash_to_addressindex_commit_handle.join().unwrap()?;
|
||||
blockhash_prefix_to_height_commit_handle.join().unwrap()?;
|
||||
txid_prefix_to_txindex_commit_handle.join().unwrap()?;
|
||||
addressbyteshash_to_outputtypeindex_commit_handle
|
||||
.join()
|
||||
.unwrap()?;
|
||||
blockhashprefix_to_height_commit_handle.join().unwrap()?;
|
||||
txidprefix_to_txindex_commit_handle.join().unwrap()?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
})?;
|
||||
|
||||
self.keyspace.persist(PersistMode::SyncAll)
|
||||
}
|
||||
|
||||
pub fn rotate_memtables(&self) {
|
||||
self.addresshash_to_addressindex.rotate_memtable();
|
||||
self.blockhash_prefix_to_height.rotate_memtable();
|
||||
self.txid_prefix_to_txindex.rotate_memtable();
|
||||
self.addressbyteshash_to_outputtypeindex.rotate_memtable();
|
||||
self.blockhashprefix_to_height.rotate_memtable();
|
||||
self.txidprefix_to_txindex.rotate_memtable();
|
||||
}
|
||||
|
||||
fn open_keyspace(path: &Path) -> fjall::Result<TransactionalKeyspace> {
|
||||
fjall::Config::new(path.join("fjall"))
|
||||
.max_write_buffer_size(32 * 1024 * 1024)
|
||||
.open_transactional()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ use std::{
|
||||
};
|
||||
|
||||
use brk_vec::{
|
||||
Compressed, DynamicVec, Error, GenericVec, Result, StoredIndex, StoredType, StoredVec, Value,
|
||||
Version,
|
||||
Compressed, DynamicVec, Error, GenericVec, Result, StoredIndex, StoredType, StoredVec,
|
||||
StoredVecIterator, Value, Version,
|
||||
};
|
||||
|
||||
use super::Height;
|
||||
@@ -45,21 +45,6 @@ where
|
||||
pub fn get(&self, index: I) -> Result<Option<Value<'_, T>>> {
|
||||
self.inner.get(index)
|
||||
}
|
||||
#[inline]
|
||||
pub fn unwrap_cached_get(&mut self, index: I) -> Option<T> {
|
||||
self.inner.unwrap_cached_get(index)
|
||||
}
|
||||
#[inline]
|
||||
pub fn double_unwrap_cached_get(&mut self, index: I) -> T {
|
||||
self.inner.double_unwrap_cached_get(index)
|
||||
}
|
||||
|
||||
pub fn iter_from<F>(&mut self, index: I, f: F) -> Result<()>
|
||||
where
|
||||
F: FnMut((I, T, &mut dyn DynamicVec<I = I, T = T>)) -> Result<()>,
|
||||
{
|
||||
self.inner.iter_from(index, f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn push_if_needed(&mut self, index: I, value: T) -> Result<()> {
|
||||
@@ -127,6 +112,16 @@ where
|
||||
fn path_height_(path: &Path) -> PathBuf {
|
||||
path.join("height")
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> StoredVecIterator<'_, I, T> {
|
||||
self.into_iter()
|
||||
}
|
||||
|
||||
pub fn iter_at(&self, i: I) -> StoredVecIterator<'_, I, T> {
|
||||
let mut iter = self.into_iter();
|
||||
iter.set(i);
|
||||
iter
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AnyIndexedVec: Send + Sync {
|
||||
@@ -147,3 +142,16 @@ where
|
||||
self.flush(height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I, T> IntoIterator for &'a IndexedVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
{
|
||||
type Item = (I, Value<'a, T>);
|
||||
type IntoIter = StoredVecIterator<'a, I, T>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.inner.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
+329
-464
@@ -1,11 +1,11 @@
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use brk_core::{
|
||||
Addressbytes, Addressindex, Addresstype, Addresstypeindex, BlockHash, Emptyindex, Height,
|
||||
LockTime, Multisigindex, Opreturnindex, P2PK33AddressBytes, P2PK33index, P2PK65AddressBytes,
|
||||
P2PK65index, P2PKHAddressBytes, P2PKHindex, P2SHAddressBytes, P2SHindex, P2TRAddressBytes,
|
||||
P2TRindex, P2WPKHAddressBytes, P2WPKHindex, P2WSHAddressBytes, P2WSHindex, Pushonlyindex, Sats,
|
||||
StoredUsize, Timestamp, TxVersion, Txid, Txindex, Txinindex, Txoutindex, Unknownindex, Weight,
|
||||
AddressBytes, BlockHash, EmptyOutputIndex, Height, InputIndex, OpReturnIndex, OutputIndex,
|
||||
OutputType, OutputTypeIndex, P2ABytes, P2AIndex, P2MSIndex, P2PK33Bytes, P2PK33Index,
|
||||
P2PK65Bytes, P2PK65Index, P2PKHBytes, P2PKHIndex, P2SHBytes, P2SHIndex, P2TRBytes, P2TRIndex,
|
||||
P2WPKHBytes, P2WPKHIndex, P2WSHBytes, P2WSHIndex, RawLockTime, Sats, StoredF64, StoredU32,
|
||||
StoredUsize, Timestamp, TxIndex, TxVersion, Txid, UnknownOutputIndex, Weight,
|
||||
};
|
||||
use brk_vec::{AnyStoredVec, Compressed, Result, Version};
|
||||
use rayon::prelude::*;
|
||||
@@ -18,108 +18,81 @@ pub use base::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
pub addressindex_to_addresstype: IndexedVec<Addressindex, Addresstype>,
|
||||
pub addressindex_to_addresstypeindex: IndexedVec<Addressindex, Addresstypeindex>,
|
||||
pub addressindex_to_height: IndexedVec<Addressindex, Height>,
|
||||
pub emptyindex_to_height: IndexedVec<Emptyindex, Height>,
|
||||
pub emptyoutputindex_to_txindex: IndexedVec<EmptyOutputIndex, TxIndex>,
|
||||
pub height_to_blockhash: IndexedVec<Height, BlockHash>,
|
||||
pub height_to_difficulty: IndexedVec<Height, f64>,
|
||||
pub height_to_first_addressindex: IndexedVec<Height, Addressindex>,
|
||||
pub height_to_first_emptyindex: IndexedVec<Height, Emptyindex>,
|
||||
pub height_to_first_multisigindex: IndexedVec<Height, Multisigindex>,
|
||||
pub height_to_first_opreturnindex: IndexedVec<Height, Opreturnindex>,
|
||||
pub height_to_first_p2pk33index: IndexedVec<Height, P2PK33index>,
|
||||
pub height_to_first_p2pk65index: IndexedVec<Height, P2PK65index>,
|
||||
pub height_to_first_p2pkhindex: IndexedVec<Height, P2PKHindex>,
|
||||
pub height_to_first_p2shindex: IndexedVec<Height, P2SHindex>,
|
||||
pub height_to_first_p2trindex: IndexedVec<Height, P2TRindex>,
|
||||
pub height_to_first_p2wpkhindex: IndexedVec<Height, P2WPKHindex>,
|
||||
pub height_to_first_p2wshindex: IndexedVec<Height, P2WSHindex>,
|
||||
pub height_to_first_pushonlyindex: IndexedVec<Height, Pushonlyindex>,
|
||||
pub height_to_first_txindex: IndexedVec<Height, Txindex>,
|
||||
pub height_to_first_txinindex: IndexedVec<Height, Txinindex>,
|
||||
pub height_to_first_txoutindex: IndexedVec<Height, Txoutindex>,
|
||||
pub height_to_first_unknownindex: IndexedVec<Height, Unknownindex>,
|
||||
pub height_to_total_size: IndexedVec<Height, StoredUsize>,
|
||||
pub height_to_difficulty: IndexedVec<Height, StoredF64>,
|
||||
pub height_to_first_emptyoutputindex: IndexedVec<Height, EmptyOutputIndex>,
|
||||
pub height_to_first_inputindex: IndexedVec<Height, InputIndex>,
|
||||
pub height_to_first_opreturnindex: IndexedVec<Height, OpReturnIndex>,
|
||||
pub height_to_first_outputindex: IndexedVec<Height, OutputIndex>,
|
||||
pub height_to_first_p2aindex: IndexedVec<Height, P2AIndex>,
|
||||
pub height_to_first_p2msindex: IndexedVec<Height, P2MSIndex>,
|
||||
pub height_to_first_p2pk33index: IndexedVec<Height, P2PK33Index>,
|
||||
pub height_to_first_p2pk65index: IndexedVec<Height, P2PK65Index>,
|
||||
pub height_to_first_p2pkhindex: IndexedVec<Height, P2PKHIndex>,
|
||||
pub height_to_first_p2shindex: IndexedVec<Height, P2SHIndex>,
|
||||
pub height_to_first_p2trindex: IndexedVec<Height, P2TRIndex>,
|
||||
pub height_to_first_p2wpkhindex: IndexedVec<Height, P2WPKHIndex>,
|
||||
pub height_to_first_p2wshindex: IndexedVec<Height, P2WSHIndex>,
|
||||
pub height_to_first_txindex: IndexedVec<Height, TxIndex>,
|
||||
pub height_to_first_unknownoutputindex: IndexedVec<Height, UnknownOutputIndex>,
|
||||
/// Doesn't guarantee continuity due to possible reorgs
|
||||
pub height_to_timestamp: IndexedVec<Height, Timestamp>,
|
||||
pub height_to_total_size: IndexedVec<Height, StoredUsize>,
|
||||
pub height_to_weight: IndexedVec<Height, Weight>,
|
||||
pub multisigindex_to_height: IndexedVec<Multisigindex, Height>,
|
||||
pub opreturnindex_to_height: IndexedVec<Opreturnindex, Height>,
|
||||
pub p2pk33index_to_height: IndexedVec<P2PK33index, Height>,
|
||||
pub p2pk33index_to_p2pk33addressbytes: IndexedVec<P2PK33index, P2PK33AddressBytes>,
|
||||
pub p2pk65index_to_height: IndexedVec<P2PK65index, Height>,
|
||||
pub p2pk65index_to_p2pk65addressbytes: IndexedVec<P2PK65index, P2PK65AddressBytes>,
|
||||
pub p2pkhindex_to_height: IndexedVec<P2PKHindex, Height>,
|
||||
pub p2pkhindex_to_p2pkhaddressbytes: IndexedVec<P2PKHindex, P2PKHAddressBytes>,
|
||||
pub p2shindex_to_height: IndexedVec<P2SHindex, Height>,
|
||||
pub p2shindex_to_p2shaddressbytes: IndexedVec<P2SHindex, P2SHAddressBytes>,
|
||||
pub p2trindex_to_height: IndexedVec<P2TRindex, Height>,
|
||||
pub p2trindex_to_p2traddressbytes: IndexedVec<P2TRindex, P2TRAddressBytes>,
|
||||
pub p2wpkhindex_to_height: IndexedVec<P2WPKHindex, Height>,
|
||||
pub p2wpkhindex_to_p2wpkhaddressbytes: IndexedVec<P2WPKHindex, P2WPKHAddressBytes>,
|
||||
pub p2wshindex_to_height: IndexedVec<P2WSHindex, Height>,
|
||||
pub p2wshindex_to_p2wshaddressbytes: IndexedVec<P2WSHindex, P2WSHAddressBytes>,
|
||||
pub pushonlyindex_to_height: IndexedVec<Pushonlyindex, Height>,
|
||||
pub txindex_to_base_size: IndexedVec<Txindex, usize>,
|
||||
pub txindex_to_first_txinindex: IndexedVec<Txindex, Txinindex>,
|
||||
pub txindex_to_first_txoutindex: IndexedVec<Txindex, Txoutindex>,
|
||||
pub txindex_to_height: IndexedVec<Txindex, Height>,
|
||||
pub txindex_to_is_explicitly_rbf: IndexedVec<Txindex, bool>,
|
||||
pub txindex_to_locktime: IndexedVec<Txindex, LockTime>,
|
||||
pub txindex_to_total_size: IndexedVec<Txindex, usize>,
|
||||
pub txindex_to_txid: IndexedVec<Txindex, Txid>,
|
||||
pub txindex_to_txversion: IndexedVec<Txindex, TxVersion>,
|
||||
pub txinindex_to_height: IndexedVec<Txinindex, Height>,
|
||||
/// If txoutindex == Txoutindex MAX then is it's coinbase
|
||||
pub txinindex_to_txoutindex: IndexedVec<Txinindex, Txoutindex>,
|
||||
pub txoutindex_to_addressindex: IndexedVec<Txoutindex, Addressindex>,
|
||||
pub txoutindex_to_height: IndexedVec<Txoutindex, Height>,
|
||||
pub txoutindex_to_value: IndexedVec<Txoutindex, Sats>,
|
||||
pub unknownindex_to_height: IndexedVec<Unknownindex, Height>,
|
||||
/// If outputindex == Outputindex::MAX then it's coinbase
|
||||
pub inputindex_to_outputindex: IndexedVec<InputIndex, OutputIndex>,
|
||||
pub opreturnindex_to_txindex: IndexedVec<OpReturnIndex, TxIndex>,
|
||||
pub outputindex_to_outputtype: IndexedVec<OutputIndex, OutputType>,
|
||||
pub outputindex_to_outputtypeindex: IndexedVec<OutputIndex, OutputTypeIndex>,
|
||||
pub outputindex_to_value: IndexedVec<OutputIndex, Sats>,
|
||||
pub p2aindex_to_p2abytes: IndexedVec<P2AIndex, P2ABytes>,
|
||||
pub p2msindex_to_txindex: IndexedVec<P2MSIndex, TxIndex>,
|
||||
pub p2pk33index_to_p2pk33bytes: IndexedVec<P2PK33Index, P2PK33Bytes>,
|
||||
pub p2pk65index_to_p2pk65bytes: IndexedVec<P2PK65Index, P2PK65Bytes>,
|
||||
pub p2pkhindex_to_p2pkhbytes: IndexedVec<P2PKHIndex, P2PKHBytes>,
|
||||
pub p2shindex_to_p2shbytes: IndexedVec<P2SHIndex, P2SHBytes>,
|
||||
pub p2trindex_to_p2trbytes: IndexedVec<P2TRIndex, P2TRBytes>,
|
||||
pub p2wpkhindex_to_p2wpkhbytes: IndexedVec<P2WPKHIndex, P2WPKHBytes>,
|
||||
pub p2wshindex_to_p2wshbytes: IndexedVec<P2WSHIndex, P2WSHBytes>,
|
||||
pub txindex_to_base_size: IndexedVec<TxIndex, StoredU32>,
|
||||
pub txindex_to_first_inputindex: IndexedVec<TxIndex, InputIndex>,
|
||||
pub txindex_to_first_outputindex: IndexedVec<TxIndex, OutputIndex>,
|
||||
pub txindex_to_is_explicitly_rbf: IndexedVec<TxIndex, bool>,
|
||||
pub txindex_to_rawlocktime: IndexedVec<TxIndex, RawLockTime>,
|
||||
pub txindex_to_total_size: IndexedVec<TxIndex, StoredU32>,
|
||||
pub txindex_to_txid: IndexedVec<TxIndex, Txid>,
|
||||
pub txindex_to_txversion: IndexedVec<TxIndex, TxVersion>,
|
||||
pub unknownoutputindex_to_txindex: IndexedVec<UnknownOutputIndex, TxIndex>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub fn import(path: &Path, compressed: Compressed) -> color_eyre::Result<Self> {
|
||||
pub fn forced_import(path: &Path, compressed: Compressed) -> color_eyre::Result<Self> {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
Ok(Self {
|
||||
addressindex_to_addresstype: IndexedVec::forced_import(
|
||||
&path.join("addressindex_to_addresstype"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
addressindex_to_addresstypeindex: IndexedVec::forced_import(
|
||||
&path.join("addressindex_to_addresstypeindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
addressindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("addressindex_to_height"),
|
||||
emptyoutputindex_to_txindex: IndexedVec::forced_import(
|
||||
&path.join("emptyoutputindex_to_txindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_blockhash: IndexedVec::forced_import(
|
||||
&path.join("height_to_blockhash"),
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_difficulty: IndexedVec::forced_import(
|
||||
&path.join("height_to_difficulty"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_addressindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_addressindex"),
|
||||
height_to_first_emptyoutputindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_emptyoutputindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_emptyindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_emptyindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_multisigindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_multisigindex"),
|
||||
height_to_first_inputindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_inputindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
@@ -128,28 +101,18 @@ impl Vecs {
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_pushonlyindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_pushonlyindex"),
|
||||
height_to_first_outputindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_outputindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_txindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_txindex"),
|
||||
height_to_first_p2aindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_p2aindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_txinindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_txinindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_txoutindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_txoutindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_unknownindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_unkownindex"),
|
||||
height_to_first_p2msindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_p2msindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
@@ -188,8 +151,13 @@ impl Vecs {
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_total_size: IndexedVec::forced_import(
|
||||
&path.join("height_to_total_size"),
|
||||
height_to_first_txindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_txindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_unknownoutputindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_unknownoutputindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
@@ -198,78 +166,98 @@ impl Vecs {
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_total_size: IndexedVec::forced_import(
|
||||
&path.join("height_to_total_size"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_weight: IndexedVec::forced_import(
|
||||
&path.join("height_to_weight"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2pk33index_to_p2pk33addressbytes: IndexedVec::forced_import(
|
||||
&path.join("p2pk33index_to_p2pk33addressbytes"),
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2pk65index_to_p2pk65addressbytes: IndexedVec::forced_import(
|
||||
&path.join("p2pk65index_to_p2pk65addressbytes"),
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2pkhindex_to_p2pkhaddressbytes: IndexedVec::forced_import(
|
||||
&path.join("p2pkhindex_to_p2pkhaddressbytes"),
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2shindex_to_p2shaddressbytes: IndexedVec::forced_import(
|
||||
&path.join("p2shindex_to_p2shaddressbytes"),
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2trindex_to_p2traddressbytes: IndexedVec::forced_import(
|
||||
&path.join("p2trindex_to_p2traddressbytes"),
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2wpkhindex_to_p2wpkhaddressbytes: IndexedVec::forced_import(
|
||||
&path.join("p2wpkhindex_to_p2wpkhaddressbytes"),
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2wshindex_to_p2wshaddressbytes: IndexedVec::forced_import(
|
||||
&path.join("p2wshindex_to_p2wshaddressbytes"),
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
txindex_to_first_txinindex: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_first_txinindex"),
|
||||
inputindex_to_outputindex: IndexedVec::forced_import(
|
||||
&path.join("inputindex_to_outputindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_first_txoutindex: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_first_txoutindex"),
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
txindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_height"),
|
||||
opreturnindex_to_txindex: IndexedVec::forced_import(
|
||||
&path.join("opreturnindex_to_txindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_locktime: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_locktime"),
|
||||
outputindex_to_outputtype: IndexedVec::forced_import(
|
||||
&path.join("outputindex_to_outputtype"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_txid: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_txid"),
|
||||
outputindex_to_outputtypeindex: IndexedVec::forced_import(
|
||||
&path.join("outputindex_to_outputtypeindex"),
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
compressed,
|
||||
)?,
|
||||
outputindex_to_value: IndexedVec::forced_import(
|
||||
&path.join("outputindex_to_value"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2aindex_to_p2abytes: IndexedVec::forced_import(
|
||||
&path.join("p2aindex_to_p2abytes"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2msindex_to_txindex: IndexedVec::forced_import(
|
||||
&path.join("p2msindex_to_txindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2pk33index_to_p2pk33bytes: IndexedVec::forced_import(
|
||||
&path.join("p2pk33index_to_p2pk33bytes"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2pk65index_to_p2pk65bytes: IndexedVec::forced_import(
|
||||
&path.join("p2pk65index_to_p2pk65bytes"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2pkhindex_to_p2pkhbytes: IndexedVec::forced_import(
|
||||
&path.join("p2pkhindex_to_p2pkhbytes"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2shindex_to_p2shbytes: IndexedVec::forced_import(
|
||||
&path.join("p2shindex_to_p2shbytes"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2trindex_to_p2trbytes: IndexedVec::forced_import(
|
||||
&path.join("p2trindex_to_p2trbytes"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2wpkhindex_to_p2wpkhbytes: IndexedVec::forced_import(
|
||||
&path.join("p2wpkhindex_to_p2wpkhbytes"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2wshindex_to_p2wshbytes: IndexedVec::forced_import(
|
||||
&path.join("p2wshindex_to_p2wshbytes"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_base_size: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_base_size"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_total_size: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_total_size"),
|
||||
txindex_to_first_inputindex: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_first_inputindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_first_outputindex: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_first_outputindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
@@ -278,93 +266,28 @@ impl Vecs {
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_rawlocktime: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_rawlocktime"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_total_size: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_total_size"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_txid: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_txid"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_txversion: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_txversion"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txinindex_to_txoutindex: IndexedVec::forced_import(
|
||||
&path.join("txinindex_to_txoutindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txoutindex_to_addressindex: IndexedVec::forced_import(
|
||||
&path.join("txoutindex_to_addressindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txoutindex_to_value: IndexedVec::forced_import(
|
||||
&path.join("txoutindex_to_value"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
emptyindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("emptyindex_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
multisigindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("multisigindex_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
opreturnindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("opreturnindex_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
pushonlyindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("pushonlyindex_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txinindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("txinindex_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txoutindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("txoutindex_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
unknownindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("unknownindex_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2pk33index_to_height: IndexedVec::forced_import(
|
||||
&path.join("p2pk33index_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2pk65index_to_height: IndexedVec::forced_import(
|
||||
&path.join("p2pk65index_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2pkhindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("p2pkhindex_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2shindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("p2shindex_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2trindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("p2trindex_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2wpkhindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("p2wpkhindex_to_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2wshindex_to_height: IndexedVec::forced_import(
|
||||
&path.join("p2wshindex_to_height"),
|
||||
unknownoutputindex_to_txindex: IndexedVec::forced_import(
|
||||
&path.join("unknownoutputindex_to_txindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
@@ -375,8 +298,13 @@ impl Vecs {
|
||||
let saved_height = starting_indexes.height.decremented().unwrap_or_default();
|
||||
|
||||
let &Indexes {
|
||||
addressindex,
|
||||
emptyoutputindex,
|
||||
height,
|
||||
inputindex,
|
||||
opreturnindex,
|
||||
outputindex,
|
||||
p2aindex,
|
||||
p2msindex,
|
||||
p2pk33index,
|
||||
p2pk65index,
|
||||
p2pkhindex,
|
||||
@@ -385,23 +313,27 @@ impl Vecs {
|
||||
p2wpkhindex,
|
||||
p2wshindex,
|
||||
txindex,
|
||||
txinindex,
|
||||
txoutindex,
|
||||
unknownindex,
|
||||
pushonlyindex,
|
||||
opreturnindex,
|
||||
multisigindex,
|
||||
emptyindex,
|
||||
unknownoutputindex,
|
||||
} = starting_indexes;
|
||||
|
||||
self.height_to_first_addressindex
|
||||
self.emptyoutputindex_to_txindex
|
||||
.truncate_if_needed(emptyoutputindex, saved_height)?;
|
||||
self.height_to_blockhash
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_emptyindex
|
||||
self.height_to_difficulty
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_multisigindex
|
||||
self.height_to_first_emptyoutputindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_inputindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_opreturnindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_outputindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_p2aindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_p2msindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_p2pk33index
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_p2pk65index
|
||||
@@ -416,180 +348,139 @@ impl Vecs {
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_p2wshindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_pushonlyindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_txindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_txinindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_txoutindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_first_unknownindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
|
||||
self.height_to_blockhash
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_difficulty
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_total_size
|
||||
self.height_to_first_unknownoutputindex
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_timestamp
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_total_size
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
self.height_to_weight
|
||||
.truncate_if_needed(height, saved_height)?;
|
||||
|
||||
self.addressindex_to_addresstype
|
||||
.truncate_if_needed(addressindex, saved_height)?;
|
||||
self.addressindex_to_addresstypeindex
|
||||
.truncate_if_needed(addressindex, saved_height)?;
|
||||
self.addressindex_to_height
|
||||
.truncate_if_needed(addressindex, saved_height)?;
|
||||
|
||||
self.p2pk33index_to_p2pk33addressbytes
|
||||
self.inputindex_to_outputindex
|
||||
.truncate_if_needed(inputindex, saved_height)?;
|
||||
self.opreturnindex_to_txindex
|
||||
.truncate_if_needed(opreturnindex, saved_height)?;
|
||||
self.outputindex_to_outputtype
|
||||
.truncate_if_needed(outputindex, saved_height)?;
|
||||
self.outputindex_to_outputtypeindex
|
||||
.truncate_if_needed(outputindex, saved_height)?;
|
||||
self.outputindex_to_value
|
||||
.truncate_if_needed(outputindex, saved_height)?;
|
||||
self.p2aindex_to_p2abytes
|
||||
.truncate_if_needed(p2aindex, saved_height)?;
|
||||
self.p2msindex_to_txindex
|
||||
.truncate_if_needed(p2msindex, saved_height)?;
|
||||
self.p2pk33index_to_p2pk33bytes
|
||||
.truncate_if_needed(p2pk33index, saved_height)?;
|
||||
self.p2pk65index_to_p2pk65addressbytes
|
||||
self.p2pk65index_to_p2pk65bytes
|
||||
.truncate_if_needed(p2pk65index, saved_height)?;
|
||||
self.p2pkhindex_to_p2pkhaddressbytes
|
||||
self.p2pkhindex_to_p2pkhbytes
|
||||
.truncate_if_needed(p2pkhindex, saved_height)?;
|
||||
self.p2shindex_to_p2shaddressbytes
|
||||
self.p2shindex_to_p2shbytes
|
||||
.truncate_if_needed(p2shindex, saved_height)?;
|
||||
self.p2trindex_to_p2traddressbytes
|
||||
self.p2trindex_to_p2trbytes
|
||||
.truncate_if_needed(p2trindex, saved_height)?;
|
||||
self.p2wpkhindex_to_p2wpkhaddressbytes
|
||||
self.p2wpkhindex_to_p2wpkhbytes
|
||||
.truncate_if_needed(p2wpkhindex, saved_height)?;
|
||||
self.p2wshindex_to_p2wshaddressbytes
|
||||
self.p2wshindex_to_p2wshbytes
|
||||
.truncate_if_needed(p2wshindex, saved_height)?;
|
||||
|
||||
self.txindex_to_first_txinindex
|
||||
self.txindex_to_base_size
|
||||
.truncate_if_needed(txindex, saved_height)?;
|
||||
self.txindex_to_first_txoutindex
|
||||
self.txindex_to_first_inputindex
|
||||
.truncate_if_needed(txindex, saved_height)?;
|
||||
self.txindex_to_height
|
||||
self.txindex_to_first_outputindex
|
||||
.truncate_if_needed(txindex, saved_height)?;
|
||||
self.txindex_to_locktime
|
||||
self.txindex_to_is_explicitly_rbf
|
||||
.truncate_if_needed(txindex, saved_height)?;
|
||||
self.txindex_to_rawlocktime
|
||||
.truncate_if_needed(txindex, saved_height)?;
|
||||
self.txindex_to_total_size
|
||||
.truncate_if_needed(txindex, saved_height)?;
|
||||
self.txindex_to_txid
|
||||
.truncate_if_needed(txindex, saved_height)?;
|
||||
self.txindex_to_txversion
|
||||
.truncate_if_needed(txindex, saved_height)?;
|
||||
self.txindex_to_base_size
|
||||
.truncate_if_needed(txindex, saved_height)?;
|
||||
self.txindex_to_total_size
|
||||
.truncate_if_needed(txindex, saved_height)?;
|
||||
self.txindex_to_is_explicitly_rbf
|
||||
.truncate_if_needed(txindex, saved_height)?;
|
||||
|
||||
self.txinindex_to_txoutindex
|
||||
.truncate_if_needed(txinindex, saved_height)?;
|
||||
|
||||
self.txoutindex_to_addressindex
|
||||
.truncate_if_needed(txoutindex, saved_height)?;
|
||||
self.txoutindex_to_value
|
||||
.truncate_if_needed(txoutindex, saved_height)?;
|
||||
|
||||
self.emptyindex_to_height
|
||||
.truncate_if_needed(emptyindex, saved_height)?;
|
||||
self.multisigindex_to_height
|
||||
.truncate_if_needed(multisigindex, saved_height)?;
|
||||
self.opreturnindex_to_height
|
||||
.truncate_if_needed(opreturnindex, saved_height)?;
|
||||
self.pushonlyindex_to_height
|
||||
.truncate_if_needed(pushonlyindex, saved_height)?;
|
||||
self.txinindex_to_height
|
||||
.truncate_if_needed(txinindex, saved_height)?;
|
||||
self.txoutindex_to_height
|
||||
.truncate_if_needed(txoutindex, saved_height)?;
|
||||
self.unknownindex_to_height
|
||||
.truncate_if_needed(unknownindex, saved_height)?;
|
||||
self.p2pk33index_to_height
|
||||
.truncate_if_needed(p2pk33index, saved_height)?;
|
||||
self.p2pk65index_to_height
|
||||
.truncate_if_needed(p2pk65index, saved_height)?;
|
||||
self.p2pkhindex_to_height
|
||||
.truncate_if_needed(p2pkhindex, saved_height)?;
|
||||
self.p2shindex_to_height
|
||||
.truncate_if_needed(p2shindex, saved_height)?;
|
||||
self.p2trindex_to_height
|
||||
.truncate_if_needed(p2trindex, saved_height)?;
|
||||
self.p2wpkhindex_to_height
|
||||
.truncate_if_needed(p2wpkhindex, saved_height)?;
|
||||
self.p2wshindex_to_height
|
||||
.truncate_if_needed(p2wshindex, saved_height)?;
|
||||
self.unknownoutputindex_to_txindex
|
||||
.truncate_if_needed(unknownoutputindex, saved_height)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_addressbytes(
|
||||
&self,
|
||||
addresstype: Addresstype,
|
||||
addresstypeindex: Addresstypeindex,
|
||||
) -> brk_vec::Result<Option<Addressbytes>> {
|
||||
Ok(match addresstype {
|
||||
Addresstype::P2PK65 => self
|
||||
.p2pk65index_to_p2pk65addressbytes
|
||||
.get(addresstypeindex.into())?
|
||||
// .map(|v| Addressbytes::from(v.clone())),
|
||||
.map(|v| Addressbytes::from(v.into_inner())),
|
||||
Addresstype::P2PK33 => self
|
||||
.p2pk33index_to_p2pk33addressbytes
|
||||
.get(addresstypeindex.into())?
|
||||
// .map(|v| Addressbytes::from(v.clone())),
|
||||
.map(|v| Addressbytes::from(v.into_inner())),
|
||||
Addresstype::P2PKH => self
|
||||
.p2pkhindex_to_p2pkhaddressbytes
|
||||
.get(addresstypeindex.into())?
|
||||
// .map(|v| Addressbytes::from(v.clone())),
|
||||
.map(|v| Addressbytes::from(v.into_inner())),
|
||||
Addresstype::P2SH => self
|
||||
.p2shindex_to_p2shaddressbytes
|
||||
.get(addresstypeindex.into())?
|
||||
// .map(|v| Addressbytes::from(v.clone())),
|
||||
.map(|v| Addressbytes::from(v.into_inner())),
|
||||
Addresstype::P2WPKH => self
|
||||
.p2wpkhindex_to_p2wpkhaddressbytes
|
||||
.get(addresstypeindex.into())?
|
||||
// .map(|v| Addressbytes::from(v.clone())),
|
||||
.map(|v| Addressbytes::from(v.into_inner())),
|
||||
Addresstype::P2WSH => self
|
||||
.p2wshindex_to_p2wshaddressbytes
|
||||
.get(addresstypeindex.into())?
|
||||
// .map(|v| Addressbytes::from(v.clone())),
|
||||
.map(|v| Addressbytes::from(v.into_inner())),
|
||||
Addresstype::P2TR => self
|
||||
.p2trindex_to_p2traddressbytes
|
||||
.get(addresstypeindex.into())?
|
||||
// .map(|v| Addressbytes::from(v.clone())),
|
||||
.map(|v| Addressbytes::from(v.into_inner())),
|
||||
_ => unreachable!(),
|
||||
outputtype: OutputType,
|
||||
outputtypeindex: OutputTypeIndex,
|
||||
) -> brk_vec::Result<Option<AddressBytes>> {
|
||||
Ok(match outputtype {
|
||||
OutputType::P2PK65 => self
|
||||
.p2pk65index_to_p2pk65bytes
|
||||
.get(outputtypeindex.into())?
|
||||
.map(|v| AddressBytes::from(v.into_inner())),
|
||||
OutputType::P2PK33 => self
|
||||
.p2pk33index_to_p2pk33bytes
|
||||
.get(outputtypeindex.into())?
|
||||
.map(|v| AddressBytes::from(v.into_inner())),
|
||||
OutputType::P2PKH => self
|
||||
.p2pkhindex_to_p2pkhbytes
|
||||
.get(outputtypeindex.into())?
|
||||
.map(|v| AddressBytes::from(v.into_inner())),
|
||||
OutputType::P2SH => self
|
||||
.p2shindex_to_p2shbytes
|
||||
.get(outputtypeindex.into())?
|
||||
.map(|v| AddressBytes::from(v.into_inner())),
|
||||
OutputType::P2WPKH => self
|
||||
.p2wpkhindex_to_p2wpkhbytes
|
||||
.get(outputtypeindex.into())?
|
||||
.map(|v| AddressBytes::from(v.into_inner())),
|
||||
OutputType::P2WSH => self
|
||||
.p2wshindex_to_p2wshbytes
|
||||
.get(outputtypeindex.into())?
|
||||
.map(|v| AddressBytes::from(v.into_inner())),
|
||||
OutputType::P2TR => self
|
||||
.p2trindex_to_p2trbytes
|
||||
.get(outputtypeindex.into())?
|
||||
.map(|v| AddressBytes::from(v.into_inner())),
|
||||
OutputType::P2A => self
|
||||
.p2aindex_to_p2abytes
|
||||
.get(outputtypeindex.into())?
|
||||
.map(|v| AddressBytes::from(v.into_inner())),
|
||||
OutputType::Empty | OutputType::OpReturn | OutputType::P2MS | OutputType::Unknown => {
|
||||
unreachable!()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn push_addressbytes_if_needed(
|
||||
pub fn push_bytes_if_needed(
|
||||
&mut self,
|
||||
index: Addresstypeindex,
|
||||
addressbytes: Addressbytes,
|
||||
index: OutputTypeIndex,
|
||||
bytes: AddressBytes,
|
||||
) -> brk_vec::Result<()> {
|
||||
match addressbytes {
|
||||
Addressbytes::P2PK65(bytes) => self
|
||||
.p2pk65index_to_p2pk65addressbytes
|
||||
match bytes {
|
||||
AddressBytes::P2PK65(bytes) => self
|
||||
.p2pk65index_to_p2pk65bytes
|
||||
.push_if_needed(index.into(), bytes),
|
||||
Addressbytes::P2PK33(bytes) => self
|
||||
.p2pk33index_to_p2pk33addressbytes
|
||||
AddressBytes::P2PK33(bytes) => self
|
||||
.p2pk33index_to_p2pk33bytes
|
||||
.push_if_needed(index.into(), bytes),
|
||||
Addressbytes::P2PKH(bytes) => self
|
||||
.p2pkhindex_to_p2pkhaddressbytes
|
||||
AddressBytes::P2PKH(bytes) => self
|
||||
.p2pkhindex_to_p2pkhbytes
|
||||
.push_if_needed(index.into(), bytes),
|
||||
Addressbytes::P2SH(bytes) => self
|
||||
.p2shindex_to_p2shaddressbytes
|
||||
AddressBytes::P2SH(bytes) => self
|
||||
.p2shindex_to_p2shbytes
|
||||
.push_if_needed(index.into(), bytes),
|
||||
Addressbytes::P2WPKH(bytes) => self
|
||||
.p2wpkhindex_to_p2wpkhaddressbytes
|
||||
AddressBytes::P2WPKH(bytes) => self
|
||||
.p2wpkhindex_to_p2wpkhbytes
|
||||
.push_if_needed(index.into(), bytes),
|
||||
Addressbytes::P2WSH(bytes) => self
|
||||
.p2wshindex_to_p2wshaddressbytes
|
||||
AddressBytes::P2WSH(bytes) => self
|
||||
.p2wshindex_to_p2wshbytes
|
||||
.push_if_needed(index.into(), bytes),
|
||||
Addressbytes::P2TR(bytes) => self
|
||||
.p2trindex_to_p2traddressbytes
|
||||
AddressBytes::P2TR(bytes) => self
|
||||
.p2trindex_to_p2trbytes
|
||||
.push_if_needed(index.into(), bytes),
|
||||
AddressBytes::P2A(bytes) => self
|
||||
.p2aindex_to_p2abytes
|
||||
.push_if_needed(index.into(), bytes),
|
||||
}
|
||||
}
|
||||
@@ -610,20 +501,15 @@ impl Vecs {
|
||||
|
||||
pub fn as_any_vecs(&self) -> Vec<&dyn AnyStoredVec> {
|
||||
vec![
|
||||
self.addressindex_to_addresstype.any_vec(),
|
||||
self.addressindex_to_addresstypeindex.any_vec(),
|
||||
self.addressindex_to_height.any_vec(),
|
||||
self.emptyoutputindex_to_txindex.any_vec(),
|
||||
self.height_to_blockhash.any_vec(),
|
||||
self.height_to_difficulty.any_vec(),
|
||||
self.height_to_first_addressindex.any_vec(),
|
||||
self.height_to_first_emptyindex.any_vec(),
|
||||
self.height_to_first_multisigindex.any_vec(),
|
||||
self.height_to_first_emptyoutputindex.any_vec(),
|
||||
self.height_to_first_inputindex.any_vec(),
|
||||
self.height_to_first_opreturnindex.any_vec(),
|
||||
self.height_to_first_pushonlyindex.any_vec(),
|
||||
self.height_to_first_txindex.any_vec(),
|
||||
self.height_to_first_txinindex.any_vec(),
|
||||
self.height_to_first_txoutindex.any_vec(),
|
||||
self.height_to_first_unknownindex.any_vec(),
|
||||
self.height_to_first_outputindex.any_vec(),
|
||||
self.height_to_first_p2aindex.any_vec(),
|
||||
self.height_to_first_p2msindex.any_vec(),
|
||||
self.height_to_first_p2pk33index.any_vec(),
|
||||
self.height_to_first_p2pk65index.any_vec(),
|
||||
self.height_to_first_p2pkhindex.any_vec(),
|
||||
@@ -631,61 +517,48 @@ impl Vecs {
|
||||
self.height_to_first_p2trindex.any_vec(),
|
||||
self.height_to_first_p2wpkhindex.any_vec(),
|
||||
self.height_to_first_p2wshindex.any_vec(),
|
||||
self.height_to_total_size.any_vec(),
|
||||
self.height_to_first_txindex.any_vec(),
|
||||
self.height_to_first_unknownoutputindex.any_vec(),
|
||||
self.height_to_timestamp.any_vec(),
|
||||
self.height_to_total_size.any_vec(),
|
||||
self.height_to_weight.any_vec(),
|
||||
self.p2pk33index_to_p2pk33addressbytes.any_vec(),
|
||||
self.p2pk65index_to_p2pk65addressbytes.any_vec(),
|
||||
self.p2pkhindex_to_p2pkhaddressbytes.any_vec(),
|
||||
self.p2shindex_to_p2shaddressbytes.any_vec(),
|
||||
self.p2trindex_to_p2traddressbytes.any_vec(),
|
||||
self.p2wpkhindex_to_p2wpkhaddressbytes.any_vec(),
|
||||
self.p2wshindex_to_p2wshaddressbytes.any_vec(),
|
||||
self.txindex_to_first_txinindex.any_vec(),
|
||||
self.txindex_to_first_txoutindex.any_vec(),
|
||||
self.txindex_to_height.any_vec(),
|
||||
self.txindex_to_locktime.any_vec(),
|
||||
self.txindex_to_txid.any_vec(),
|
||||
self.inputindex_to_outputindex.any_vec(),
|
||||
self.opreturnindex_to_txindex.any_vec(),
|
||||
self.outputindex_to_outputtype.any_vec(),
|
||||
self.outputindex_to_outputtypeindex.any_vec(),
|
||||
self.outputindex_to_value.any_vec(),
|
||||
self.p2aindex_to_p2abytes.any_vec(),
|
||||
self.p2msindex_to_txindex.any_vec(),
|
||||
self.p2pk33index_to_p2pk33bytes.any_vec(),
|
||||
self.p2pk65index_to_p2pk65bytes.any_vec(),
|
||||
self.p2pkhindex_to_p2pkhbytes.any_vec(),
|
||||
self.p2shindex_to_p2shbytes.any_vec(),
|
||||
self.p2trindex_to_p2trbytes.any_vec(),
|
||||
self.p2wpkhindex_to_p2wpkhbytes.any_vec(),
|
||||
self.p2wshindex_to_p2wshbytes.any_vec(),
|
||||
self.txindex_to_base_size.any_vec(),
|
||||
self.txindex_to_total_size.any_vec(),
|
||||
self.txindex_to_first_inputindex.any_vec(),
|
||||
self.txindex_to_first_outputindex.any_vec(),
|
||||
self.txindex_to_is_explicitly_rbf.any_vec(),
|
||||
self.txindex_to_rawlocktime.any_vec(),
|
||||
self.txindex_to_total_size.any_vec(),
|
||||
self.txindex_to_txid.any_vec(),
|
||||
self.txindex_to_txversion.any_vec(),
|
||||
self.txinindex_to_txoutindex.any_vec(),
|
||||
self.txoutindex_to_addressindex.any_vec(),
|
||||
self.txoutindex_to_value.any_vec(),
|
||||
self.emptyindex_to_height.any_vec(),
|
||||
self.multisigindex_to_height.any_vec(),
|
||||
self.opreturnindex_to_height.any_vec(),
|
||||
self.pushonlyindex_to_height.any_vec(),
|
||||
self.txinindex_to_height.any_vec(),
|
||||
self.txoutindex_to_height.any_vec(),
|
||||
self.unknownindex_to_height.any_vec(),
|
||||
self.p2pk33index_to_height.any_vec(),
|
||||
self.p2pk65index_to_height.any_vec(),
|
||||
self.p2pkhindex_to_height.any_vec(),
|
||||
self.p2shindex_to_height.any_vec(),
|
||||
self.p2trindex_to_height.any_vec(),
|
||||
self.p2wpkhindex_to_height.any_vec(),
|
||||
self.p2wshindex_to_height.any_vec(),
|
||||
self.unknownoutputindex_to_txindex.any_vec(),
|
||||
]
|
||||
}
|
||||
|
||||
fn as_mut_any_vecs(&mut self) -> Vec<&mut dyn AnyIndexedVec> {
|
||||
vec![
|
||||
&mut self.addressindex_to_addresstype,
|
||||
&mut self.addressindex_to_addresstypeindex,
|
||||
&mut self.addressindex_to_height,
|
||||
&mut self.emptyoutputindex_to_txindex,
|
||||
&mut self.height_to_blockhash,
|
||||
&mut self.height_to_difficulty,
|
||||
&mut self.height_to_first_addressindex,
|
||||
&mut self.height_to_first_emptyindex,
|
||||
&mut self.height_to_first_multisigindex,
|
||||
&mut self.height_to_first_emptyoutputindex,
|
||||
&mut self.height_to_first_inputindex,
|
||||
&mut self.height_to_first_opreturnindex,
|
||||
&mut self.height_to_first_pushonlyindex,
|
||||
&mut self.height_to_first_txindex,
|
||||
&mut self.height_to_first_txinindex,
|
||||
&mut self.height_to_first_txoutindex,
|
||||
&mut self.height_to_first_unknownindex,
|
||||
&mut self.height_to_first_outputindex,
|
||||
&mut self.height_to_first_p2aindex,
|
||||
&mut self.height_to_first_p2msindex,
|
||||
&mut self.height_to_first_p2pk33index,
|
||||
&mut self.height_to_first_p2pk65index,
|
||||
&mut self.height_to_first_p2pkhindex,
|
||||
@@ -693,42 +566,34 @@ impl Vecs {
|
||||
&mut self.height_to_first_p2trindex,
|
||||
&mut self.height_to_first_p2wpkhindex,
|
||||
&mut self.height_to_first_p2wshindex,
|
||||
&mut self.height_to_total_size,
|
||||
&mut self.height_to_first_txindex,
|
||||
&mut self.height_to_first_unknownoutputindex,
|
||||
&mut self.height_to_timestamp,
|
||||
&mut self.height_to_total_size,
|
||||
&mut self.height_to_weight,
|
||||
&mut self.p2pk33index_to_p2pk33addressbytes,
|
||||
&mut self.p2pk65index_to_p2pk65addressbytes,
|
||||
&mut self.p2pkhindex_to_p2pkhaddressbytes,
|
||||
&mut self.p2shindex_to_p2shaddressbytes,
|
||||
&mut self.p2trindex_to_p2traddressbytes,
|
||||
&mut self.p2wpkhindex_to_p2wpkhaddressbytes,
|
||||
&mut self.p2wshindex_to_p2wshaddressbytes,
|
||||
&mut self.txindex_to_first_txinindex,
|
||||
&mut self.txindex_to_first_txoutindex,
|
||||
&mut self.txindex_to_height,
|
||||
&mut self.txindex_to_locktime,
|
||||
&mut self.txindex_to_txid,
|
||||
&mut self.inputindex_to_outputindex,
|
||||
&mut self.opreturnindex_to_txindex,
|
||||
&mut self.outputindex_to_outputtype,
|
||||
&mut self.outputindex_to_outputtypeindex,
|
||||
&mut self.outputindex_to_value,
|
||||
&mut self.p2aindex_to_p2abytes,
|
||||
&mut self.p2msindex_to_txindex,
|
||||
&mut self.p2pk33index_to_p2pk33bytes,
|
||||
&mut self.p2pk65index_to_p2pk65bytes,
|
||||
&mut self.p2pkhindex_to_p2pkhbytes,
|
||||
&mut self.p2shindex_to_p2shbytes,
|
||||
&mut self.p2trindex_to_p2trbytes,
|
||||
&mut self.p2wpkhindex_to_p2wpkhbytes,
|
||||
&mut self.p2wshindex_to_p2wshbytes,
|
||||
&mut self.txindex_to_base_size,
|
||||
&mut self.txindex_to_total_size,
|
||||
&mut self.txindex_to_first_inputindex,
|
||||
&mut self.txindex_to_first_outputindex,
|
||||
&mut self.txindex_to_is_explicitly_rbf,
|
||||
&mut self.txindex_to_rawlocktime,
|
||||
&mut self.txindex_to_total_size,
|
||||
&mut self.txindex_to_txid,
|
||||
&mut self.txindex_to_txversion,
|
||||
&mut self.txinindex_to_txoutindex,
|
||||
&mut self.txoutindex_to_addressindex,
|
||||
&mut self.txoutindex_to_value,
|
||||
&mut self.emptyindex_to_height,
|
||||
&mut self.multisigindex_to_height,
|
||||
&mut self.opreturnindex_to_height,
|
||||
&mut self.pushonlyindex_to_height,
|
||||
&mut self.txinindex_to_height,
|
||||
&mut self.txoutindex_to_height,
|
||||
&mut self.unknownindex_to_height,
|
||||
&mut self.p2pk33index_to_height,
|
||||
&mut self.p2pk65index_to_height,
|
||||
&mut self.p2pkhindex_to_height,
|
||||
&mut self.p2shindex_to_height,
|
||||
&mut self.p2trindex_to_height,
|
||||
&mut self.p2wpkhindex_to_height,
|
||||
&mut self.p2wshindex_to_height,
|
||||
&mut self.unknownoutputindex_to_txindex,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a href="https://bsky.app/profile/bitcoinresearchkit.org">
|
||||
<img src="https://img.shields.io/badge/bluesky-blue?link=https%3A%2F%2Fbsky.app%2Fprofile%2Fbitcoinresearchkit.org" alt="Bluesky" />
|
||||
</a>
|
||||
<a href="https://x.com/0xbrk">
|
||||
<a href="https://x.com/brkdotorg">
|
||||
<img src="https://img.shields.io/badge/x.com-black" alt="X" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a href="https://bsky.app/profile/bitcoinresearchkit.org">
|
||||
<img src="https://img.shields.io/badge/bluesky-blue?link=https%3A%2F%2Fbsky.app%2Fprofile%2Fbitcoinresearchkit.org" alt="Bluesky" />
|
||||
</a>
|
||||
<a href="https://x.com/0xbrk">
|
||||
<a href="https://x.com/brkdotorg">
|
||||
<img src="https://img.shields.io/badge/x.com-black" alt="X" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
use bitcoincore_rpc::{Auth, Client};
|
||||
use brk_core::{Height, OutputType, default_bitcoin_path};
|
||||
use brk_parser::Parser;
|
||||
|
||||
fn main() {
|
||||
let i = std::time::Instant::now();
|
||||
|
||||
let bitcoin_dir = default_bitcoin_path();
|
||||
|
||||
let rpc = Box::leak(Box::new(
|
||||
Client::new(
|
||||
"http://localhost:8332",
|
||||
Auth::CookieFile(bitcoin_dir.join(".cookie")),
|
||||
)
|
||||
.unwrap(),
|
||||
));
|
||||
|
||||
// let start = None;
|
||||
// let end = None;
|
||||
|
||||
let parser = Parser::new(bitcoin_dir.join("blocks"), rpc);
|
||||
|
||||
// parser
|
||||
// .parse(start, end)
|
||||
// .iter()
|
||||
// .for_each(|(height, _block, hash)| {
|
||||
// println!("{height}: {hash}");
|
||||
// });
|
||||
|
||||
// println!(
|
||||
// "{}",
|
||||
// parser
|
||||
// .get(Height::new(0))
|
||||
// .txdata
|
||||
// .first()
|
||||
// .unwrap()
|
||||
// .output
|
||||
// .first()
|
||||
// .unwrap()
|
||||
// .script_pubkey
|
||||
// );
|
||||
|
||||
let block_850_000 = parser.get(Height::new(850_000));
|
||||
|
||||
let tx = block_850_000.txdata.iter().find(|tx| {
|
||||
tx.compute_txid().to_string()
|
||||
== "b10c0000004da5a9d1d9b4ae32e09f0b3e62d21a5cce5428d4ad714fb444eb5d"
|
||||
});
|
||||
|
||||
let output = tx.unwrap().tx_out(7).unwrap();
|
||||
|
||||
dbg!(OutputType::from(&output.script_pubkey));
|
||||
|
||||
dbg!(output);
|
||||
|
||||
// println!(
|
||||
// "{}",
|
||||
|
||||
// .txdata
|
||||
// .first()
|
||||
// .unwrap()
|
||||
// .output
|
||||
// .first()
|
||||
// .unwrap()
|
||||
// .value
|
||||
// );
|
||||
|
||||
dbg!(i.elapsed());
|
||||
}
|
||||
@@ -14,7 +14,11 @@ pub struct BlkIndexToBlkRecap {
|
||||
}
|
||||
|
||||
impl BlkIndexToBlkRecap {
|
||||
pub fn import(bitcoin_dir: &Path, blk_index_to_blk_path: &BlkIndexToBlkPath, start: Option<Height>) -> (Self, u16) {
|
||||
pub fn import(
|
||||
bitcoin_dir: &Path,
|
||||
blk_index_to_blk_path: &BlkIndexToBlkPath,
|
||||
start: Option<Height>,
|
||||
) -> (Self, u16) {
|
||||
let path = bitcoin_dir.join("blk_index_to_blk_recap.json");
|
||||
|
||||
let tree = {
|
||||
@@ -40,17 +44,19 @@ impl BlkIndexToBlkRecap {
|
||||
|
||||
let mut unprocessed_keys = self.tree.keys().copied().collect::<BTreeSet<_>>();
|
||||
|
||||
blk_index_to_blk_path.iter().for_each(|(blk_index, blk_path)| {
|
||||
unprocessed_keys.remove(blk_index);
|
||||
if let Some(blk_recap) = self.tree.get(blk_index) {
|
||||
if blk_recap.has_different_modified_time(blk_path) {
|
||||
self.tree.remove(blk_index).unwrap();
|
||||
if min_removed_blk_index.is_none_or(|_blk_index| *blk_index < _blk_index) {
|
||||
min_removed_blk_index.replace(*blk_index);
|
||||
blk_index_to_blk_path
|
||||
.iter()
|
||||
.for_each(|(blk_index, blk_path)| {
|
||||
unprocessed_keys.remove(blk_index);
|
||||
if let Some(blk_recap) = self.tree.get(blk_index) {
|
||||
if blk_recap.has_different_modified_time(blk_path) {
|
||||
self.tree.remove(blk_index).unwrap();
|
||||
if min_removed_blk_index.is_none_or(|_blk_index| *blk_index < _blk_index) {
|
||||
min_removed_blk_index.replace(*blk_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
unprocessed_keys.into_iter().for_each(|blk_index| {
|
||||
self.tree.remove(&blk_index).unwrap();
|
||||
@@ -71,7 +77,11 @@ impl BlkIndexToBlkRecap {
|
||||
|
||||
let mut start = None;
|
||||
|
||||
if let Some(found) = self.tree.iter().find(|(_, recap)| recap.max_height >= height) {
|
||||
if let Some(found) = self
|
||||
.tree
|
||||
.iter()
|
||||
.find(|(_, recap)| recap.max_height >= height)
|
||||
{
|
||||
start = Some(*found.0);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a href="https://bsky.app/profile/bitcoinresearchkit.org">
|
||||
<img src="https://img.shields.io/badge/bluesky-blue?link=https%3A%2F%2Fbsky.app%2Fprofile%2Fbitcoinresearchkit.org" alt="Bluesky" />
|
||||
</a>
|
||||
<a href="https://x.com/0xbrk">
|
||||
<a href="https://x.com/brkdotorg">
|
||||
<img src="https://img.shields.io/badge/x.com-black" alt="X" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -11,10 +11,10 @@ pub fn main() -> color_eyre::Result<()> {
|
||||
|
||||
let compressed = true;
|
||||
|
||||
let mut indexer = Indexer::new(outputs_dir.join("indexed"), compressed, true)?;
|
||||
let mut indexer = Indexer::new(outputs_dir, compressed, true)?;
|
||||
indexer.import_vecs()?;
|
||||
|
||||
let mut computer = Computer::new(outputs_dir.join("computed"), None, compressed);
|
||||
let mut computer = Computer::new(outputs_dir, None, compressed);
|
||||
computer.import_vecs()?;
|
||||
|
||||
let query = Query::build(&indexer, &computer);
|
||||
|
||||
@@ -4,92 +4,89 @@ use color_eyre::eyre::eyre;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Index {
|
||||
Addressindex,
|
||||
Dateindex,
|
||||
DateIndex,
|
||||
DecadeIndex,
|
||||
DifficultyEpoch,
|
||||
EmptyOutputIndex,
|
||||
HalvingEpoch,
|
||||
Height,
|
||||
P2PK33index,
|
||||
P2PK65index,
|
||||
P2PKHindex,
|
||||
P2SHindex,
|
||||
P2TRindex,
|
||||
P2WPKHindex,
|
||||
P2WSHindex,
|
||||
Txindex,
|
||||
Txinindex,
|
||||
Txoutindex,
|
||||
Weekindex,
|
||||
Monthindex,
|
||||
Quarterindex,
|
||||
Yearindex,
|
||||
Decadeindex,
|
||||
Difficultyepoch,
|
||||
Halvingepoch,
|
||||
Emptyindex,
|
||||
Multisigindex,
|
||||
Opreturnindex,
|
||||
Pushonlyindex,
|
||||
Unknownindex,
|
||||
InputIndex,
|
||||
MonthIndex,
|
||||
OpReturnIndex,
|
||||
OutputIndex,
|
||||
P2AIndex,
|
||||
P2MSIndex,
|
||||
P2PK33Index,
|
||||
P2PK65Index,
|
||||
P2PKHIndex,
|
||||
P2SHIndex,
|
||||
P2TRIndex,
|
||||
P2WPKHIndex,
|
||||
P2WSHIndex,
|
||||
QuarterIndex,
|
||||
TxIndex,
|
||||
UnknownOutputIndex,
|
||||
WeekIndex,
|
||||
YearIndex,
|
||||
}
|
||||
|
||||
impl Index {
|
||||
pub fn all() -> [Self; 25] {
|
||||
pub fn all() -> [Self; 24] {
|
||||
[
|
||||
Self::DateIndex,
|
||||
Self::DecadeIndex,
|
||||
Self::DifficultyEpoch,
|
||||
Self::EmptyOutputIndex,
|
||||
Self::HalvingEpoch,
|
||||
Self::Height,
|
||||
Self::Dateindex,
|
||||
Self::Weekindex,
|
||||
Self::Difficultyepoch,
|
||||
Self::Monthindex,
|
||||
Self::Quarterindex,
|
||||
Self::Yearindex,
|
||||
Self::Decadeindex,
|
||||
Self::Halvingepoch,
|
||||
Self::Addressindex,
|
||||
Self::P2PK33index,
|
||||
Self::P2PK65index,
|
||||
Self::P2PKHindex,
|
||||
Self::P2SHindex,
|
||||
Self::P2TRindex,
|
||||
Self::P2WPKHindex,
|
||||
Self::P2WSHindex,
|
||||
Self::Txindex,
|
||||
Self::Txinindex,
|
||||
Self::Txoutindex,
|
||||
Self::Emptyindex,
|
||||
Self::Multisigindex,
|
||||
Self::Opreturnindex,
|
||||
Self::Pushonlyindex,
|
||||
Self::Unknownindex,
|
||||
Self::InputIndex,
|
||||
Self::MonthIndex,
|
||||
Self::OpReturnIndex,
|
||||
Self::OutputIndex,
|
||||
Self::P2AIndex,
|
||||
Self::P2MSIndex,
|
||||
Self::P2PK33Index,
|
||||
Self::P2PK65Index,
|
||||
Self::P2PKHIndex,
|
||||
Self::P2SHIndex,
|
||||
Self::P2TRIndex,
|
||||
Self::P2WPKHIndex,
|
||||
Self::P2WSHIndex,
|
||||
Self::QuarterIndex,
|
||||
Self::TxIndex,
|
||||
Self::UnknownOutputIndex,
|
||||
Self::WeekIndex,
|
||||
Self::YearIndex,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn possible_values(&self) -> &[&str] {
|
||||
// Always have the "correct" id at the end
|
||||
match self {
|
||||
Self::DateIndex => &["d", "date", "dateindex"],
|
||||
Self::DecadeIndex => &["decade", "decadeindex"],
|
||||
Self::DifficultyEpoch => &["difficulty", "difficultyepoch"],
|
||||
Self::EmptyOutputIndex => &["empty", "emptyoutputindex"],
|
||||
Self::HalvingEpoch => &["h", "halving", "halvingepoch"],
|
||||
Self::Height => &["h", "height"],
|
||||
Self::Dateindex => &["d", "date", "dateindex"],
|
||||
Self::Weekindex => &["w", "week", "weekindex"],
|
||||
Self::Difficultyepoch => &["difficulty", "difficultyepoch"],
|
||||
Self::Monthindex => &["m", "month", "monthindex"],
|
||||
Self::Quarterindex => &["q", "quarter", "quarterindex"],
|
||||
Self::Yearindex => &["y", "year", "yearindex"],
|
||||
Self::Decadeindex => &["decade", "decadeindex"],
|
||||
Self::Halvingepoch => &["h", "halving", "halvingepoch"],
|
||||
Self::Txindex => &["tx", "txindex"],
|
||||
Self::Txinindex => &["txin", "txinindex"],
|
||||
Self::Txoutindex => &["txout", "txoutindex"],
|
||||
Self::Addressindex => &["a", "address", "addressindex"],
|
||||
Self::P2PK33index => &["p2pk33", "p2pk33index"],
|
||||
Self::P2PK65index => &["p2pk65", "p2pk65index"],
|
||||
Self::P2PKHindex => &["p2pkh", "p2pkhindex"],
|
||||
Self::P2SHindex => &["p2sh", "p2shindex"],
|
||||
Self::P2TRindex => &["p2tr", "p2trindex"],
|
||||
Self::P2WPKHindex => &["p2wpkh", "p2wpkhindex"],
|
||||
Self::P2WSHindex => &["p2wsh", "p2wshindex"],
|
||||
Self::Emptyindex => &["empty", "emptyindex"],
|
||||
Self::Multisigindex => &["multisig", "multisigindex"],
|
||||
Self::Opreturnindex => &["opreturn", "opreturnindex"],
|
||||
Self::Pushonlyindex => &["pushonly", "pushonlyindex"],
|
||||
Self::Unknownindex => &["unknown", "unknownindex"],
|
||||
Self::InputIndex => &["txin", "inputindex"],
|
||||
Self::MonthIndex => &["m", "month", "monthindex"],
|
||||
Self::OpReturnIndex => &["opreturn", "opreturnindex"],
|
||||
Self::OutputIndex => &["txout", "outputindex"],
|
||||
Self::P2AIndex => &["p2a", "p2aindex"],
|
||||
Self::P2MSIndex => &["p2ms", "p2msindex"],
|
||||
Self::P2PK33Index => &["p2pk33", "p2pk33index"],
|
||||
Self::P2PK65Index => &["p2pk65", "p2pk65index"],
|
||||
Self::P2PKHIndex => &["p2pkh", "p2pkhindex"],
|
||||
Self::P2SHIndex => &["p2sh", "p2shindex"],
|
||||
Self::P2TRIndex => &["p2tr", "p2trindex"],
|
||||
Self::P2WPKHIndex => &["p2wpkh", "p2wpkhindex"],
|
||||
Self::P2WSHIndex => &["p2wsh", "p2wshindex"],
|
||||
Self::QuarterIndex => &["q", "quarter", "quarterindex"],
|
||||
Self::TxIndex => &["tx", "txindex"],
|
||||
Self::UnknownOutputIndex => &["unknown", "unknownoutputindex"],
|
||||
Self::WeekIndex => &["w", "week", "weekindex"],
|
||||
Self::YearIndex => &["y", "year", "yearindex"],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,32 +114,33 @@ impl TryFrom<&str> for Index {
|
||||
type Error = color_eyre::Report;
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
Ok(match value.to_lowercase().as_str() {
|
||||
v if (Self::Dateindex).possible_values().contains(&v) => Self::Dateindex,
|
||||
v if (Self::DateIndex).possible_values().contains(&v) => Self::DateIndex,
|
||||
v if (Self::DecadeIndex).possible_values().contains(&v) => Self::DecadeIndex,
|
||||
v if (Self::DifficultyEpoch).possible_values().contains(&v) => Self::DifficultyEpoch,
|
||||
v if (Self::EmptyOutputIndex).possible_values().contains(&v) => Self::EmptyOutputIndex,
|
||||
v if (Self::HalvingEpoch).possible_values().contains(&v) => Self::HalvingEpoch,
|
||||
v if (Self::Height).possible_values().contains(&v) => Self::Height,
|
||||
v if (Self::Txindex).possible_values().contains(&v) => Self::Txindex,
|
||||
v if (Self::Txinindex).possible_values().contains(&v) => Self::Txinindex,
|
||||
v if (Self::Txoutindex).possible_values().contains(&v) => Self::Txoutindex,
|
||||
v if (Self::Addressindex).possible_values().contains(&v) => Self::Addressindex,
|
||||
v if (Self::P2PK33index).possible_values().contains(&v) => Self::P2PK33index,
|
||||
v if (Self::P2PK65index).possible_values().contains(&v) => Self::P2PK65index,
|
||||
v if (Self::P2PKHindex).possible_values().contains(&v) => Self::P2PKHindex,
|
||||
v if (Self::P2SHindex).possible_values().contains(&v) => Self::P2SHindex,
|
||||
v if (Self::P2TRindex).possible_values().contains(&v) => Self::P2TRindex,
|
||||
v if (Self::P2WPKHindex).possible_values().contains(&v) => Self::P2WPKHindex,
|
||||
v if (Self::P2WSHindex).possible_values().contains(&v) => Self::P2WSHindex,
|
||||
v if (Self::Weekindex).possible_values().contains(&v) => Self::Weekindex,
|
||||
v if (Self::Monthindex).possible_values().contains(&v) => Self::Monthindex,
|
||||
v if (Self::Yearindex).possible_values().contains(&v) => Self::Yearindex,
|
||||
v if (Self::Decadeindex).possible_values().contains(&v) => Self::Decadeindex,
|
||||
v if (Self::Difficultyepoch).possible_values().contains(&v) => Self::Difficultyepoch,
|
||||
v if (Self::Halvingepoch).possible_values().contains(&v) => Self::Halvingepoch,
|
||||
v if (Self::Quarterindex).possible_values().contains(&v) => Self::Quarterindex,
|
||||
v if (Self::Quarterindex).possible_values().contains(&v) => Self::Quarterindex,
|
||||
v if (Self::Emptyindex).possible_values().contains(&v) => Self::Emptyindex,
|
||||
v if (Self::Multisigindex).possible_values().contains(&v) => Self::Multisigindex,
|
||||
v if (Self::Opreturnindex).possible_values().contains(&v) => Self::Opreturnindex,
|
||||
v if (Self::Pushonlyindex).possible_values().contains(&v) => Self::Pushonlyindex,
|
||||
v if (Self::Unknownindex).possible_values().contains(&v) => Self::Unknownindex,
|
||||
v if (Self::InputIndex).possible_values().contains(&v) => Self::InputIndex,
|
||||
v if (Self::MonthIndex).possible_values().contains(&v) => Self::MonthIndex,
|
||||
v if (Self::OpReturnIndex).possible_values().contains(&v) => Self::OpReturnIndex,
|
||||
v if (Self::OutputIndex).possible_values().contains(&v) => Self::OutputIndex,
|
||||
v if (Self::P2AIndex).possible_values().contains(&v) => Self::P2AIndex,
|
||||
v if (Self::P2MSIndex).possible_values().contains(&v) => Self::P2MSIndex,
|
||||
v if (Self::P2PK33Index).possible_values().contains(&v) => Self::P2PK33Index,
|
||||
v if (Self::P2PK65Index).possible_values().contains(&v) => Self::P2PK65Index,
|
||||
v if (Self::P2PKHIndex).possible_values().contains(&v) => Self::P2PKHIndex,
|
||||
v if (Self::P2SHIndex).possible_values().contains(&v) => Self::P2SHIndex,
|
||||
v if (Self::P2TRIndex).possible_values().contains(&v) => Self::P2TRIndex,
|
||||
v if (Self::P2WPKHIndex).possible_values().contains(&v) => Self::P2WPKHIndex,
|
||||
v if (Self::P2WSHIndex).possible_values().contains(&v) => Self::P2WSHIndex,
|
||||
v if (Self::QuarterIndex).possible_values().contains(&v) => Self::QuarterIndex,
|
||||
v if (Self::QuarterIndex).possible_values().contains(&v) => Self::QuarterIndex,
|
||||
v if (Self::TxIndex).possible_values().contains(&v) => Self::TxIndex,
|
||||
v if (Self::WeekIndex).possible_values().contains(&v) => Self::WeekIndex,
|
||||
v if (Self::YearIndex).possible_values().contains(&v) => Self::YearIndex,
|
||||
v if (Self::UnknownOutputIndex).possible_values().contains(&v) => {
|
||||
Self::UnknownOutputIndex
|
||||
}
|
||||
_ => return Err(eyre!("Bad index")),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ color-eyre = { workspace = true }
|
||||
jiff = { workspace = true }
|
||||
log = { workspace = true }
|
||||
minreq = { workspace = true }
|
||||
oxc = { version = "0.64.0", features = ["codegen", "minifier"] }
|
||||
oxc = { version = "0.66.0", features = ["codegen", "minifier"] }
|
||||
serde = { workspace = true }
|
||||
tokio = { version = "1.44.2", features = ["full"] }
|
||||
tower-http = { version = "0.6.2", features = ["compression-full", "trace"] }
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a href="https://bsky.app/profile/bitcoinresearchkit.org">
|
||||
<img src="https://img.shields.io/badge/bluesky-blue?link=https%3A%2F%2Fbsky.app%2Fprofile%2Fbitcoinresearchkit.org" alt="Bluesky" />
|
||||
</a>
|
||||
<a href="https://x.com/0xbrk">
|
||||
<a href="https://x.com/brkdotorg">
|
||||
<img src="https://img.shields.io/badge/x.com-black" alt="X" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -32,14 +32,14 @@ pub fn main() -> color_eyre::Result<()> {
|
||||
|
||||
let compressed = true;
|
||||
|
||||
let mut indexer = Indexer::new(outputs_dir.join("indexed"), compressed, true)?;
|
||||
let mut indexer = Indexer::new(outputs_dir, compressed, true)?;
|
||||
indexer.import_stores()?;
|
||||
indexer.import_vecs()?;
|
||||
|
||||
let fetcher = Some(Fetcher::import(None)?);
|
||||
|
||||
let mut computer = Computer::new(outputs_dir.join("computed"), fetcher, compressed);
|
||||
computer.import_stores()?;
|
||||
let mut computer = Computer::new(outputs_dir, fetcher, compressed);
|
||||
computer.import_stores(&indexer)?;
|
||||
computer.import_vecs()?;
|
||||
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a href="https://bsky.app/profile/bitcoinresearchkit.org">
|
||||
<img src="https://img.shields.io/badge/bluesky-blue?link=https%3A%2F%2Fbsky.app%2Fprofile%2Fbitcoinresearchkit.org" alt="Bluesky" />
|
||||
</a>
|
||||
<a href="https://x.com/0xbrk">
|
||||
<a href="https://x.com/brkdotorg">
|
||||
<img src="https://img.shields.io/badge/x.com-black" alt="X" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -61,17 +61,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
dbg!(vec.get(5)?);
|
||||
dbg!(vec.get(20)?);
|
||||
|
||||
vec.iter(|(_, v, ..)| {
|
||||
dbg!(v);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
vec.iter_from(5, |(_, v, ..)| {
|
||||
dbg!(v);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
dbg!(vec.collect_signed_range(Some(-5), None)?);
|
||||
|
||||
vec.push(vec.len() as u32);
|
||||
dbg!(vec.iter().last());
|
||||
|
||||
dbg!(vec.into_iter().collect::<Vec<_>>());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
+107
-17
@@ -52,6 +52,16 @@ where
|
||||
Self::Raw(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> StoredVecIterator<'_, I, T> {
|
||||
self.into_iter()
|
||||
}
|
||||
|
||||
pub fn iter_at(&self, i: I) -> StoredVecIterator<'_, I, T> {
|
||||
let mut iter = self.into_iter();
|
||||
iter.set(i);
|
||||
iter
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T> DynamicVec for StoredVec<I, T>
|
||||
@@ -69,13 +79,6 @@ where
|
||||
StoredVec::Compressed(v) => v.get_stored_(index, guard),
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn cached_get_stored_(&mut self, index: usize, guard: &Mmap) -> Result<Option<T>> {
|
||||
match self {
|
||||
StoredVec::Raw(v) => v.cached_get_stored_(index, guard),
|
||||
StoredVec::Compressed(v) => v.cached_get_stored_(index, guard),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mmap(&self) -> &ArcSwap<Mmap> {
|
||||
@@ -137,16 +140,6 @@ where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
{
|
||||
fn iter_from<F>(&mut self, index: I, f: F) -> Result<()>
|
||||
where
|
||||
F: FnMut((I, T, &mut dyn DynamicVec<I = I, T = T>)) -> Result<()>,
|
||||
{
|
||||
match self {
|
||||
StoredVec::Raw(v) => v.iter_from(index, f),
|
||||
StoredVec::Compressed(v) => v.iter_from(index, f),
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_range(&self, from: Option<usize>, to: Option<usize>) -> Result<Vec<Self::T>> {
|
||||
match self {
|
||||
StoredVec::Raw(v) => v.collect_range(from, to),
|
||||
@@ -239,3 +232,100 @@ where
|
||||
GenericVec::file_name(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum StoredVecIterator<'a, I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
{
|
||||
Raw(RawVecIterator<'a, I, T>),
|
||||
Compressed(CompressedVecIterator<'a, I, T>),
|
||||
}
|
||||
|
||||
impl<I, T> StoredVecIterator<'_, I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
{
|
||||
#[inline]
|
||||
pub fn unwrap_get_inner(&mut self, i: I) -> T {
|
||||
self.get_(i.unwrap_to_usize()).unwrap().1.into_inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_inner(&mut self, i: I) -> Option<T> {
|
||||
self.get_(i.unwrap_to_usize()).map(|(_, v)| v.into_inner())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(&mut self, i: I) -> Option<(I, Value<'_, T>)> {
|
||||
self.get_(i.unwrap_to_usize())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_(&mut self, i: usize) -> Option<(I, Value<'_, T>)> {
|
||||
match self {
|
||||
Self::Compressed(iter) => iter.get_(i),
|
||||
Self::Raw(iter) => iter.get_(i),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, i: I) {
|
||||
match self {
|
||||
Self::Compressed(iter) => {
|
||||
iter.set(i);
|
||||
}
|
||||
Self::Raw(iter) => {
|
||||
iter.set(i);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I, T> Iterator for StoredVecIterator<'a, I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
{
|
||||
type Item = (I, Value<'a, T>);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self {
|
||||
Self::Compressed(i) => i.next(),
|
||||
Self::Raw(i) => i.next(),
|
||||
}
|
||||
}
|
||||
|
||||
fn last(self) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match self {
|
||||
Self::Compressed(i) => i.last(),
|
||||
Self::Raw(i) => i.last(),
|
||||
}
|
||||
}
|
||||
|
||||
fn skip(self, _: usize) -> std::iter::Skip<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
todo!("")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I, T> IntoIterator for &'a StoredVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
{
|
||||
type Item = (I, Value<'a, T>);
|
||||
type IntoIter = StoredVecIterator<'a, I, T>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
StoredVec::Compressed(v) => StoredVecIterator::Compressed(v.into_iter()),
|
||||
StoredVec::Raw(v) => StoredVecIterator::Raw(v.into_iter()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,18 +16,6 @@ pub trait DynamicVec: Send + Sync {
|
||||
self.get_(index.to_usize()?)
|
||||
}
|
||||
#[inline]
|
||||
fn cached_get(&mut self, index: Self::I) -> Result<Option<Value<Self::T>>> {
|
||||
self.cached_get_(index.to_usize()?)
|
||||
}
|
||||
#[inline]
|
||||
fn unwrap_cached_get(&mut self, index: Self::I) -> Option<Self::T> {
|
||||
self.cached_get(index).unwrap().map(Value::into_inner)
|
||||
}
|
||||
#[inline]
|
||||
fn double_unwrap_cached_get(&mut self, index: Self::I) -> Self::T {
|
||||
self.unwrap_cached_get(index).unwrap()
|
||||
}
|
||||
#[inline]
|
||||
fn get_(&self, index: usize) -> Result<Option<Value<Self::T>>> {
|
||||
match self.index_to_pushed_index(index) {
|
||||
Ok(index) => {
|
||||
@@ -45,40 +33,13 @@ pub trait DynamicVec: Send + Sync {
|
||||
.map(Value::Owned))
|
||||
}
|
||||
fn get_stored_(&self, index: usize, mmap: &Mmap) -> Result<Option<Self::T>>;
|
||||
fn get_last(&self) -> Result<Option<Value<Self::T>>> {
|
||||
let len = self.len();
|
||||
if len == 0 {
|
||||
return Ok(None);
|
||||
}
|
||||
self.get_(len - 1)
|
||||
}
|
||||
#[inline]
|
||||
fn cached_get_(&mut self, index: usize) -> Result<Option<Value<Self::T>>> {
|
||||
match self.index_to_pushed_index(index) {
|
||||
Ok(index) => {
|
||||
if let Some(index) = index {
|
||||
return Ok(self.pushed().get(index).map(Value::Ref));
|
||||
}
|
||||
}
|
||||
Err(Error::IndexTooHigh) => return Ok(None),
|
||||
Err(Error::IndexTooLow) => {}
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
|
||||
let mmap = Arc::clone(self.guard().as_ref().unwrap());
|
||||
|
||||
Ok(self
|
||||
.cached_get_stored_(index.to_usize()?, &mmap)?
|
||||
.map(Value::Owned))
|
||||
}
|
||||
fn cached_get_stored_(&mut self, index: usize, mmap: &Mmap) -> Result<Option<Self::T>>;
|
||||
fn cached_get_last(&mut self) -> Result<Option<Value<Self::T>>> {
|
||||
let len = self.len();
|
||||
if len == 0 {
|
||||
return Ok(None);
|
||||
}
|
||||
self.cached_get_(len - 1)
|
||||
}
|
||||
// fn last(&self) -> Result<Option<Value<Self::T>>> {
|
||||
// let len = self.len();
|
||||
// if len == 0 {
|
||||
// return Ok(None);
|
||||
// }
|
||||
// self.get_(len - 1)
|
||||
// }
|
||||
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
|
||||
@@ -10,7 +10,6 @@ use axum::{
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use memmap2::Mmap;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::{Error, Result, Version};
|
||||
|
||||
@@ -99,40 +98,16 @@ where
|
||||
Self::I::to_string()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn iter<F>(&mut self, f: F) -> Result<()>
|
||||
where
|
||||
F: FnMut(
|
||||
(
|
||||
Self::I,
|
||||
Self::T,
|
||||
&mut dyn DynamicVec<I = Self::I, T = Self::T>,
|
||||
),
|
||||
) -> Result<()>,
|
||||
{
|
||||
self.iter_from(Self::I::default(), f)
|
||||
}
|
||||
|
||||
fn iter_from<F>(&mut self, index: Self::I, f: F) -> Result<()>
|
||||
where
|
||||
F: FnMut(
|
||||
(
|
||||
Self::I,
|
||||
Self::T,
|
||||
&mut dyn DynamicVec<I = Self::I, T = Self::T>,
|
||||
),
|
||||
) -> Result<()>;
|
||||
|
||||
fn flush(&mut self) -> Result<()>;
|
||||
|
||||
fn truncate_if_needed(&mut self, index: Self::I) -> Result<()>;
|
||||
|
||||
fn collect_range(&self, from: Option<usize>, to: Option<usize>) -> Result<Vec<Self::T>>;
|
||||
|
||||
#[inline]
|
||||
fn collect_inclusive_range(&self, from: I, to: I) -> Result<Vec<Self::T>> {
|
||||
self.collect_range(Some(from.to_usize()?), Some(to.to_usize()? + 1))
|
||||
}
|
||||
// #[inline]
|
||||
// fn collect_inclusive_range(&self, from: I, to: I) -> Result<Vec<Self::T>> {
|
||||
// self.collect_range(Some(from.to_usize()?), Some(to.to_usize()? + 1))
|
||||
// }
|
||||
|
||||
#[inline]
|
||||
fn i64_to_usize(i: i64, len: usize) -> usize {
|
||||
@@ -144,6 +119,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn collect_signed_range(&self, from: Option<i64>, to: Option<i64>) -> Result<Vec<Self::T>> {
|
||||
let len = self.len();
|
||||
let from = from.map(|i| Self::i64_to_usize(i, len));
|
||||
@@ -161,7 +137,11 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn collect_range_serde_json(&self, from: Option<i64>, to: Option<i64>) -> Result<Vec<Value>> {
|
||||
fn collect_range_serde_json(
|
||||
&self,
|
||||
from: Option<i64>,
|
||||
to: Option<i64>,
|
||||
) -> Result<Vec<serde_json::Value>> {
|
||||
self.collect_signed_range(from, to)?
|
||||
.into_iter()
|
||||
.map(|v| serde_json::to_value(v).map_err(Error::from))
|
||||
|
||||
@@ -21,6 +21,7 @@ where
|
||||
fn unwrap_to_usize(self) -> usize;
|
||||
fn to_usize(self) -> Result<usize>;
|
||||
fn to_string<'a>() -> &'a str;
|
||||
fn decremented(self) -> Option<Self>;
|
||||
}
|
||||
impl<I> StoredIndex for I
|
||||
where
|
||||
@@ -52,4 +53,9 @@ where
|
||||
fn to_string<'a>() -> &'a str {
|
||||
std::any::type_name::<I>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn decremented(self) -> Option<Self> {
|
||||
self.unwrap_to_usize().checked_sub(1).map(Self::from)
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user