diff --git a/Cargo.lock b/Cargo.lock index ad26f25a4..3d36484d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -648,9 +648,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.18" +version = "1.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" +checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" dependencies = [ "jobserver", "libc", @@ -851,9 +851,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] @@ -1129,7 +1129,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", - "miniz_oxide 0.8.7", + "miniz_oxide 0.8.8", ] [[package]] @@ -1470,9 +1470,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260" +checksum = "1f33145a5cbea837164362c7bd596106eb7c5198f97d1ba6f6ebb3223952e488" dependencies = [ "jiff-static", "jiff-tzdb-platform", @@ -1485,9 +1485,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c" +checksum = "43ce13c40ec6956157a3635d97a1ee2df323b263f09ea14165131289cb0f5c19" dependencies = [ "proc-macro2", "quote", @@ -1555,9 +1555,9 @@ checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "linux-raw-sys" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "lock_api" @@ -1670,9 +1670,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] @@ -1789,9 +1789,9 @@ checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564" [[package]] name = "oxc" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c274a11ab2471eea5f970d943ecb7b64dc9fa21d89ac5c968fc0f48ca9971196" +checksum = "fa680279066565502d5cc612d82dc2841499518f5430d047aff33869ec5592a5" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1832,9 +1832,9 @@ dependencies = [ [[package]] name = "oxc_allocator" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef6db9c542af8b1b0889c4fdbc4dfd0a13c5bec0f94ef39bb826084465d6b1e" +checksum = "3f90c485c4f2781e0c8b4703a5fa205f49ecc6d496d2b88260db27d60f9f1661" dependencies = [ "allocator-api2", "bumpalo", @@ -1846,9 +1846,9 @@ dependencies = [ [[package]] name = "oxc_ast" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c269cf713bed18d74e957045d2b1cf57827333a66aad2b2c136c9f8b79940bd2" +checksum = "2552b2248c0d320c97f865d0620946821e687a0c02200cc6aa08161862447f8d" dependencies = [ "bitflags", "cow-utils", @@ -1863,9 +1863,9 @@ dependencies = [ [[package]] name = "oxc_ast_macros" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1d8afe9d7e4aed37d6e8906250db4872f514c15a244268ce3da09ccb4017900" +checksum = "ccd0b70b7752610fc00a22e3cbf92fa2b0a007b022a976fba75a254f6ea21f18" dependencies = [ "proc-macro2", "quote", @@ -1874,9 +1874,9 @@ dependencies = [ [[package]] name = "oxc_ast_visit" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d360f012f970b3e79f8f9863abb83b373014eb9d1a23fecd7ce33e555cc3151" +checksum = "ef6a46d3d3158668e5d8a9231bce6f5c8abc4a818a48583a254f4aa4a9682fa0" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1886,9 +1886,9 @@ dependencies = [ [[package]] name = "oxc_cfg" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17a48085dd0ca7e8f3ad946a131d8229af783be65cbf4965ff6379e432f6b625" +checksum = "e6e0e5fa83ea1b3bbcc5496cf6acbbc46f7d147cbd342ecf968df500239c73bd" dependencies = [ "bitflags", "itertools", @@ -1901,9 +1901,9 @@ dependencies = [ [[package]] name = "oxc_codegen" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e6d4e1c953205c62effeb61c1da684dd1668feaf21b4fe15c2b603526355f6" +checksum = "454e75b9152f3aea41e4de64154bcb4a261a50df75746b08136b9994130f3a00" dependencies = [ "bitflags", "cow-utils", @@ -1922,15 +1922,15 @@ dependencies = [ [[package]] name = "oxc_data_structures" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2866696e6bb90151c5687a961c3ff1fa2726436869d42eea14cf2d5c663590" +checksum = "c77ea3b4eae572b066a314edd33ccd07e0d0b148bdea635fdd1a44ff97b1a9fb" [[package]] name = "oxc_diagnostics" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7800336d376a2baeafb9d2bcdc9fbef254863c33810e6d1cc4a431cd0048ef" +checksum = "f5f38bf4f67832d521bcd99a79d4483e9b571d37c81e6b09a0a397b18931df8b" dependencies = [ "cow-utils", "oxc-miette", @@ -1938,9 +1938,9 @@ dependencies = [ [[package]] name = "oxc_ecmascript" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0edf650adfacf84768cdfeca874d8f5ffebfd108ee8a44959c0eca82b04321c6" +checksum = "53a754f033637a086a80d7f81620ff1123f20ad70789f37873bc635ec89f0021" dependencies = [ "cow-utils", "num-bigint", @@ -1952,9 +1952,9 @@ dependencies = [ [[package]] name = "oxc_estree" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd77f6588d373c1b753588b784de380a7418f8e46776e25c4564739994b9a5a6" +checksum = "85b7edeb47c4700027cc113d22ed899df45fda2ed5b29af2e471cad2be09244d" [[package]] name = "oxc_index" @@ -1964,9 +1964,9 @@ checksum = "2fa07b0cfa997730afed43705766ef27792873fdf5215b1391949fec678d2392" [[package]] name = "oxc_mangler" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f00ca9e544230f01d37de50ba710136763a13804303bcf70cf22d8155f9db5" +checksum = "8a837c659bb2e340f491d2196d4565d8e75ffa19e7a8c6b35eeab67159cda546" dependencies = [ "fixedbitset", "itertools", @@ -1981,9 +1981,9 @@ dependencies = [ [[package]] name = "oxc_minifier" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8670c4452b9f78012b9ede921e40f91686ad9a1af1c40aab8ee3a5f4ef8380ef" +checksum = "d186a202e49cebf004903e45eccecc3fc8bd10d4f6803ad73eb9eba51b4770b4" dependencies = [ "cow-utils", "oxc_allocator", @@ -2003,9 +2003,9 @@ dependencies = [ [[package]] name = "oxc_parser" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8eaebe1ac01073b2a43a8848ae7ec24fdad3813855d72bb1942908632654f94" +checksum = "a54ce76e891cdfa2bf1b946492e94f17a5d6a5d9731e59aaa1b4ae435f8439ef" dependencies = [ "bitflags", "cow-utils", @@ -2026,9 +2026,9 @@ dependencies = [ [[package]] name = "oxc_regular_expression" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9ad8833ffba010e9f4cced1482297282728b0dc1c410cd716f206d214250f3f" +checksum = "50d43967a36f4ce1577099e3d70927845fb9f1cbfdd57298e7fd69897c1f434d" dependencies = [ "oxc_allocator", "oxc_ast_macros", @@ -2042,9 +2042,9 @@ dependencies = [ [[package]] name = "oxc_semantic" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0523c9521e3ee63d6e0b463941e030b482977d7c323ee802eebacac8e5227bc8" +checksum = "2c8f0eb991e07aa1aab2efd85f61879452374d406145bdc6d32681ddda8d74c8" dependencies = [ "itertools", "oxc_allocator", @@ -2078,9 +2078,9 @@ dependencies = [ [[package]] name = "oxc_span" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bcfa55b4e3de93d39528b4ac616c00918dc73b6f6828403b3c56a7dde7af23b" +checksum = "2cdfaea137d47979b406de82e3b3c13f03b4bda4bc237c1b6fdbb8c46b436e70" dependencies = [ "compact_str", "oxc-miette", @@ -2091,9 +2091,9 @@ dependencies = [ [[package]] name = "oxc_syntax" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bc0d1f63b254791867280db5e582d7411c112f0798eee50bfdb8cdd2ef80c93" +checksum = "eb675497fc1051b3cec9c5cfa224ead942a830c8583394deaadcae5eb54669fa" dependencies = [ "bitflags", "cow-utils", @@ -2112,9 +2112,9 @@ dependencies = [ [[package]] name = "oxc_traverse" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a1f5183b3db89b3b3c7621741d5e2b9c13996dec5be4ad5e7adf86fdcfd24f0" +checksum = "f89e6801eb9ef451e1c785fdee237050be91da172b9fbcad849f9703d37a8ae8" dependencies = [ "compact_str", "itoa", @@ -3404,9 +3404,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 0f64a0162..5e17705d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ clap = { version = "4.5.35", features = ["derive", "string"] } color-eyre = "0.6.3" derive_deref = "1.1.1" fjall = "2.8.0" -jiff = "0.2.5" +jiff = "0.2.6" log = { version = "0.4.27" } minreq = { version = "2.13.3", features = ["https", "serde_json"] } rayon = "1.10.0" diff --git a/crates/brk_computer/src/storage/vecs/base.rs b/crates/brk_computer/src/storage/vecs/base.rs index fb182205f..41cf7bc2f 100644 --- a/crates/brk_computer/src/storage/vecs/base.rs +++ b/crates/brk_computer/src/storage/vecs/base.rs @@ -2,7 +2,7 @@ use core::error; use std::{ cmp::Ordering, fmt::Debug, - ops::{Add, Sub}, + ops::Add, path::{Path, PathBuf}, }; @@ -390,22 +390,26 @@ where max_from: I, first_indexes: &mut StoredVec, last_indexes: &mut StoredVec, + source: &mut StoredVec, exit: &Exit, ) -> Result<()> where - T: From, - T2: StoredType + Copy + Add + Sub + TryInto, - >::Error: error::Error + 'static, + T: From + Add, + T2: StoredIndex + StoredType, { self.validate_computed_version_or_reset_file( Version::ZERO + self.version() + first_indexes.version() + last_indexes.version(), )?; let index = max_from.min(I::from(self.len())); - first_indexes.iter_from(index, |(index, first_index, ..)| { - let last_index = last_indexes.cached_get(index)?.unwrap(); - let count = *last_index + 1_usize - first_index; - self.forced_push_at(index, count.into(), exit) + first_indexes.iter_from(index, |(i, first_index, ..)| { + let last_index = last_indexes.cached_get(i)?.unwrap().into_inner(); + let range = first_index.to_usize().unwrap()..=last_index.to_usize().unwrap(); + let mut sum = T::from(0_usize); + range.into_iter().for_each(|i| { + sum = sum.clone() + source.cached_get_(i).unwrap().unwrap().into_inner(); + }); + self.forced_push_at(i, sum, exit) })?; self.safe_flush(exit) diff --git a/crates/brk_computer/src/storage/vecs/blocks.rs b/crates/brk_computer/src/storage/vecs/blocks.rs index 1cca8e0d0..864aefa4e 100644 --- a/crates/brk_computer/src/storage/vecs/blocks.rs +++ b/crates/brk_computer/src/storage/vecs/blocks.rs @@ -92,7 +92,8 @@ impl Vecs { indexer_vecs.height_to_timestamp.mut_vec(), |(height, timestamp, _, height_to_timestamp)| { let interval = height.decremented().map_or(Timestamp::ZERO, |prev_h| { - let prev_timestamp = *height_to_timestamp.get(prev_h).unwrap().unwrap(); + let prev_timestamp = + *height_to_timestamp.cached_get(prev_h).unwrap().unwrap(); timestamp .checked_sub(prev_timestamp) .unwrap_or(Timestamp::ZERO) diff --git a/crates/brk_computer/src/storage/vecs/grouped/from_txindex.rs b/crates/brk_computer/src/storage/vecs/grouped/from_txindex.rs index f94c4150d..9314ecf15 100644 --- a/crates/brk_computer/src/storage/vecs/grouped/from_txindex.rs +++ b/crates/brk_computer/src/storage/vecs/grouped/from_txindex.rs @@ -18,7 +18,6 @@ where T: ComputedType + PartialOrd, { pub txindex: Option>, - pub txindex_extra: ComputedVecBuilder, pub height: ComputedVecBuilder, pub dateindex: ComputedVecBuilder, pub weekindex: ComputedVecBuilder, @@ -52,23 +51,14 @@ where .unwrap() }); - let txindex_extra = ComputedVecBuilder::forced_import( - path, - name, - compressed, - StorableVecGeneatorOptions::default(), - )?; - let height = ComputedVecBuilder::forced_import(path, name, compressed, options)?; - let dateindex = ComputedVecBuilder::forced_import(path, name, compressed, options)?; let options = options.remove_percentiles(); Ok(Self { txindex, - txindex_extra, height, - dateindex, + dateindex: ComputedVecBuilder::forced_import(path, name, compressed, options)?, weekindex: ComputedVecBuilder::forced_import(path, name, compressed, options)?, difficultyepoch: ComputedVecBuilder::forced_import(path, name, compressed, options)?, monthindex: ComputedVecBuilder::forced_import(path, name, compressed, options)?, @@ -119,9 +109,6 @@ where ) -> color_eyre::Result<()> { let txindex = txindex.unwrap_or_else(|| self.txindex.as_mut().unwrap().mut_vec()); - self.txindex_extra - .extend(starting_indexes.txindex, txindex, exit)?; - self.height.compute( starting_indexes.height, txindex, @@ -192,7 +179,6 @@ where pub fn any_vecs(&self) -> Vec<&dyn AnyStoredVec> { [ self.txindex.as_ref().map_or(vec![], |v| vec![v.any_vec()]), - self.txindex_extra.any_vecs(), self.height.any_vecs(), self.dateindex.any_vecs(), self.weekindex.any_vecs(), diff --git a/crates/brk_computer/src/storage/vecs/transactions.rs b/crates/brk_computer/src/storage/vecs/transactions.rs index 9fd7c1142..fa7e61853 100644 --- a/crates/brk_computer/src/storage/vecs/transactions.rs +++ b/crates/brk_computer/src/storage/vecs/transactions.rs @@ -1,8 +1,12 @@ use std::{fs, path::Path}; -use brk_core::{Sats, StoredU32, StoredU64, TxVersion, Txindex, Txinindex, Txoutindex}; +use brk_core::{ + CheckedSub, Feerate, Sats, StoredU32, StoredU64, StoredUsize, TxVersion, Txindex, Txinindex, + Txoutindex, Weight, +}; use brk_exit::Exit; use brk_indexer::Indexer; +use brk_parser::bitcoin; use brk_vec::{Compressed, DynamicVec, Version}; use super::{ @@ -21,19 +25,19 @@ pub struct Vecs { // pub height_to_outputcount: ComputedVec, // pub height_to_subsidy: ComputedVec, // pub height_to_totalfees: ComputedVec, - // pub txindex_to_fee: ComputedVec, - // pub txindex_to_feerate: ComputedVec, - // pub txindex_to_input_sum: ComputedVec, - // pub txindex_to_output_sum: ComputedVec, - // pub txindex_to_output_value: ComputedVecsFromTxindex, + pub height_to_tx_count: ComputedVecsFromHeight, + pub indexes_to_fee: ComputedVecsFromTxindex, + pub indexes_to_feerate: ComputedVecsFromTxindex, + pub indexes_to_input_value: ComputedVecsFromTxindex, + pub indexes_to_output_value: ComputedVecsFromTxindex, pub indexes_to_tx_v1: ComputedVecsFromHeight, pub indexes_to_tx_v2: ComputedVecsFromHeight, pub indexes_to_tx_v3: ComputedVecsFromHeight, - // pub txinindex_to_value: ComputedVec, - pub height_to_tx_count: ComputedVecsFromHeight, pub txindex_to_input_count: ComputedVecsFromTxindex, pub txindex_to_is_coinbase: ComputedVec, pub txindex_to_output_count: ComputedVecsFromTxindex, + pub txindex_to_vsize: ComputedVec, + pub txindex_to_weight: ComputedVec, /// Value == 0 when Coinbase pub txinindex_to_value: ComputedVec, } @@ -66,10 +70,6 @@ impl Vecs { // height_to_subsidy: StorableVec::forced_import(&path.join("height_to_subsidy"), Version::ZERO)?, // height_to_totalfees: StorableVec::forced_import(&path.join("height_to_totalfees"), Version::ZERO)?, // height_to_txcount: StorableVec::forced_import(&path.join("height_to_txcount"), Version::ZERO)?, - // txindex_to_fee: StorableVec::forced_import( - // &path.join("txindex_to_fee"), - // Version::ZERO, - // )?, txindex_to_is_coinbase: ComputedVec::forced_import( &path.join("txindex_to_is_coinbase"), Version::ZERO, @@ -128,6 +128,51 @@ impl Vecs { compressed, StorableVecGeneatorOptions::default().add_sum().add_total(), )?, + indexes_to_input_value: ComputedVecsFromTxindex::forced_import( + path, + "input_value", + true, + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_sum().add_total(), + )?, + indexes_to_output_value: ComputedVecsFromTxindex::forced_import( + path, + "output_value", + true, + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_sum().add_total(), + )?, + indexes_to_fee: ComputedVecsFromTxindex::forced_import( + path, + "fee", + true, + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_sum().add_total(), + )?, + indexes_to_feerate: ComputedVecsFromTxindex::forced_import( + path, + "feerate", + true, + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default() + .add_percentiles() + .add_minmax() + .add_average(), + )?, + txindex_to_weight: ComputedVec::forced_import( + &path.join("txindex_to_weight"), + Version::ZERO, + compressed, + )?, + txindex_to_vsize: ComputedVec::forced_import( + &path.join("txindex_to_vsize"), + Version::ZERO, + compressed, + )?, }) } @@ -231,6 +276,38 @@ impl Vecs { exit, )?; + self.txindex_to_weight.compute_transform( + starting_indexes.txindex, + indexer_vecs.txindex_to_base_size.mut_vec(), + |(txindex, base_size, ..)| { + let total_size = indexer_vecs + .txindex_to_total_size + .mut_vec() + .cached_get(txindex) + .unwrap() + .unwrap() + .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 weight = Weight::from(bitcoin::Weight::from_wu_usize(wu)); + + (txindex, weight) + }, + exit, + )?; + + self.txindex_to_vsize.compute_transform( + starting_indexes.txindex, + self.txindex_to_weight.mut_vec(), + |(txindex, weight, ..)| { + let vbytes = + StoredUsize::from(bitcoin::Weight::from(weight).to_vbytes_ceil() as usize); + (txindex, vbytes) + }, + exit, + )?; + self.txinindex_to_value.compute_transform( starting_indexes.txinindex, indexer_vecs.txinindex_to_txoutindex.mut_vec(), @@ -252,10 +329,100 @@ impl Vecs { exit, )?; - // self.txindex_to_fee.compute_transform( - // &mut self.vecs.txindex_to_height, - // &mut indexer.vecs().height_to_first_txindex, - // )?; + self.indexes_to_output_value.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |vec, indexer, indexes, starting_indexes, exit| { + let indexer_vecs = indexer.mut_vecs(); + 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(), + exit, + ) + }, + )?; + + self.indexes_to_input_value.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |vec, indexer, indexes, starting_indexes, exit| { + let indexer_vecs = indexer.mut_vecs(); + 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(), + exit, + ) + }, + )?; + + self.indexes_to_fee.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |vec, _, _, starting_indexes, exit| { + let txindex_to_output_value = self + .indexes_to_output_value + .txindex + .as_mut() + .unwrap() + .mut_vec(); + vec.compute_transform( + starting_indexes.txindex, + self.indexes_to_input_value + .txindex + .as_mut() + .unwrap() + .mut_vec(), + |(txindex, input_value, ..)| { + if input_value.is_zero() { + (txindex, input_value) + } else { + let output_value = txindex_to_output_value + .cached_get(txindex) + .unwrap() + .unwrap() + .into_inner(); + (txindex, input_value.checked_sub(output_value).unwrap()) + } + }, + exit, + ) + }, + )?; + + self.indexes_to_feerate.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |vec, _, _, starting_indexes, exit| { + vec.compute_transform( + starting_indexes.txindex, + self.indexes_to_fee.txindex.as_mut().unwrap().mut_vec(), + |(txindex, fee, ..)| { + let vsize = self + .txindex_to_vsize + .mut_vec() + .cached_get(txindex) + .unwrap() + .unwrap() + .into_inner(); + + (txindex, Feerate::from((fee, vsize))) + }, + exit, + ) + }, + )?; Ok(()) } @@ -265,13 +432,19 @@ impl Vecs { vec![ self.txindex_to_is_coinbase.any_vec(), self.txinindex_to_value.any_vec(), + self.txindex_to_weight.any_vec(), + self.txindex_to_vsize.any_vec(), ], self.height_to_tx_count.any_vecs(), - self.txindex_to_output_count.any_vecs(), - self.txindex_to_input_count.any_vecs(), + self.indexes_to_input_value.any_vecs(), + self.indexes_to_output_value.any_vecs(), self.indexes_to_tx_v1.any_vecs(), self.indexes_to_tx_v2.any_vecs(), self.indexes_to_tx_v3.any_vecs(), + self.indexes_to_fee.any_vecs(), + self.indexes_to_feerate.any_vecs(), + self.txindex_to_input_count.any_vecs(), + self.txindex_to_output_count.any_vecs(), ] .concat() } diff --git a/crates/brk_core/src/structs/feerate.rs b/crates/brk_core/src/structs/feerate.rs index 2416f17d7..ea502e0e0 100644 --- a/crates/brk_core/src/structs/feerate.rs +++ b/crates/brk_core/src/structs/feerate.rs @@ -1,5 +1,66 @@ +use std::ops::{Add, Div}; + use serde::Serialize; use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; -#[derive(Debug, Clone, Copy, Serialize, FromBytes, Immutable, IntoBytes, KnownLayout)] +use super::{Sats, StoredUsize}; + +#[derive( + Debug, + Clone, + Copy, + Serialize, + PartialEq, + PartialOrd, + FromBytes, + Immutable, + IntoBytes, + KnownLayout, +)] pub struct Feerate(f32); + +impl From<(Sats, StoredUsize)> for Feerate { + fn from((sats, vsize): (Sats, StoredUsize)) -> Self { + Self((f64::from(sats) / f64::from(vsize)) as f32) + } +} + +impl From for Feerate { + fn from(value: f64) -> Self { + Self(value as f32) + } +} +impl From for f64 { + fn from(value: Feerate) -> Self { + value.0 as f64 + } +} + +impl Add for Feerate { + type Output = Self; + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) + } +} + +impl Div for Feerate { + type Output = Self; + fn div(self, rhs: usize) -> Self::Output { + Self((self.0 as f64 / rhs as f64) as f32) + } +} + +impl From for Feerate { + fn from(value: usize) -> Self { + Self(value as f32) + } +} + +impl Eq for Feerate {} + +#[allow(clippy::derive_ord_xor_partial_ord)] +impl Ord for Feerate { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.0.partial_cmp(&other.0).unwrap() + } +} diff --git a/crates/brk_server/Cargo.toml b/crates/brk_server/Cargo.toml index 8dc6bb29d..3a79b8485 100644 --- a/crates/brk_server/Cargo.toml +++ b/crates/brk_server/Cargo.toml @@ -21,7 +21,7 @@ color-eyre = { workspace = true } jiff = { workspace = true } log = { workspace = true } minreq = { workspace = true } -oxc = { version = "0.62.0", features = ["codegen", "minifier"] } +oxc = { version = "0.63.0", features = ["codegen", "minifier"] } serde = { workspace = true } tokio = { version = "1.44.2", features = ["full"] } tower-http = { version = "0.6.2", features = ["compression-full", "trace"] } diff --git a/websites/kibo.money/scripts/main.js b/websites/kibo.money/scripts/main.js index 4851f6b9e..80a2619e8 100644 --- a/websites/kibo.money/scripts/main.js +++ b/websites/kibo.money/scripts/main.js @@ -767,13 +767,13 @@ function createUtils() { return numberToUSFormat(value, 0); } else if (absoluteValue < 1_000_000) { return `${numberToUSFormat(value / 1_000, 1)}K`; - } else if (absoluteValue >= 9_000_000_000_000_000) { + } else if (absoluteValue >= 900_000_000_000_000_000) { return "Inf."; } const log = Math.floor(Math.log10(absoluteValue) - 6); - const suffices = ["M", "B", "T", "Q"]; + const suffices = ["M", "B", "T", "P", "E"]; const letterIndex = Math.floor(log / 3); const letter = suffices[letterIndex]; diff --git a/websites/kibo.money/scripts/options.js b/websites/kibo.money/scripts/options.js index fcc1bd7ed..f9d7e00ca 100644 --- a/websites/kibo.money/scripts/options.js +++ b/websites/kibo.money/scripts/options.js @@ -14,6 +14,7 @@ * "Percentage" | * "Ratio" | * "Satoshis" | + * "sat/vB" | * "Seconds" | * "Transactions" | * "US Dollars" | @@ -869,6 +870,16 @@ function createPartialOptions(colors) { title: "Transaction Count", key: "tx-count", }), + createBaseSumTotal({ + name: "Fee", + title: "Transaction Fee", + key: "fee", + }), + createBaseAverageMinMaxPercentiles({ + name: "Feerate", + title: "Transaction Fee Rate", + key: "feerate", + }), { name: "Version", tree: [ @@ -899,6 +910,11 @@ function createPartialOptions(colors) { title: "Transaction Input Count", key: "input-count", }), + createBaseSumTotal({ + name: "Value", + title: "Transaction Input Value", + key: "input-value", + }), ], }, { @@ -909,6 +925,11 @@ function createPartialOptions(colors) { title: "Transaction Output Count", key: "output-count", }), + createBaseSumTotal({ + name: "Value", + title: "Transaction Output Value", + key: "output-value", + }), ], }, ], @@ -1265,7 +1286,14 @@ export function initOptions({ if (key) { if (key.includes("-interval")) { anyPartial.unit = "Seconds"; - } else if (key.startsWith("sats-")) { + } else if (key.includes("feerate")) { + anyPartial.unit = "sat/vB"; + } else if ( + key.startsWith("sats-") || + key.includes("input-value") || + key.includes("output-value") || + key.includes("fee") + ) { anyPartial.unit = "Satoshis"; } else if (key.includes("count")) { anyPartial.unit = "Count"; diff --git a/websites/kibo.money/scripts/vecid-to-indexes.js b/websites/kibo.money/scripts/vecid-to-indexes.js index fe7b41e68..bb03c414c 100644 --- a/websites/kibo.money/scripts/vecid-to-indexes.js +++ b/websites/kibo.money/scripts/vecid-to-indexes.js @@ -87,6 +87,17 @@ export function createVecIdToIndexes() { decadeindex: [Yearindex, Decadeindex], difficulty: [Height], difficultyepoch: [Height, Difficultyepoch], + fee: [Txindex], + "fee-sum": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], + feerate: [Txindex], + "feerate-10p": [Height], + "feerate-25p": [Height], + "feerate-75p": [Height], + "feerate-90p": [Height], + "feerate-average": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], + "feerate-max": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], + "feerate-median": [Height], + "feerate-min": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], "first-addressindex": [Height], "first-dateindex": [Weekindex, Monthindex], "first-emptyindex": [Height], @@ -115,6 +126,8 @@ export function createVecIdToIndexes() { "high-in-cents": [Dateindex, Height], "input-count": [Txindex], "input-count-sum": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], + "input-value": [Txindex], + "input-value-sum": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], "is-coinbase": [Txindex], "is-explicitly-rbf": [Txindex], "last-dateindex": [Weekindex, Monthindex], @@ -134,6 +147,8 @@ export function createVecIdToIndexes() { "open-in-cents": [Dateindex, Height], "output-count": [Txindex], "output-count-sum": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], + "output-value": [Txindex], + "output-value-sum": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], p2pk33addressbytes: [P2PK33index], p2pk65addressbytes: [P2PK65index], p2pkhaddressbytes: [P2PKHindex], @@ -149,8 +164,11 @@ export function createVecIdToIndexes() { "total-block-size": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], "total-block-vbytes": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], "total-block-weight": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], + "total-fee": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], "total-input-count": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], + "total-input-value": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], "total-output-count": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], + "total-output-value": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], "total-size": [Txindex], "total-tx-count": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], "total-tx-v1": [Dateindex, Height, Weekindex, Monthindex, Quarterindex, Yearindex, Decadeindex, Difficultyepoch], @@ -168,7 +186,9 @@ export function createVecIdToIndexes() { txoutindex: [Txinindex], txversion: [Txindex], value: [Txinindex, Txoutindex], + vsize: [Txindex], weekindex: [Dateindex, Weekindex], + weight: [Txindex], yearindex: [Monthindex, Yearindex], } }