From 10c16335ed0322614e12426c7d7021e1025104ed Mon Sep 17 00:00:00 2001 From: nym21 Date: Fri, 17 Jul 2026 21:45:18 +0200 Subject: [PATCH] global: opreturn part 2 --- Cargo.lock | 97 ++-- Cargo.toml | 8 +- crates/brk_cli/Cargo.toml | 2 +- crates/brk_client/src/lib.rs | 423 ++++++++++++++++-- .../src/internal/per_tx/lazy_distribution.rs | 58 --- .../per_tx/lazy_distribution_transformed.rs | 3 +- .../brk_computer/src/internal/per_tx/mod.rs | 2 - crates/brk_computer/src/lib.rs | 1 + crates/brk_computer/src/op_return/compute.rs | 41 +- crates/brk_computer/src/op_return/import.rs | 20 +- crates/brk_computer/src/op_return/mod.rs | 2 +- crates/brk_computer/src/op_return/vecs.rs | 243 +++++----- .../src/transactions/fees/compute.rs | 18 +- .../src/transactions/patterns/compute.rs | 10 +- .../src/transactions/policy/compute.rs | 13 +- .../src/transactions/size/compute.rs | 9 +- .../src/transactions/size/import.rs | 20 +- .../src/transactions/size/vecs.rs | 4 +- crates/brk_indexer/src/lib.rs | 2 +- .../src/processor/txin/resolver.rs | 258 ++++++++--- .../src/processor/txout/address.rs | 3 + .../src/processor/txout/address/cache.rs | 2 +- modules/brk-client/index.js | 349 +++++++++++++-- packages/brk_client/brk_client/__init__.py | 214 ++++++++- rust-toolchain.toml | 2 +- 25 files changed, 1366 insertions(+), 438 deletions(-) delete mode 100644 crates/brk_computer/src/internal/per_tx/lazy_distribution.rs diff --git a/Cargo.lock b/Cargo.lock index 12277c30d..293836f4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -213,7 +213,7 @@ version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "cexpr", "clang-sys", "itertools", @@ -227,9 +227,9 @@ dependencies = [ [[package]] name = "bitcoin" -version = "0.32.101" +version = "0.32.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed8ccb78a9ff7a6fbb90e2fb9b8588b4a9928d49d8af3cb789108a84ea6b0ce" +checksum = "bb0ce8bd5baaa0d303a19915a6d93afed161f528654e42da2a7a97d05c59499a" dependencies = [ "base58ck", "base64 0.21.7", @@ -245,21 +245,20 @@ dependencies = [ [[package]] name = "bitcoin-consensus-encoding" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2d6094e2a1ba3c93b5a596fe5a10d1a10c3c6e06785cde89f693a044c01aa40" +checksum = "207311705279250ba465076a1bac4b1ac982855fff73fc5f67e22158ac58cdc9" dependencies = [ "bitcoin-internals", + "hex-conservative 1.2.0", + "serde", ] [[package]] name = "bitcoin-internals" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a30a22d1f112dde8e16be7b45c63645dc165cef254f835b3e1e9553e485cfa64" -dependencies = [ - "hex-conservative 0.3.2", -] +checksum = "d573f4cf32996a8dce612e4348cece65a241f1882ed594047c9ba348e8869fa5" [[package]] name = "bitcoin-io" @@ -299,9 +298,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" [[package]] name = "blk" @@ -1292,7 +1291,9 @@ checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "fjall" -version = "3.0.4" +version = "3.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fcdc69609906151dff9b534e30eaf8515082055d36f628e382bd0b5d6a1d362" dependencies = [ "byteorder-lite", "byteview", @@ -1300,7 +1301,7 @@ dependencies = [ "flume", "log", "lsm-tree", - "lz4_flex 0.11.6", + "lz4_flex", "tempfile", "xxhash-rust", ] @@ -1336,7 +1337,7 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c7e611d49285d4c4b2e1727b72cf05353558885cc5252f93707b845dfcaf3d3" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "byteorder", "core-foundation", "core-graphics", @@ -1537,9 +1538,9 @@ dependencies = [ [[package]] name = "hex-conservative" -version = "0.3.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830e599c2904b08f0834ee6337d8fe8f0ed4a63b5d9e7a7f49c0ffa06d08d360" +checksum = "35431185f361ccf3ffc58254628af5f1f5d5f28531da2e02e5d6c82bbc282a10" dependencies = [ "arrayvec", ] @@ -2017,7 +2018,9 @@ checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "lsm-tree" -version = "3.0.4" +version = "3.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ca67401338b98d58447387dd5230552d2241bc388206e491d137b18dfea9d6" dependencies = [ "byteorder-lite", "byteview", @@ -2025,7 +2028,7 @@ dependencies = [ "enum_dispatch", "interval-heap", "log", - "lz4_flex 0.11.6", + "lz4_flex", "quick_cache", "rustc-hash", "self_cell", @@ -2035,20 +2038,14 @@ dependencies = [ "xxhash-rust", ] -[[package]] -name = "lz4_flex" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373f5eceeeab7925e0c1098212f2fbc4d416adec9d35051a6ab251e824c1854a" -dependencies = [ - "twox-hash", -] - [[package]] name = "lz4_flex" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef0d4ed8669f8f8826eb00dc878084aa8f253506c4fd5e8f58f5bce72ddb97e" +dependencies = [ + "twox-hash", +] [[package]] name = "matchit" @@ -2469,7 +2466,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", ] [[package]] @@ -2505,9 +2502,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -2517,9 +2514,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.15" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db" +checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" dependencies = [ "aho-corasick", "memchr", @@ -2582,7 +2579,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "errno", "libc", "linux-raw-sys", @@ -2699,9 +2696,9 @@ dependencies = [ [[package]] name = "self_cell" -version = "1.2.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" +checksum = "2ab42ca02749e120097e328d91d415325bdf43b1c72c4c8badf37375fe40a813" [[package]] name = "semver" @@ -2853,9 +2850,9 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "simd-adler32" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" [[package]] name = "slab" @@ -2942,9 +2939,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.118" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" dependencies = [ "proc-macro2", "quote", @@ -3052,9 +3049,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.52.3" +version = "1.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +checksum = "317fafbbe3f02fc663dad00ea6186197de963cd4190e86a26d8d0fae095539af" dependencies = [ "libc", "mio", @@ -3090,9 +3087,9 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.2+spec-1.1.0" +version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +checksum = "53c96ecdfa941c8fc4fcaed14f99ada8ebed502eef533015095a07e3301d4c3c" dependencies = [ "indexmap", "serde_core", @@ -3123,9 +3120,9 @@ dependencies = [ [[package]] name = "toml_writer" -version = "1.1.1+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" [[package]] name = "tower" @@ -3149,7 +3146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b11f75e912b0c2be01b63d8cf8057b8c3f97cf34abb3d431a3a4c8675498e233" dependencies = [ "async-compression", - "bitflags 2.13.0", + "bitflags 2.13.1", "bytes", "futures-core", "futures-util", @@ -3355,7 +3352,7 @@ dependencies = [ "itoa", "libc", "log", - "lz4_flex 0.13.1", + "lz4_flex", "parking_lot", "pco", "rawdb", @@ -3666,9 +3663,9 @@ checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "xxhash-rust" -version = "0.8.16" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d93c89cdc2d3a63c3ec48ffe926931bdc069eafa8e4402fe6d8f790c9d1e576" +checksum = "985eec839aaf2a1270af8f4ebcf63cf9401cfd90f0902f97c28d9f104ffbde72" [[package]] name = "yeslogic-fontconfig-sys" diff --git a/Cargo.toml b/Cargo.toml index 247a0308f..832f3424b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ debug = true [workspace.dependencies] aide = { version = "0.16.0-alpha.4", features = ["axum-json", "axum-query"] } axum = { version = "0.8.9", default-features = false, features = ["http1", "json", "query", "tokio", "tracing"] } -bitcoin = { version = "0.32.101", features = ["serde"] } +bitcoin = { version = "0.32.102", features = ["serde"] } brk_alloc = { version = "0.3.6", path = "crates/brk_alloc" } brk_bencher = { version = "0.3.6", path = "crates/brk_bencher" } brk_bindgen = { version = "0.3.6", path = "crates/brk_bindgen" } @@ -64,7 +64,7 @@ color-eyre = "0.6.5" corepc-jsonrpc = { package = "jsonrpc", version = "0.19.0", features = ["simple_http"], default-features = false } corepc-types = { version = "0.15.0", features = ["std"], default-features = false } derive_more = { version = "2.1.1", features = ["deref", "deref_mut"] } -fjall = { version = "=3.0.4", path = "../fjall" } +fjall = "3.1.6" indexmap = { version = "2.14.0", features = ["serde"] } jiff = { version = "0.2.32", features = ["perf-inline", "tz-system"], default-features = false } owo-colors = "4.3.0" @@ -79,7 +79,7 @@ serde_bytes = "0.11.19" serde_derive = "1.0.228" serde_json = { version = "1.0.150", features = ["float_roundtrip", "preserve_order"] } smallvec = "1.15.2" -tokio = { version = "1.52.3", features = ["rt-multi-thread"] } +tokio = { version = "1.52.4", features = ["rt-multi-thread"] } tower-http = { version = "0.7.0", features = ["catch-panic", "compression-br", "compression-gzip", "compression-zstd", "cors", "normalize-path", "timeout", "trace"] } tower-layer = "0.3" tracing = { version = "0.1", default-features = false, features = ["std"] } @@ -87,8 +87,6 @@ ureq = { version = "3.3.0", features = ["json"] } vecdb = { version = "0.10.4", features = ["derive", "serde_json", "pco", "schemars"] } # vecdb = { path = "../anydb/crates/vecdb", features = ["derive", "serde_json", "pco", "schemars"] } -[patch.crates-io] -lsm-tree = { path = "../lsm-tree" } [workspace.metadata.release] shared-version = true diff --git a/crates/brk_cli/Cargo.toml b/crates/brk_cli/Cargo.toml index 4fade1d3f..58579d0a6 100644 --- a/crates/brk_cli/Cargo.toml +++ b/crates/brk_cli/Cargo.toml @@ -25,7 +25,7 @@ owo-colors = { workspace = true } tracing = { workspace = true } serde = { workspace = true } tokio = { workspace = true } -toml = "1.1.2" +toml = "1.1.3" vecdb = { workspace = true } [[bin]] diff --git a/crates/brk_client/src/lib.rs b/crates/brk_client/src/lib.rs index f8b461d38..fedae26bd 100644 --- a/crates/brk_client/src/lib.rs +++ b/crates/brk_client/src/lib.rs @@ -1831,13 +1831,13 @@ impl InMaxMinPerSupplyPattern { /// Pattern struct for repeated tree structure. pub struct MaxMedianMinPct10Pct25Pct75Pct90Pattern2 { - pub max: SeriesPattern18, - pub median: SeriesPattern18, - pub min: SeriesPattern18, - pub pct10: SeriesPattern18, - pub pct25: SeriesPattern18, - pub pct75: SeriesPattern18, - pub pct90: SeriesPattern18, + pub max: SeriesPattern18, + pub median: SeriesPattern18, + pub min: SeriesPattern18, + pub pct10: SeriesPattern18, + pub pct25: SeriesPattern18, + pub pct75: SeriesPattern18, + pub pct90: SeriesPattern18, } impl MaxMedianMinPct10Pct25Pct75Pct90Pattern2 { @@ -2652,6 +2652,26 @@ impl BtcCentsSatsUsdPattern3 { } } +/// Pattern struct for repeated tree structure. +pub struct CarrierOutputPostPattern { + pub carrier_tx_count: AverageBlockCumulativeSumPattern, + pub carrier_vsize: AverageBlockCumulativeSumPattern, + pub output_count: AverageBlockCumulativeSumPattern, + pub post_op_return_bytes: AverageBlockCumulativeSumPattern, +} + +impl CarrierOutputPostPattern { + /// Create a new pattern node with accumulated series name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + carrier_tx_count: AverageBlockCumulativeSumPattern::new(client.clone(), _m(&acc, "carrier_tx_count")), + carrier_vsize: AverageBlockCumulativeSumPattern::new(client.clone(), _m(&acc, "carrier_vsize")), + output_count: AverageBlockCumulativeSumPattern::new(client.clone(), _m(&acc, "output_count")), + post_op_return_bytes: AverageBlockCumulativeSumPattern::new(client.clone(), _m(&acc, "post_op_return_bytes")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct CentsDeltaToUsdPattern { pub cents: SeriesPattern1, @@ -3661,6 +3681,7 @@ pub struct SeriesTree { pub outputs: SeriesTree_Outputs, pub addrs: SeriesTree_Addrs, pub scripts: SeriesTree_Scripts, + pub op_return: SeriesTree_OpReturn, pub mining: SeriesTree_Mining, pub cointime: SeriesTree_Cointime, pub constants: SeriesTree_Constants, @@ -3683,6 +3704,7 @@ impl SeriesTree { outputs: SeriesTree_Outputs::new(client.clone(), format!("{base_path}_outputs")), addrs: SeriesTree_Addrs::new(client.clone(), format!("{base_path}_addrs")), scripts: SeriesTree_Scripts::new(client.clone(), format!("{base_path}_scripts")), + op_return: SeriesTree_OpReturn::new(client.clone(), format!("{base_path}_op_return")), mining: SeriesTree_Mining::new(client.clone(), format!("{base_path}_mining")), cointime: SeriesTree_Cointime::new(client.clone(), format!("{base_path}_cointime")), constants: SeriesTree_Constants::new(client.clone(), format!("{base_path}_constants")), @@ -3978,9 +4000,12 @@ impl SeriesTree_Blocks_Halving { /// Series tree node. pub struct SeriesTree_Transactions { pub raw: SeriesTree_Transactions_Raw, + pub features: SeriesTree_Transactions_Features, pub count: SeriesTree_Transactions_Count, pub size: SeriesTree_Transactions_Size, pub fees: SeriesTree_Transactions_Fees, + pub patterns: SeriesTree_Transactions_Patterns, + pub policy: SeriesTree_Transactions_Policy, pub versions: SeriesTree_Transactions_Versions, pub volume: SeriesTree_Transactions_Volume, } @@ -3989,9 +4014,12 @@ impl SeriesTree_Transactions { pub fn new(client: Arc, base_path: String) -> Self { Self { raw: SeriesTree_Transactions_Raw::new(client.clone(), format!("{base_path}_raw")), + features: SeriesTree_Transactions_Features::new(client.clone(), format!("{base_path}_features")), count: SeriesTree_Transactions_Count::new(client.clone(), format!("{base_path}_count")), size: SeriesTree_Transactions_Size::new(client.clone(), format!("{base_path}_size")), fees: SeriesTree_Transactions_Fees::new(client.clone(), format!("{base_path}_fees")), + patterns: SeriesTree_Transactions_Patterns::new(client.clone(), format!("{base_path}_patterns")), + policy: SeriesTree_Transactions_Policy::new(client.clone(), format!("{base_path}_policy")), versions: SeriesTree_Transactions_Versions::new(client.clone(), format!("{base_path}_versions")), volume: SeriesTree_Transactions_Volume::new(client.clone(), format!("{base_path}_volume")), } @@ -4004,7 +4032,7 @@ pub struct SeriesTree_Transactions_Raw { pub txid: SeriesPattern19, pub tx_version: SeriesPattern19, pub raw_locktime: SeriesPattern19, - pub base_size: SeriesPattern19, + pub weight: SeriesPattern19, pub total_size: SeriesPattern19, pub total_sigop_cost: SeriesPattern19, pub is_explicitly_rbf: SeriesPattern19, @@ -4019,7 +4047,7 @@ impl SeriesTree_Transactions_Raw { txid: SeriesPattern19::new(client.clone(), "txid".to_string()), tx_version: SeriesPattern19::new(client.clone(), "tx_version".to_string()), raw_locktime: SeriesPattern19::new(client.clone(), "raw_locktime".to_string()), - base_size: SeriesPattern19::new(client.clone(), "base_size".to_string()), + weight: SeriesPattern19::new(client.clone(), "tx_weight".to_string()), total_size: SeriesPattern19::new(client.clone(), "total_size".to_string()), total_sigop_cost: SeriesPattern19::new(client.clone(), "total_sigop_cost".to_string()), is_explicitly_rbf: SeriesPattern19::new(client.clone(), "is_explicitly_rbf".to_string()), @@ -4029,6 +4057,128 @@ impl SeriesTree_Transactions_Raw { } } +/// Series tree node. +pub struct SeriesTree_Transactions_Features { + pub count: SeriesTree_Transactions_Features_Count, + pub has_p2pk: SeriesPattern19, + pub has_p2ms: SeriesPattern19, + pub has_p2pkh: SeriesPattern19, + pub has_p2sh: SeriesPattern19, + pub has_p2wpkh: SeriesPattern19, + pub has_p2wsh: SeriesPattern19, + pub has_p2tr: SeriesPattern19, + pub has_p2a: SeriesPattern19, + pub has_op_return: SeriesPattern19, + pub has_empty: SeriesPattern19, + pub has_unknown: SeriesPattern19, + pub has_fake_pubkey: SeriesPattern19, + pub has_fake_scripthash: SeriesPattern19, + pub has_inscription: SeriesPattern19, + pub has_annex: SeriesPattern19, + pub has_sighash_all: SeriesPattern19, + pub has_sighash_none: SeriesPattern19, + pub has_sighash_single: SeriesPattern19, + pub has_sighash_default: SeriesPattern19, + pub has_sighash_anyone_can_pay: SeriesPattern19, + pub has_dust_output: SeriesPattern19, +} + +impl SeriesTree_Transactions_Features { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + count: SeriesTree_Transactions_Features_Count::new(client.clone(), format!("{base_path}_count")), + has_p2pk: SeriesPattern19::new(client.clone(), "has_p2pk".to_string()), + has_p2ms: SeriesPattern19::new(client.clone(), "has_p2ms".to_string()), + has_p2pkh: SeriesPattern19::new(client.clone(), "has_p2pkh".to_string()), + has_p2sh: SeriesPattern19::new(client.clone(), "has_p2sh".to_string()), + has_p2wpkh: SeriesPattern19::new(client.clone(), "has_p2wpkh".to_string()), + has_p2wsh: SeriesPattern19::new(client.clone(), "has_p2wsh".to_string()), + has_p2tr: SeriesPattern19::new(client.clone(), "has_p2tr".to_string()), + has_p2a: SeriesPattern19::new(client.clone(), "has_p2a".to_string()), + has_op_return: SeriesPattern19::new(client.clone(), "has_op_return".to_string()), + has_empty: SeriesPattern19::new(client.clone(), "has_empty".to_string()), + has_unknown: SeriesPattern19::new(client.clone(), "has_unknown".to_string()), + has_fake_pubkey: SeriesPattern19::new(client.clone(), "has_fake_pubkey".to_string()), + has_fake_scripthash: SeriesPattern19::new(client.clone(), "has_fake_scripthash".to_string()), + has_inscription: SeriesPattern19::new(client.clone(), "has_inscription".to_string()), + has_annex: SeriesPattern19::new(client.clone(), "has_annex".to_string()), + has_sighash_all: SeriesPattern19::new(client.clone(), "has_sighash_all".to_string()), + has_sighash_none: SeriesPattern19::new(client.clone(), "has_sighash_none".to_string()), + has_sighash_single: SeriesPattern19::new(client.clone(), "has_sighash_single".to_string()), + has_sighash_default: SeriesPattern19::new(client.clone(), "has_sighash_default".to_string()), + has_sighash_anyone_can_pay: SeriesPattern19::new(client.clone(), "has_sighash_anyone_can_pay".to_string()), + has_dust_output: SeriesPattern19::new(client.clone(), "has_dust_output".to_string()), + } + } +} + +/// Series tree node. +pub struct SeriesTree_Transactions_Features_Count { + pub v1: SeriesPattern18, + pub v2: SeriesPattern18, + pub v3: SeriesPattern18, + pub other_version: SeriesPattern18, + pub explicitly_rbf: SeriesPattern18, + pub one_input: SeriesPattern18, + pub one_output: SeriesPattern18, + pub p2pk: SeriesPattern18, + pub p2ms: SeriesPattern18, + pub p2pkh: SeriesPattern18, + pub p2sh: SeriesPattern18, + pub p2wpkh: SeriesPattern18, + pub p2wsh: SeriesPattern18, + pub p2tr: SeriesPattern18, + pub p2a: SeriesPattern18, + pub op_return: SeriesPattern18, + pub empty: SeriesPattern18, + pub unknown: SeriesPattern18, + pub fake_pubkey: SeriesPattern18, + pub fake_scripthash: SeriesPattern18, + pub inscription: SeriesPattern18, + pub annex: SeriesPattern18, + pub sighash_all: SeriesPattern18, + pub sighash_none: SeriesPattern18, + pub sighash_single: SeriesPattern18, + pub sighash_default: SeriesPattern18, + pub sighash_anyone_can_pay: SeriesPattern18, + pub dust_output: SeriesPattern18, +} + +impl SeriesTree_Transactions_Features_Count { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + v1: SeriesPattern18::new(client.clone(), "tx_count_v1".to_string()), + v2: SeriesPattern18::new(client.clone(), "tx_count_v2".to_string()), + v3: SeriesPattern18::new(client.clone(), "tx_count_v3".to_string()), + other_version: SeriesPattern18::new(client.clone(), "tx_count_other_version".to_string()), + explicitly_rbf: SeriesPattern18::new(client.clone(), "tx_count_explicitly_rbf".to_string()), + one_input: SeriesPattern18::new(client.clone(), "tx_count_one_input".to_string()), + one_output: SeriesPattern18::new(client.clone(), "tx_count_one_output".to_string()), + p2pk: SeriesPattern18::new(client.clone(), "tx_count_p2pk".to_string()), + p2ms: SeriesPattern18::new(client.clone(), "tx_count_p2ms".to_string()), + p2pkh: SeriesPattern18::new(client.clone(), "tx_count_p2pkh".to_string()), + p2sh: SeriesPattern18::new(client.clone(), "tx_count_p2sh".to_string()), + p2wpkh: SeriesPattern18::new(client.clone(), "tx_count_p2wpkh".to_string()), + p2wsh: SeriesPattern18::new(client.clone(), "tx_count_p2wsh".to_string()), + p2tr: SeriesPattern18::new(client.clone(), "tx_count_p2tr".to_string()), + p2a: SeriesPattern18::new(client.clone(), "tx_count_p2a".to_string()), + op_return: SeriesPattern18::new(client.clone(), "tx_count_op_return".to_string()), + empty: SeriesPattern18::new(client.clone(), "tx_count_empty".to_string()), + unknown: SeriesPattern18::new(client.clone(), "tx_count_unknown".to_string()), + fake_pubkey: SeriesPattern18::new(client.clone(), "tx_count_fake_pubkey".to_string()), + fake_scripthash: SeriesPattern18::new(client.clone(), "tx_count_fake_scripthash".to_string()), + inscription: SeriesPattern18::new(client.clone(), "tx_count_inscription".to_string()), + annex: SeriesPattern18::new(client.clone(), "tx_count_annex".to_string()), + sighash_all: SeriesPattern18::new(client.clone(), "tx_count_sighash_all".to_string()), + sighash_none: SeriesPattern18::new(client.clone(), "tx_count_sighash_none".to_string()), + sighash_single: SeriesPattern18::new(client.clone(), "tx_count_sighash_single".to_string()), + sighash_default: SeriesPattern18::new(client.clone(), "tx_count_sighash_default".to_string()), + sighash_anyone_can_pay: SeriesPattern18::new(client.clone(), "tx_count_sighash_anyone_can_pay".to_string()), + dust_output: SeriesPattern18::new(client.clone(), "tx_count_dust_output".to_string()), + } + } +} + /// Series tree node. pub struct SeriesTree_Transactions_Count { pub total: AverageBlockCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern, @@ -4044,53 +4194,140 @@ impl SeriesTree_Transactions_Count { /// Series tree node. pub struct SeriesTree_Transactions_Size { - pub vsize: _6bBlockTxPattern, + pub vsize: SeriesTree_Transactions_Size_Vsize, pub weight: SeriesTree_Transactions_Size_Weight, } impl SeriesTree_Transactions_Size { pub fn new(client: Arc, base_path: String) -> Self { Self { - vsize: _6bBlockTxPattern::new(client.clone(), "tx_vsize".to_string()), + vsize: SeriesTree_Transactions_Size_Vsize::new(client.clone(), format!("{base_path}_vsize")), weight: SeriesTree_Transactions_Size_Weight::new(client.clone(), format!("{base_path}_weight")), } } } /// Series tree node. -pub struct SeriesTree_Transactions_Size_Weight { - pub tx_index: SeriesPattern19, +pub struct SeriesTree_Transactions_Size_Vsize { + pub tx_index: SeriesPattern19, pub block: MaxMedianMinPct10Pct25Pct75Pct90Pattern2, pub _6b: MaxMedianMinPct10Pct25Pct75Pct90Pattern2, } +impl SeriesTree_Transactions_Size_Vsize { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + tx_index: SeriesPattern19::new(client.clone(), "tx_vsize".to_string()), + block: MaxMedianMinPct10Pct25Pct75Pct90Pattern2::new(client.clone(), "tx_vsize".to_string()), + _6b: MaxMedianMinPct10Pct25Pct75Pct90Pattern2::new(client.clone(), "tx_vsize_6b".to_string()), + } + } +} + +/// Series tree node. +pub struct SeriesTree_Transactions_Size_Weight { + pub block: MaxMedianMinPct10Pct25Pct75Pct90Pattern, + pub _6b: MaxMedianMinPct10Pct25Pct75Pct90Pattern, +} + impl SeriesTree_Transactions_Size_Weight { pub fn new(client: Arc, base_path: String) -> Self { Self { - tx_index: SeriesPattern19::new(client.clone(), "tx_weight".to_string()), - block: MaxMedianMinPct10Pct25Pct75Pct90Pattern2::new(client.clone(), "tx_weight".to_string()), - _6b: MaxMedianMinPct10Pct25Pct75Pct90Pattern2::new(client.clone(), "tx_weight_6b".to_string()), + block: MaxMedianMinPct10Pct25Pct75Pct90Pattern::new(client.clone(), "tx_weight".to_string()), + _6b: MaxMedianMinPct10Pct25Pct75Pct90Pattern::new(client.clone(), "tx_weight_6b".to_string()), } } } /// Series tree node. pub struct SeriesTree_Transactions_Fees { + pub count: SeriesTree_Transactions_Fees_Count, pub input_value: SeriesPattern19, pub output_value: SeriesPattern19, pub fee: _6bBlockTxPattern, pub fee_rate: SeriesPattern19, pub effective_fee_rate: _6bBlockTxPattern, + pub is_cpfp_parent: SeriesPattern19, + pub is_cpfp_child: SeriesPattern19, } impl SeriesTree_Transactions_Fees { pub fn new(client: Arc, base_path: String) -> Self { Self { + count: SeriesTree_Transactions_Fees_Count::new(client.clone(), format!("{base_path}_count")), input_value: SeriesPattern19::new(client.clone(), "input_value".to_string()), output_value: SeriesPattern19::new(client.clone(), "output_value".to_string()), fee: _6bBlockTxPattern::new(client.clone(), "fee".to_string()), fee_rate: SeriesPattern19::new(client.clone(), "fee_rate".to_string()), effective_fee_rate: _6bBlockTxPattern::new(client.clone(), "effective_fee_rate".to_string()), + is_cpfp_parent: SeriesPattern19::new(client.clone(), "is_cpfp_parent".to_string()), + is_cpfp_child: SeriesPattern19::new(client.clone(), "is_cpfp_child".to_string()), + } + } +} + +/// Series tree node. +pub struct SeriesTree_Transactions_Fees_Count { + pub cpfp_parent: SeriesPattern18, + pub cpfp_child: SeriesPattern18, +} + +impl SeriesTree_Transactions_Fees_Count { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + cpfp_parent: SeriesPattern18::new(client.clone(), "cpfp_parent_count".to_string()), + cpfp_child: SeriesPattern18::new(client.clone(), "cpfp_child_count".to_string()), + } + } +} + +/// Series tree node. +pub struct SeriesTree_Transactions_Patterns { + pub count: SeriesTree_Transactions_Patterns_Count, + pub is_coinjoin: SeriesPattern19, + pub is_consolidation: SeriesPattern19, + pub is_batch_payout: SeriesPattern19, +} + +impl SeriesTree_Transactions_Patterns { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + count: SeriesTree_Transactions_Patterns_Count::new(client.clone(), format!("{base_path}_count")), + is_coinjoin: SeriesPattern19::new(client.clone(), "is_coinjoin".to_string()), + is_consolidation: SeriesPattern19::new(client.clone(), "is_consolidation".to_string()), + is_batch_payout: SeriesPattern19::new(client.clone(), "is_batch_payout".to_string()), + } + } +} + +/// Series tree node. +pub struct SeriesTree_Transactions_Patterns_Count { + pub coinjoin: SeriesPattern18, + pub consolidation: SeriesPattern18, + pub batch_payout: SeriesPattern18, +} + +impl SeriesTree_Transactions_Patterns_Count { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + coinjoin: SeriesPattern18::new(client.clone(), "coinjoin_count".to_string()), + consolidation: SeriesPattern18::new(client.clone(), "consolidation_count".to_string()), + batch_payout: SeriesPattern18::new(client.clone(), "batch_payout_count".to_string()), + } + } +} + +/// Series tree node. +pub struct SeriesTree_Transactions_Policy { + pub count: SeriesPattern18, + pub is_nonstandard: SeriesPattern19, +} + +impl SeriesTree_Transactions_Policy { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + count: SeriesPattern18::new(client.clone(), "nonstandard_count".to_string()), + is_nonstandard: SeriesPattern19::new(client.clone(), "is_nonstandard".to_string()), } } } @@ -4100,6 +4337,7 @@ pub struct SeriesTree_Transactions_Versions { pub v1: AverageBlockCumulativeSumPattern, pub v2: AverageBlockCumulativeSumPattern, pub v3: AverageBlockCumulativeSumPattern, + pub other: AverageBlockCumulativeSumPattern, } impl SeriesTree_Transactions_Versions { @@ -4108,6 +4346,7 @@ impl SeriesTree_Transactions_Versions { v1: AverageBlockCumulativeSumPattern::new(client.clone(), "tx_v1".to_string()), v2: AverageBlockCumulativeSumPattern::new(client.clone(), "tx_v2".to_string()), v3: AverageBlockCumulativeSumPattern::new(client.clone(), "tx_v3".to_string()), + other: AverageBlockCumulativeSumPattern::new(client.clone(), "tx_other_version".to_string()), } } } @@ -5043,7 +5282,6 @@ impl SeriesTree_Scripts { /// Series tree node. pub struct SeriesTree_Scripts_Raw { pub empty: SeriesTree_Scripts_Raw_Empty, - pub op_return: SeriesTree_Scripts_Raw_OpReturn, pub p2ms: SeriesTree_Scripts_Raw_P2ms, pub unknown: SeriesTree_Scripts_Raw_Unknown, } @@ -5052,7 +5290,6 @@ impl SeriesTree_Scripts_Raw { pub fn new(client: Arc, base_path: String) -> Self { Self { empty: SeriesTree_Scripts_Raw_Empty::new(client.clone(), format!("{base_path}_empty")), - op_return: SeriesTree_Scripts_Raw_OpReturn::new(client.clone(), format!("{base_path}_op_return")), p2ms: SeriesTree_Scripts_Raw_P2ms::new(client.clone(), format!("{base_path}_p2ms")), unknown: SeriesTree_Scripts_Raw_Unknown::new(client.clone(), format!("{base_path}_unknown")), } @@ -5074,25 +5311,11 @@ impl SeriesTree_Scripts_Raw_Empty { } } -/// Series tree node. -pub struct SeriesTree_Scripts_Raw_OpReturn { - pub first_index: SeriesPattern18, - pub to_tx_index: SeriesPattern23, -} - -impl SeriesTree_Scripts_Raw_OpReturn { - pub fn new(client: Arc, base_path: String) -> Self { - Self { - first_index: SeriesPattern18::new(client.clone(), "first_op_return_index".to_string()), - to_tx_index: SeriesPattern23::new(client.clone(), "tx_index".to_string()), - } - } -} - /// Series tree node. pub struct SeriesTree_Scripts_Raw_P2ms { pub first_index: SeriesPattern18, pub to_tx_index: SeriesPattern25, + pub legacy_sigops: SeriesPattern25, } impl SeriesTree_Scripts_Raw_P2ms { @@ -5100,6 +5323,7 @@ impl SeriesTree_Scripts_Raw_P2ms { Self { first_index: SeriesPattern18::new(client.clone(), "first_p2ms_output_index".to_string()), to_tx_index: SeriesPattern25::new(client.clone(), "tx_index".to_string()), + legacy_sigops: SeriesPattern25::new(client.clone(), "p2ms_legacy_sigops".to_string()), } } } @@ -5108,6 +5332,7 @@ impl SeriesTree_Scripts_Raw_P2ms { pub struct SeriesTree_Scripts_Raw_Unknown { pub first_index: SeriesPattern18, pub to_tx_index: SeriesPattern33, + pub legacy_sigops: SeriesPattern33, } impl SeriesTree_Scripts_Raw_Unknown { @@ -5115,6 +5340,138 @@ impl SeriesTree_Scripts_Raw_Unknown { Self { first_index: SeriesPattern18::new(client.clone(), "first_unknown_output_index".to_string()), to_tx_index: SeriesPattern33::new(client.clone(), "tx_index".to_string()), + legacy_sigops: SeriesPattern33::new(client.clone(), "unknown_legacy_sigops".to_string()), + } + } +} + +/// Series tree node. +pub struct SeriesTree_OpReturn { + pub raw: SeriesTree_OpReturn_Raw, + pub total: SeriesTree_OpReturn_Total, + pub by_kind: SeriesTree_OpReturn_ByKind, + pub policy: SeriesTree_OpReturn_Policy, +} + +impl SeriesTree_OpReturn { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + raw: SeriesTree_OpReturn_Raw::new(client.clone(), format!("{base_path}_raw")), + total: SeriesTree_OpReturn_Total::new(client.clone(), format!("{base_path}_total")), + by_kind: SeriesTree_OpReturn_ByKind::new(client.clone(), format!("{base_path}_by_kind")), + policy: SeriesTree_OpReturn_Policy::new(client.clone(), format!("{base_path}_policy")), + } + } +} + +/// Series tree node. +pub struct SeriesTree_OpReturn_Raw { + pub first_index: SeriesPattern18, + pub to_tx_index: SeriesPattern23, + pub kind: SeriesPattern23, + pub post_op_return_bytes: SeriesPattern23, +} + +impl SeriesTree_OpReturn_Raw { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + first_index: SeriesPattern18::new(client.clone(), "first_op_return_index".to_string()), + to_tx_index: SeriesPattern23::new(client.clone(), "tx_index".to_string()), + kind: SeriesPattern23::new(client.clone(), "kind".to_string()), + post_op_return_bytes: SeriesPattern23::new(client.clone(), "op_return_post_op_return_bytes".to_string()), + } + } +} + +/// Series tree node. +pub struct SeriesTree_OpReturn_Total { + pub post_op_return_bytes: AverageBlockCumulativeSumPattern, + pub carrier_tx_count: AverageBlockCumulativeSumPattern, + pub carrier_vsize: AverageBlockCumulativeSumPattern, +} + +impl SeriesTree_OpReturn_Total { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + post_op_return_bytes: AverageBlockCumulativeSumPattern::new(client.clone(), "op_return_post_op_return_bytes".to_string()), + carrier_tx_count: AverageBlockCumulativeSumPattern::new(client.clone(), "op_return_carrier_tx_count".to_string()), + carrier_vsize: AverageBlockCumulativeSumPattern::new(client.clone(), "op_return_carrier_vsize".to_string()), + } + } +} + +/// Series tree node. +pub struct SeriesTree_OpReturn_ByKind { + pub runes: CarrierOutputPostPattern, + pub veri_block: CarrierOutputPostPattern, + pub omni: CarrierOutputPostPattern, + pub stacks: CarrierOutputPostPattern, + pub blockstack: CarrierOutputPostPattern, + pub colu: CarrierOutputPostPattern, + pub open_assets: CarrierOutputPostPattern, + pub komodo: CarrierOutputPostPattern, + pub coin_spark: CarrierOutputPostPattern, + pub poet: CarrierOutputPostPattern, + pub docproof: CarrierOutputPostPattern, + pub open_timestamps: CarrierOutputPostPattern, + pub factom: CarrierOutputPostPattern, + pub eternity_wall: CarrierOutputPostPattern, + pub memo: CarrierOutputPostPattern, + pub bitproof: CarrierOutputPostPattern, + pub ascribe: CarrierOutputPostPattern, + pub stampery: CarrierOutputPostPattern, + pub epobc: CarrierOutputPostPattern, + pub bare_hash: CarrierOutputPostPattern, + pub text: CarrierOutputPostPattern, + pub empty: CarrierOutputPostPattern, + pub unknown: CarrierOutputPostPattern, +} + +impl SeriesTree_OpReturn_ByKind { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + runes: CarrierOutputPostPattern::new(client.clone(), "op_return_runes".to_string()), + veri_block: CarrierOutputPostPattern::new(client.clone(), "op_return_veri_block".to_string()), + omni: CarrierOutputPostPattern::new(client.clone(), "op_return_omni".to_string()), + stacks: CarrierOutputPostPattern::new(client.clone(), "op_return_stacks".to_string()), + blockstack: CarrierOutputPostPattern::new(client.clone(), "op_return_blockstack".to_string()), + colu: CarrierOutputPostPattern::new(client.clone(), "op_return_colu".to_string()), + open_assets: CarrierOutputPostPattern::new(client.clone(), "op_return_open_assets".to_string()), + komodo: CarrierOutputPostPattern::new(client.clone(), "op_return_komodo".to_string()), + coin_spark: CarrierOutputPostPattern::new(client.clone(), "op_return_coin_spark".to_string()), + poet: CarrierOutputPostPattern::new(client.clone(), "op_return_poet".to_string()), + docproof: CarrierOutputPostPattern::new(client.clone(), "op_return_docproof".to_string()), + open_timestamps: CarrierOutputPostPattern::new(client.clone(), "op_return_open_timestamps".to_string()), + factom: CarrierOutputPostPattern::new(client.clone(), "op_return_factom".to_string()), + eternity_wall: CarrierOutputPostPattern::new(client.clone(), "op_return_eternity_wall".to_string()), + memo: CarrierOutputPostPattern::new(client.clone(), "op_return_memo".to_string()), + bitproof: CarrierOutputPostPattern::new(client.clone(), "op_return_bitproof".to_string()), + ascribe: CarrierOutputPostPattern::new(client.clone(), "op_return_ascribe".to_string()), + stampery: CarrierOutputPostPattern::new(client.clone(), "op_return_stampery".to_string()), + epobc: CarrierOutputPostPattern::new(client.clone(), "op_return_epobc".to_string()), + bare_hash: CarrierOutputPostPattern::new(client.clone(), "op_return_bare_hash".to_string()), + text: CarrierOutputPostPattern::new(client.clone(), "op_return_text".to_string()), + empty: CarrierOutputPostPattern::new(client.clone(), "op_return_empty".to_string()), + unknown: CarrierOutputPostPattern::new(client.clone(), "op_return_unknown".to_string()), + } + } +} + +/// Series tree node. +pub struct SeriesTree_OpReturn_Policy { + pub standard: CarrierOutputPostPattern, + pub oversized: CarrierOutputPostPattern, + pub multiple: CarrierOutputPostPattern, + pub pre_v30_nonstandard: CarrierOutputPostPattern, +} + +impl SeriesTree_OpReturn_Policy { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + standard: CarrierOutputPostPattern::new(client.clone(), "op_return_policy_standard".to_string()), + oversized: CarrierOutputPostPattern::new(client.clone(), "op_return_policy_oversized".to_string()), + multiple: CarrierOutputPostPattern::new(client.clone(), "op_return_policy_multiple".to_string()), + pre_v30_nonstandard: CarrierOutputPostPattern::new(client.clone(), "op_return_policy_pre_v30_nonstandard".to_string()), } } } diff --git a/crates/brk_computer/src/internal/per_tx/lazy_distribution.rs b/crates/brk_computer/src/internal/per_tx/lazy_distribution.rs deleted file mode 100644 index 82d5c4a0f..000000000 --- a/crates/brk_computer/src/internal/per_tx/lazy_distribution.rs +++ /dev/null @@ -1,58 +0,0 @@ -use brk_error::Result; -use brk_indexer::{Indexer, Lengths}; -use brk_traversable::Traversable; -use brk_types::TxIndex; -use schemars::JsonSchema; -use vecdb::{Database, Exit, LazyVecFrom1, ReadableVec, Rw, StorageMode, Version}; - -use crate::{ - indexes, - internal::{ComputedVecValue, NumericValue, TxDerivedDistribution}, -}; - -#[derive(Traversable)] -pub struct LazyPerTxDistribution -where - T: ComputedVecValue + PartialOrd + JsonSchema, - S: ComputedVecValue, -{ - pub tx_index: LazyVecFrom1, - #[traversable(flatten)] - pub distribution: TxDerivedDistribution, -} - -impl LazyPerTxDistribution -where - T: NumericValue + JsonSchema, - S: ComputedVecValue + JsonSchema, -{ - pub(crate) fn forced_import( - db: &Database, - name: &str, - version: Version, - indexes: &indexes::Vecs, - tx_index: LazyVecFrom1, - ) -> Result { - let distribution = TxDerivedDistribution::forced_import(db, name, version, indexes)?; - Ok(Self { - tx_index, - distribution, - }) - } - - pub(crate) fn derive_from( - &mut self, - indexer: &Indexer, - indexes: &indexes::Vecs, - starting_lengths: &Lengths, - exit: &Exit, - ) -> Result<()> - where - T: Copy + Ord + From + Default, - f64: From, - LazyVecFrom1: ReadableVec, - { - self.distribution - .derive_from(indexer, indexes, starting_lengths, &self.tx_index, exit) - } -} diff --git a/crates/brk_computer/src/internal/per_tx/lazy_distribution_transformed.rs b/crates/brk_computer/src/internal/per_tx/lazy_distribution_transformed.rs index 78ef0bb5c..65a4ed2ff 100644 --- a/crates/brk_computer/src/internal/per_tx/lazy_distribution_transformed.rs +++ b/crates/brk_computer/src/internal/per_tx/lazy_distribution_transformed.rs @@ -5,8 +5,7 @@ use vecdb::{LazyVecFrom1, UnaryTransform}; use crate::internal::{ComputedVecValue, LazyTxDerivedDistribution, TxDerivedDistribution}; -/// Like `LazyPerTxDistribution` but with a lazy-derived distribution -/// (transformed from another type's distribution rather than eagerly computed). +/// Per-transaction lazy values with a distribution transformed from another type's distribution. #[derive(Clone, Traversable)] pub struct LazyPerTxDistributionTransformed where diff --git a/crates/brk_computer/src/internal/per_tx/mod.rs b/crates/brk_computer/src/internal/per_tx/mod.rs index 31eac0154..997aeeaf9 100644 --- a/crates/brk_computer/src/internal/per_tx/mod.rs +++ b/crates/brk_computer/src/internal/per_tx/mod.rs @@ -1,11 +1,9 @@ mod derived; mod distribution; mod lazy_derived; -mod lazy_distribution; mod lazy_distribution_transformed; pub use derived::*; pub use distribution::*; pub use lazy_derived::*; -pub use lazy_distribution::*; pub use lazy_distribution_transformed::*; diff --git a/crates/brk_computer/src/lib.rs b/crates/brk_computer/src/lib.rs index b9b322051..f7cf80f89 100644 --- a/crates/brk_computer/src/lib.rs +++ b/crates/brk_computer/src/lib.rs @@ -151,6 +151,7 @@ impl Computer { &computed_path, VERSION, &indexes, + &cached_starts, )?)) })?; diff --git a/crates/brk_computer/src/op_return/compute.rs b/crates/brk_computer/src/op_return/compute.rs index ea25690da..c56f71892 100644 --- a/crates/brk_computer/src/op_return/compute.rs +++ b/crates/brk_computer/src/op_return/compute.rs @@ -11,6 +11,7 @@ const WRITE_INTERVAL: usize = 10_000; #[derive(Clone, Copy, Default)] struct PolicyTotals { + standard: Totals, oversized: Totals, multiple: Totals, pre_v30_nonstandard: Totals, @@ -54,19 +55,11 @@ impl Vecs { self.validate_and_truncate(version, starting_lengths.height)?; let skip = self.min_len(); - let end = raw - .first_index - .len() - .min(starting_lengths.height.to_usize()); + let end = raw.first_index.len(); if skip < end { self.truncate_if_needed_at(skip)?; - let op_return_len = raw - .to_tx_index - .len() - .min(raw.kind.len()) - .min(raw.post_op_return_bytes.len()) - .min(starting_lengths.op_return_index.to_usize()); + let op_return_len = raw.to_tx_index.len(); let mut tx_cursor = raw.to_tx_index.cursor(); let mut kind_cursor = raw.kind.cursor(); let mut post_op_return_bytes = raw.post_op_return_bytes.cursor(); @@ -108,7 +101,6 @@ impl Vecs { carrier.vsize = VSize::from(weight_cursor.next().unwrap()); } - total.output_count += 1; total.post_op_return_bytes += bytes; by_kind[kind_index].output_count += 1; by_kind[kind_index].post_op_return_bytes += bytes; @@ -121,6 +113,7 @@ impl Vecs { for (kind, metrics) in self.by_kind.iter_typed_mut() { metrics.push(by_kind[kind as usize]); } + self.policy.standard.push(policy.standard); self.policy.oversized.push(policy.oversized); self.policy.multiple.push(policy.multiple); self.policy @@ -183,6 +176,10 @@ fn finalize_transaction( policy.pre_v30_nonstandard.output_count += carrier.output_count; policy.pre_v30_nonstandard.post_op_return_bytes += carrier.post_op_return_bytes; add_carrier(&mut policy.pre_v30_nonstandard, carrier.vsize); + } else { + policy.standard.output_count += carrier.output_count; + policy.standard.post_op_return_bytes += carrier.post_op_return_bytes; + add_carrier(&mut policy.standard, carrier.vsize); } } @@ -219,6 +216,7 @@ mod tests { assert_eq!(policy.multiple.output_count, 2); assert_eq!(policy.pre_v30_nonstandard.carrier_tx_count, 1); assert_eq!(policy.oversized.carrier_tx_count, 0); + assert_eq!(policy.standard.carrier_tx_count, 0); } #[test] @@ -238,5 +236,26 @@ mod tests { assert_eq!(policy.oversized.carrier_vsize, VSize::new(120)); assert_eq!(policy.pre_v30_nonstandard.carrier_tx_count, 1); assert_eq!(policy.multiple.carrier_tx_count, 0); + assert_eq!(policy.standard.carrier_tx_count, 0); + } + + #[test] + fn standard_output_is_recorded_directly() { + let mut total = Totals::default(); + let mut by_kind = [Totals::default(); KIND_COUNT]; + let mut policy = PolicyTotals::default(); + let mut carrier = Carrier { + vsize: VSize::new(100), + ..Carrier::default() + }; + carrier.add_output(OpReturnKind::Runes, 15); + + finalize_transaction(&mut total, &mut by_kind, &mut policy, carrier); + + assert_eq!(policy.standard.output_count, 1); + assert_eq!(policy.standard.post_op_return_bytes, 15); + assert_eq!(policy.standard.carrier_tx_count, 1); + assert_eq!(policy.standard.carrier_vsize, VSize::new(100)); + assert_eq!(policy.pre_v30_nonstandard.carrier_tx_count, 0); } } diff --git a/crates/brk_computer/src/op_return/import.rs b/crates/brk_computer/src/op_return/import.rs index e222774e7..450d1f392 100644 --- a/crates/brk_computer/src/op_return/import.rs +++ b/crates/brk_computer/src/op_return/import.rs @@ -3,10 +3,13 @@ use std::path::Path; use brk_error::Result; use brk_types::Version; -use super::{ByKind, Metrics, Policy, Vecs}; +use super::{ByKind, Metrics, Policy, TotalMetrics, Vecs}; use crate::{ indexes, - internal::db_utils::{finalize_db, open_db}, + internal::{ + WindowStartVec, Windows, + db_utils::{finalize_db, open_db}, + }, }; impl Vecs { @@ -14,13 +17,20 @@ impl Vecs { parent_path: &Path, version: Version, indexes: &indexes::Vecs, + cached_starts: &Windows<&WindowStartVec>, ) -> Result { let db = open_db(parent_path, super::DB_NAME, 1_000_000)?; - let total = Metrics::forced_import(&db, "op_return", version, indexes)?; + let total = TotalMetrics::forced_import(&db, "op_return", version, indexes, cached_starts)?; let by_kind = ByKind::try_new(|_, name| { - Metrics::forced_import(&db, &format!("op_return_{name}"), version, indexes) + Metrics::forced_import( + &db, + &format!("op_return_{name}"), + version, + indexes, + cached_starts, + ) })?; - let policy = Policy::forced_import(&db, version, indexes)?; + let policy = Policy::forced_import(&db, version, indexes, cached_starts)?; let this = Self { db, diff --git a/crates/brk_computer/src/op_return/mod.rs b/crates/brk_computer/src/op_return/mod.rs index c979eb4f8..a46ace6b1 100644 --- a/crates/brk_computer/src/op_return/mod.rs +++ b/crates/brk_computer/src/op_return/mod.rs @@ -4,6 +4,6 @@ mod import; mod vecs; pub use by_kind::ByKind; -pub use vecs::{Metrics, Policy, Vecs}; +pub use vecs::{Metrics, Policy, TotalMetrics, Vecs}; pub const DB_NAME: &str = "op_return"; diff --git a/crates/brk_computer/src/op_return/vecs.rs b/crates/brk_computer/src/op_return/vecs.rs index a3dc0b119..fe50c58d8 100644 --- a/crates/brk_computer/src/op_return/vecs.rs +++ b/crates/brk_computer/src/op_return/vecs.rs @@ -1,73 +1,15 @@ use brk_error::Result; use brk_traversable::Traversable; use brk_types::{Height, StoredU64, VSize, Version}; -use schemars::JsonSchema; -use vecdb::{ - AnyStoredVec, AnyVec, Database, EagerVec, Exit, ImportableVec, PcoVec, Rw, StorageMode, - WritableVec, -}; +use vecdb::{AnyStoredVec, AnyVec, Database, Exit, Rw, StorageMode, WritableVec}; use super::ByKind; use crate::{ indexes, - internal::{NumericValue, PerBlock}, + internal::{PerBlockCumulativeRolling, WindowStartVec, Windows}, }; -#[derive(Traversable)] -pub struct Series -where - T: NumericValue + JsonSchema, -{ - pub block: M::Stored>>, - pub cumulative: PerBlock, -} - -impl Series -where - T: NumericValue + JsonSchema, -{ - fn forced_import( - db: &Database, - name: &str, - version: Version, - indexes: &indexes::Vecs, - ) -> Result { - let block = EagerVec::forced_import(db, name, version)?; - let cumulative = - PerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?; - Ok(Self { block, cumulative }) - } - - fn len(&self) -> usize { - self.block.len() - } - - fn validate_and_truncate(&mut self, version: Version, height: Height) -> Result<()> { - self.block.validate_and_truncate(version, height)?; - Ok(()) - } - - fn truncate_if_needed_at(&mut self, len: usize) -> Result<()> { - self.block.truncate_if_needed_at(len)?; - Ok(()) - } - - fn push(&mut self, block: T) { - self.block.push(block); - } - - fn write(&mut self) -> Result<()> { - self.block.write()?; - Ok(()) - } - - fn compute_cumulative(&mut self, max_from: Height, exit: &Exit) -> Result<()> { - self.cumulative - .height - .compute_cumulative(max_from, &self.block, exit)?; - Ok(()) - } -} +pub type Series = PerBlockCumulativeRolling; #[derive(Clone, Copy, Default)] pub(super) struct Totals { @@ -78,19 +20,112 @@ pub(super) struct Totals { } #[derive(Traversable)] -pub struct Metrics { - pub output_count: Series, +pub struct TotalMetrics { pub post_op_return_bytes: Series, pub carrier_tx_count: Series, pub carrier_vsize: Series, } +impl TotalMetrics { + pub(crate) fn forced_import( + db: &Database, + prefix: &str, + version: Version, + indexes: &indexes::Vecs, + cached_starts: &Windows<&WindowStartVec>, + ) -> Result { + Ok(Self { + post_op_return_bytes: Series::forced_import( + db, + &format!("{prefix}_post_op_return_bytes"), + version, + indexes, + cached_starts, + )?, + carrier_tx_count: Series::forced_import( + db, + &format!("{prefix}_carrier_tx_count"), + version, + indexes, + cached_starts, + )?, + carrier_vsize: Series::forced_import( + db, + &format!("{prefix}_carrier_vsize"), + version, + indexes, + cached_starts, + )?, + }) + } + + fn len(&self) -> usize { + self.post_op_return_bytes + .block + .len() + .min(self.carrier_tx_count.block.len()) + .min(self.carrier_vsize.block.len()) + } + + pub(super) fn push(&mut self, block: Totals) { + self.post_op_return_bytes + .block + .push(block.post_op_return_bytes.into()); + self.carrier_tx_count + .block + .push(block.carrier_tx_count.into()); + self.carrier_vsize.block.push(block.carrier_vsize); + } + + fn validate_and_truncate(&mut self, version: Version, height: Height) -> Result<()> { + self.post_op_return_bytes + .block + .validate_and_truncate(version, height)?; + self.carrier_tx_count + .block + .validate_and_truncate(version, height)?; + self.carrier_vsize + .block + .validate_and_truncate(version, height)?; + Ok(()) + } + + fn truncate_if_needed_at(&mut self, len: usize) -> Result<()> { + self.post_op_return_bytes.block.truncate_if_needed_at(len)?; + self.carrier_tx_count.block.truncate_if_needed_at(len)?; + self.carrier_vsize.block.truncate_if_needed_at(len)?; + Ok(()) + } + + fn write(&mut self) -> Result<()> { + self.post_op_return_bytes.block.write()?; + self.carrier_tx_count.block.write()?; + self.carrier_vsize.block.write()?; + Ok(()) + } + + fn compute_cumulative(&mut self, max_from: Height, exit: &Exit) -> Result<()> { + self.post_op_return_bytes.compute_rest(max_from, exit)?; + self.carrier_tx_count.compute_rest(max_from, exit)?; + self.carrier_vsize.compute_rest(max_from, exit)?; + Ok(()) + } +} + +#[derive(Traversable)] +pub struct Metrics { + pub output_count: Series, + #[traversable(flatten)] + pub total: TotalMetrics, +} + impl Metrics { pub(crate) fn forced_import( db: &Database, prefix: &str, version: Version, indexes: &indexes::Vecs, + cached_starts: &Windows<&WindowStartVec>, ) -> Result { Ok(Self { output_count: Series::forced_import( @@ -98,82 +133,51 @@ impl Metrics { &format!("{prefix}_output_count"), version, indexes, + cached_starts, )?, - post_op_return_bytes: Series::forced_import( - db, - &format!("{prefix}_post_op_return_bytes"), - version, - indexes, - )?, - carrier_tx_count: Series::forced_import( - db, - &format!("{prefix}_carrier_tx_count"), - version, - indexes, - )?, - carrier_vsize: Series::forced_import( - db, - &format!("{prefix}_carrier_vsize"), - version, - indexes, - )?, + total: TotalMetrics::forced_import(db, prefix, version, indexes, cached_starts)?, }) } fn len(&self) -> usize { - self.output_count - .len() - .min(self.post_op_return_bytes.len()) - .min(self.carrier_tx_count.len()) - .min(self.carrier_vsize.len()) + self.output_count.block.len().min(self.total.len()) } pub(super) fn push(&mut self, block: Totals) { - self.output_count.push(block.output_count.into()); - self.post_op_return_bytes - .push(block.post_op_return_bytes.into()); - self.carrier_tx_count.push(block.carrier_tx_count.into()); - self.carrier_vsize.push(block.carrier_vsize); + self.output_count.block.push(block.output_count.into()); + self.total.push(block); } fn validate_and_truncate(&mut self, version: Version, height: Height) -> Result<()> { - self.output_count.validate_and_truncate(version, height)?; - self.post_op_return_bytes + self.output_count + .block .validate_and_truncate(version, height)?; - self.carrier_tx_count - .validate_and_truncate(version, height)?; - self.carrier_vsize.validate_and_truncate(version, height)?; + self.total.validate_and_truncate(version, height)?; Ok(()) } fn truncate_if_needed_at(&mut self, len: usize) -> Result<()> { - self.output_count.truncate_if_needed_at(len)?; - self.post_op_return_bytes.truncate_if_needed_at(len)?; - self.carrier_tx_count.truncate_if_needed_at(len)?; - self.carrier_vsize.truncate_if_needed_at(len)?; + self.output_count.block.truncate_if_needed_at(len)?; + self.total.truncate_if_needed_at(len)?; Ok(()) } fn write(&mut self) -> Result<()> { - self.output_count.write()?; - self.post_op_return_bytes.write()?; - self.carrier_tx_count.write()?; - self.carrier_vsize.write()?; + self.output_count.block.write()?; + self.total.write()?; Ok(()) } fn compute_cumulative(&mut self, max_from: Height, exit: &Exit) -> Result<()> { - self.output_count.compute_cumulative(max_from, exit)?; - self.post_op_return_bytes - .compute_cumulative(max_from, exit)?; - self.carrier_tx_count.compute_cumulative(max_from, exit)?; - self.carrier_vsize.compute_cumulative(max_from, exit)?; + self.output_count.compute_rest(max_from, exit)?; + self.total.compute_cumulative(max_from, exit)?; Ok(()) } } #[derive(Traversable)] pub struct Policy { + pub standard: Metrics, pub oversized: Metrics, pub multiple: Metrics, pub pre_v30_nonstandard: Metrics, @@ -184,12 +188,20 @@ impl Policy { db: &Database, version: Version, indexes: &indexes::Vecs, + cached_starts: &Windows<&WindowStartVec>, ) -> Result { let import = |name| { - Metrics::forced_import(db, &format!("op_return_policy_{name}"), version, indexes) + Metrics::forced_import( + db, + &format!("op_return_policy_{name}"), + version, + indexes, + cached_starts, + ) }; Ok(Self { + standard: import("standard")?, oversized: import("oversized")?, multiple: import("multiple")?, pre_v30_nonstandard: import("pre_v30_nonstandard")?, @@ -197,11 +209,18 @@ impl Policy { } fn iter(&self) -> impl Iterator { - [&self.oversized, &self.multiple, &self.pre_v30_nonstandard].into_iter() + [ + &self.standard, + &self.oversized, + &self.multiple, + &self.pre_v30_nonstandard, + ] + .into_iter() } fn iter_mut(&mut self) -> impl Iterator { [ + &mut self.standard, &mut self.oversized, &mut self.multiple, &mut self.pre_v30_nonstandard, @@ -214,7 +233,7 @@ impl Policy { pub struct Vecs { #[traversable(skip)] pub(crate) db: Database, - pub total: Metrics, + pub total: TotalMetrics, pub by_kind: ByKind>, pub policy: Policy, } diff --git a/crates/brk_computer/src/transactions/fees/compute.rs b/crates/brk_computer/src/transactions/fees/compute.rs index 8239758a0..0277bf952 100644 --- a/crates/brk_computer/src/transactions/fees/compute.rs +++ b/crates/brk_computer/src/transactions/fees/compute.rs @@ -103,8 +103,7 @@ impl Vecs { .input_value .len() .min(self.output_value.len()) - .min(size_vecs.vsize.tx_index.len()) - .min(starting_lengths.tx_index.to_usize()); + .min(size_vecs.vsize.tx_index.len()); let tx_len = self .fee .tx_index @@ -119,7 +118,6 @@ impl Vecs { .transactions .first_tx_index .len() - .min(starting_lengths.height.to_usize()) .min(indexes.height.tx_index_count.len()); let next_height = if tx_len >= target { max_height @@ -201,12 +199,7 @@ impl Vecs { let input_end = if h + 1 < max_height { next_block_input.next().unwrap().to_usize() } else { - indexer - .vecs - .inputs - .outpoint - .len() - .min(starting_lengths.txin_index.to_usize()) + indexer.vecs.inputs.outpoint.len() }; indexer.vecs.inputs.outpoint.collect_range_into_at( input_begin, @@ -417,7 +410,7 @@ fn same_block_parents<'a>( outpoints[start..end].iter().filter_map(move |outpoint| { let parent = outpoint.tx_index().to_usize(); - (parent >= first_tx && parent < first_tx + tx_count).then_some(parent - first_tx) + (parent >= first_tx && parent < first_tx + tx_count).then(|| parent - first_tx) }) } @@ -472,7 +465,10 @@ mod tests { let mut cluster = Cluster::default(); cluster_fee_rates( &[TxInIndex::from(0usize), TxInIndex::from(1usize)], - &[OutPoint::COINBASE, OutPoint::COINBASE], + &[ + OutPoint::COINBASE, + OutPoint::new(TxIndex::from(9usize), Vout::ZERO), + ], 0, 10, &[Sats::new(100), Sats::new(300)], diff --git a/crates/brk_computer/src/transactions/patterns/compute.rs b/crates/brk_computer/src/transactions/patterns/compute.rs index d98628198..a7e5f2eb3 100644 --- a/crates/brk_computer/src/transactions/patterns/compute.rs +++ b/crates/brk_computer/src/transactions/patterns/compute.rs @@ -47,22 +47,22 @@ impl Vecs { vec.validate_computed_version_or_reset(version)?; } - let lengths = indexer.safe_lengths(); - let target_tx = lengths.tx_index.to_usize(); - let target_height = lengths.height.to_usize(); + let starting_lengths = indexer.safe_lengths(); + let target_tx = indexes.tx_index.input_count.len(); + let target_height = indexes.height.tx_index_count.len(); let tx_len = self .is_coinjoin .len() .min(self.is_consolidation.len()) .min(self.is_batch_payout.len()) - .min(target_tx); + .min(starting_lengths.tx_index.to_usize()); let count_len = self .count .coinjoin .len() .min(self.count.consolidation.len()) .min(self.count.batch_payout.len()) - .min(target_height); + .min(starting_lengths.height.to_usize()); let start_height = count_len.min(next_height(indexes, tx_len, target_tx, target_height)); if start_height >= target_height { return Ok(()); diff --git a/crates/brk_computer/src/transactions/policy/compute.rs b/crates/brk_computer/src/transactions/policy/compute.rs index 146d04b14..cd1a25d3a 100644 --- a/crates/brk_computer/src/transactions/policy/compute.rs +++ b/crates/brk_computer/src/transactions/policy/compute.rs @@ -27,11 +27,14 @@ impl Vecs { .validate_computed_version_or_reset(version)?; self.count.validate_computed_version_or_reset(version)?; - let lengths = indexer.safe_lengths(); - let target_tx = lengths.tx_index.to_usize().min(fees.fee.tx_index.len()); - let target_height = lengths.height.to_usize(); - let tx_len = self.is_nonstandard.len().min(target_tx); - let count_len = self.count.len().min(target_height); + let starting_lengths = indexer.safe_lengths(); + let target_tx = fees.fee.tx_index.len(); + let target_height = indexes.height.tx_index_count.len(); + let tx_len = self + .is_nonstandard + .len() + .min(starting_lengths.tx_index.to_usize()); + let count_len = self.count.len().min(starting_lengths.height.to_usize()); let next_height = if tx_len >= target_tx { target_height } else { diff --git a/crates/brk_computer/src/transactions/size/compute.rs b/crates/brk_computer/src/transactions/size/compute.rs index 1af8fce8a..351bcce8c 100644 --- a/crates/brk_computer/src/transactions/size/compute.rs +++ b/crates/brk_computer/src/transactions/size/compute.rs @@ -14,8 +14,13 @@ impl Vecs { ) -> Result<()> { let starting_lengths = indexer.safe_lengths(); - self.weight - .derive_from(indexer, indexes, &starting_lengths, exit)?; + self.weight.derive_from( + indexer, + indexes, + &starting_lengths, + &indexer.vecs.transactions.weight, + exit, + )?; Ok(()) } diff --git a/crates/brk_computer/src/transactions/size/import.rs b/crates/brk_computer/src/transactions/size/import.rs index a63a9d1f4..2f6e1b57e 100644 --- a/crates/brk_computer/src/transactions/size/import.rs +++ b/crates/brk_computer/src/transactions/size/import.rs @@ -1,12 +1,12 @@ use brk_error::Result; use brk_indexer::Indexer; -use brk_types::{Version, Weight}; +use brk_types::Version; use vecdb::{Database, LazyVecFrom1, ReadableCloneableVec}; use super::Vecs; use crate::{ indexes, - internal::{Identity, LazyPerTxDistribution, LazyPerTxDistributionTransformed, WeightToVSize}, + internal::{LazyPerTxDistributionTransformed, TxDerivedDistribution, WeightToVSize}, }; impl Vecs { @@ -16,19 +16,7 @@ impl Vecs { indexer: &Indexer, indexes: &indexes::Vecs, ) -> Result { - let tx_index_to_weight = LazyVecFrom1::transformed::>( - "tx_weight", - version, - indexer.vecs.transactions.weight.read_only_boxed_clone(), - ); - - let weight = LazyPerTxDistribution::forced_import( - db, - "tx_weight", - version, - indexes, - tx_index_to_weight, - )?; + let weight = TxDerivedDistribution::forced_import(db, "tx_weight", version, indexes)?; let tx_index_to_vsize = LazyVecFrom1::transformed::( "tx_vsize", @@ -40,7 +28,7 @@ impl Vecs { "tx_vsize", version, tx_index_to_vsize, - &weight.distribution, + &weight, ); Ok(Self { vsize, weight }) diff --git a/crates/brk_computer/src/transactions/size/vecs.rs b/crates/brk_computer/src/transactions/size/vecs.rs index 3003a6751..62548758c 100644 --- a/crates/brk_computer/src/transactions/size/vecs.rs +++ b/crates/brk_computer/src/transactions/size/vecs.rs @@ -2,10 +2,10 @@ use brk_traversable::Traversable; use brk_types::{VSize, Weight}; use vecdb::{Rw, StorageMode}; -use crate::internal::{LazyPerTxDistribution, LazyPerTxDistributionTransformed}; +use crate::internal::{LazyPerTxDistributionTransformed, TxDerivedDistribution}; #[derive(Traversable)] pub struct Vecs { pub vsize: LazyPerTxDistributionTransformed, - pub weight: LazyPerTxDistribution, + pub weight: TxDerivedDistribution, } diff --git a/crates/brk_indexer/src/lib.rs b/crates/brk_indexer/src/lib.rs index 043cc6584..ebc54dd4a 100644 --- a/crates/brk_indexer/src/lib.rs +++ b/crates/brk_indexer/src/lib.rs @@ -283,7 +283,6 @@ impl Indexer { processor.process_block_metadata()?; let txs = processor.compute_txids()?; - processor.push_block_size_and_weight(&txs)?; let (txins_result, txouts_result) = rayon::join( @@ -292,6 +291,7 @@ impl Indexer { ); let txins = txins_result?; let txouts = txouts_result?; + let tx_count = block.txdata.len(); let input_count = txins.len(); let output_count = txouts.len(); diff --git a/crates/brk_indexer/src/processor/txin/resolver.rs b/crates/brk_indexer/src/processor/txin/resolver.rs index d041d0ec7..21090e43e 100644 --- a/crates/brk_indexer/src/processor/txin/resolver.rs +++ b/crates/brk_indexer/src/processor/txin/resolver.rs @@ -1,7 +1,9 @@ use std::collections::hash_map::Entry; use brk_error::{Error, Result}; -use brk_types::{OutPoint, SigOps, TxIndex, TxOutIndex, Txid, TxidPrefix, Vout}; +use brk_types::{ + OutPoint, OutputType, SigOps, TxIndex, TxOutIndex, Txid, TxidPrefix, TypeIndex, Vout, +}; use rayon::prelude::*; use rustc_hash::FxHashMap; use tracing::error; @@ -16,6 +18,7 @@ pub(crate) struct InputResolver { previous_parent_indexes: FxHashMap, previous_parents: Vec, inputs: Vec, + reads: ReadBatch, } impl InputResolver { @@ -25,54 +28,20 @@ impl InputResolver { txs: &[ComputedTx<'_>], ) -> Result> { self.prepare(txs, processor.lengths.tx_index); - - let current_tx_index = processor.lengths.tx_index; - let parents = self - .previous_parents - .par_iter() - .map(|parent| { - let store_result = processor - .stores - .txid_prefix_to_tx_index - .get(&parent.txid_prefix)? - .map(|value| *value); - - let tx_index = match store_result { - Some(tx_index) if tx_index < current_tx_index => tx_index, - _ => { - error!( - "UnknownTxid: txid={}, prefix={:?}, store_result={:?}, current_tx_index={:?}", - parent.txid, - parent.txid_prefix, - store_result, - current_tx_index - ); - return Err(Error::UnknownTxid); - } - }; - - let first_txout_index = processor - .vecs - .transactions - .first_txout_index - .get_pushed_or_read( - tx_index, - &processor.readers.tx_index_to_first_txout_index, - ) - .ok_or(Error::Internal("Missing txout_index"))?; - - Ok(ResolvedParent { - tx_index, - first_txout_index, - }) - }) - .collect::>>()?; + self.reads.resolve( + processor, + &self.previous_parents, + &self.inputs, + processor.lengths.tx_index, + )?; let tracks_executed_legacy_sigops = processor.tracks_executed_legacy_sigops(); + let reads = &self.reads; self.inputs .par_iter() - .map(|input| match *input { + .enumerate() + .map(|(input_index, input)| match *input { UnresolvedInput::Coinbase => Ok(InputSource::Coinbase), UnresolvedInput::SameBlock { outpoint, @@ -82,29 +51,9 @@ impl InputResolver { txout_offset, }), UnresolvedInput::PreviousBlock { parent_index, vout } => { - let parent = parents[parent_index]; - let txout_index = parent.first_txout_index + vout; + let parent = reads.parent(parent_index); let outpoint = OutPoint::new(parent.tx_index, vout); - - let output_type = processor - .vecs - .outputs - .output_type - .get_pushed_or_read( - txout_index, - &processor.readers.txout_index_to_output_type, - ) - .ok_or(Error::Internal("Missing output_type"))?; - - let type_index = processor - .vecs - .outputs - .type_index - .get_pushed_or_read( - txout_index, - &processor.readers.txout_index_to_type_index, - ) - .ok_or(Error::Internal("Missing type_index"))?; + let (output_type, type_index) = reads.output(input_index); let legacy_sigops = if tracks_executed_legacy_sigops { processor @@ -186,11 +135,186 @@ struct PreviousParent { } #[derive(Clone, Copy)] -struct ResolvedParent { +struct ParentRead { + original_index: usize, tx_index: TxIndex, first_txout_index: TxOutIndex, } +#[derive(Clone, Copy)] +struct OutputRead { + input_index: usize, + txout_index: TxOutIndex, +} + +#[derive(Default)] +struct ReadBatch { + parents: Vec, + parent_positions: Vec, + outputs: Vec, + output_positions: Vec, + output_types: Vec, + type_indices: Vec, +} + +impl ReadBatch { + fn resolve( + &mut self, + processor: &BlockProcessor<'_>, + previous_parents: &[PreviousParent], + inputs: &[UnresolvedInput], + current_tx_index: TxIndex, + ) -> Result<()> { + self.resolve_parents(processor, previous_parents, current_tx_index)?; + self.prepare_outputs(inputs); + self.read_outputs(processor) + } + + fn resolve_parents( + &mut self, + processor: &BlockProcessor<'_>, + previous_parents: &[PreviousParent], + current_tx_index: TxIndex, + ) -> Result<()> { + self.parents.clear(); + self.parents.extend( + (0..previous_parents.len()).map(|original_index| ParentRead { + original_index, + tx_index: TxIndex::default(), + first_txout_index: TxOutIndex::default(), + }), + ); + + self.parents + .par_iter_mut() + .try_for_each(|read| { + let parent = &previous_parents[read.original_index]; + let store_result = processor + .stores + .txid_prefix_to_tx_index + .get(&parent.txid_prefix)? + .map(|value| *value); + + let tx_index = match store_result { + Some(tx_index) if tx_index < current_tx_index => tx_index, + _ => { + error!( + "UnknownTxid: txid={}, prefix={:?}, store_result={:?}, current_tx_index={:?}", + parent.txid, + parent.txid_prefix, + store_result, + current_tx_index + ); + return Err(Error::UnknownTxid); + } + }; + + read.tx_index = tx_index; + Ok(()) + })?; + + self.parents.sort_unstable_by_key(|read| read.tx_index); + self.parent_positions.clear(); + self.parent_positions.resize(self.parents.len(), 0); + + for (position, read) in self.parents.iter_mut().enumerate() { + self.parent_positions[read.original_index] = position; + read.first_txout_index = processor + .vecs + .transactions + .first_txout_index + .get_pushed_or_read( + read.tx_index, + &processor.readers.tx_index_to_first_txout_index, + ) + .ok_or(Error::Internal("Missing txout_index"))?; + } + + Ok(()) + } + + fn prepare_outputs(&mut self, inputs: &[UnresolvedInput]) { + self.outputs.clear(); + self.outputs.reserve(inputs.len()); + + for (input_index, input) in inputs.iter().enumerate() { + if let UnresolvedInput::PreviousBlock { parent_index, vout } = *input { + let parent = self.parent(parent_index); + self.outputs.push(OutputRead { + input_index, + txout_index: parent.first_txout_index + vout, + }); + } + } + + self.outputs.sort_unstable_by_key(|read| read.txout_index); + self.output_positions.clear(); + self.output_positions.resize(inputs.len(), 0); + + for (position, read) in self.outputs.iter().enumerate() { + self.output_positions[read.input_index] = position; + } + } + + fn read_outputs(&mut self, processor: &BlockProcessor<'_>) -> Result<()> { + self.output_types.clear(); + self.output_types.reserve(self.outputs.len()); + self.type_indices.clear(); + self.type_indices.reserve(self.outputs.len()); + + let outputs = &self.outputs; + let output_types = &mut self.output_types; + let type_indices = &mut self.type_indices; + + let (output_types_result, type_indices_result) = rayon::join( + || -> Result<()> { + for read in outputs { + output_types.push( + processor + .vecs + .outputs + .output_type + .get_pushed_or_read( + read.txout_index, + &processor.readers.txout_index_to_output_type, + ) + .ok_or(Error::Internal("Missing output_type"))?, + ); + } + Ok(()) + }, + || -> Result<()> { + for read in outputs { + type_indices.push( + processor + .vecs + .outputs + .type_index + .get_pushed_or_read( + read.txout_index, + &processor.readers.txout_index_to_type_index, + ) + .ok_or(Error::Internal("Missing type_index"))?, + ); + } + Ok(()) + }, + ); + + output_types_result?; + type_indices_result + } + + fn parent(&self, original_index: usize) -> ParentRead { + self.parents[self.parent_positions[original_index]] + } + + fn output(&self, input_index: usize) -> (OutputType, TypeIndex) { + let position = self.output_positions[input_index]; + (self.output_types[position], self.type_indices[position]) + } +} + #[derive(Clone, Copy)] enum UnresolvedInput { Coinbase, diff --git a/crates/brk_indexer/src/processor/txout/address.rs b/crates/brk_indexer/src/processor/txout/address.rs index c613fb7ad..fd4a5115d 100644 --- a/crates/brk_indexer/src/processor/txout/address.rs +++ b/crates/brk_indexer/src/processor/txout/address.rs @@ -68,6 +68,9 @@ impl BlockAddresses { } } + self.lookups + .sort_unstable_by_key(|lookup| (lookup.output_type, lookup.hash)); + let stores = &processor.stores.addr_type_to_addr_hash_to_addr_index; let lengths = &*processor.lengths; diff --git a/crates/brk_indexer/src/processor/txout/address/cache.rs b/crates/brk_indexer/src/processor/txout/address/cache.rs index 83dfc9600..a3dd024fc 100644 --- a/crates/brk_indexer/src/processor/txout/address/cache.rs +++ b/crates/brk_indexer/src/processor/txout/address/cache.rs @@ -3,7 +3,7 @@ use std::mem; use brk_types::{AddrHash, OutputType, TypeIndex}; const ASSOCIATIVITY: usize = 4; -const SET_COUNT: usize = 1 << 18; +const SET_COUNT: usize = 1 << 19; const SET_MASK: usize = SET_COUNT - 1; const TYPE_MIX: u64 = 0x9e37_79b9_7f4a_7c15; const REFERENCE_SHIFT: usize = 2; diff --git a/modules/brk-client/index.js b/modules/brk-client/index.js index 5a78938a6..d9e684447 100644 --- a/modules/brk-client/index.js +++ b/modules/brk-client/index.js @@ -822,6 +822,7 @@ ancestors and no descendants (matches mempool.space). * @property {Close} close */ /** @typedef {TypeIndex} OpReturnIndex */ +/** @typedef {("runes"|"veri_block"|"omni"|"stacks"|"blockstack"|"colu"|"open_assets"|"komodo"|"coin_spark"|"poet"|"docproof"|"open_timestamps"|"factom"|"eternity_wall"|"memo"|"bitproof"|"ascribe"|"stampery"|"epobc"|"bare_hash"|"text"|"empty"|"unknown")} OpReturnKind */ /** * Opening price value for a time period * @@ -3297,13 +3298,13 @@ function createInMaxMinPerSupplyPattern(client, acc) { /** * @typedef {Object} MaxMedianMinPct10Pct25Pct75Pct90Pattern2 - * @property {SeriesPattern18} max - * @property {SeriesPattern18} median - * @property {SeriesPattern18} min - * @property {SeriesPattern18} pct10 - * @property {SeriesPattern18} pct25 - * @property {SeriesPattern18} pct75 - * @property {SeriesPattern18} pct90 + * @property {SeriesPattern18} max + * @property {SeriesPattern18} median + * @property {SeriesPattern18} min + * @property {SeriesPattern18} pct10 + * @property {SeriesPattern18} pct25 + * @property {SeriesPattern18} pct75 + * @property {SeriesPattern18} pct90 */ /** @@ -4231,6 +4232,29 @@ function createBtcCentsSatsUsdPattern3(client, acc) { }; } +/** + * @typedef {Object} CarrierOutputPostPattern + * @property {AverageBlockCumulativeSumPattern} carrierTxCount + * @property {AverageBlockCumulativeSumPattern} carrierVsize + * @property {AverageBlockCumulativeSumPattern} outputCount + * @property {AverageBlockCumulativeSumPattern} postOpReturnBytes + */ + +/** + * Create a CarrierOutputPostPattern pattern node + * @param {BrkClient} client + * @param {string} acc - Accumulated series name + * @returns {CarrierOutputPostPattern} + */ +function createCarrierOutputPostPattern(client, acc) { + return { + carrierTxCount: createAverageBlockCumulativeSumPattern(client, _m(acc, 'carrier_tx_count')), + carrierVsize: createAverageBlockCumulativeSumPattern(client, _m(acc, 'carrier_vsize')), + outputCount: createAverageBlockCumulativeSumPattern(client, _m(acc, 'output_count')), + postOpReturnBytes: createAverageBlockCumulativeSumPattern(client, _m(acc, 'post_op_return_bytes')), + }; +} + /** * @typedef {Object} CentsDeltaToUsdPattern * @property {SeriesPattern1} cents @@ -5424,6 +5448,7 @@ function createTransferPattern(client, acc) { * @property {SeriesTree_Outputs} outputs * @property {SeriesTree_Addrs} addrs * @property {SeriesTree_Scripts} scripts + * @property {SeriesTree_OpReturn} opReturn * @property {SeriesTree_Mining} mining * @property {SeriesTree_Cointime} cointime * @property {SeriesTree_Constants} constants @@ -5565,9 +5590,12 @@ function createTransferPattern(client, acc) { /** * @typedef {Object} SeriesTree_Transactions * @property {SeriesTree_Transactions_Raw} raw + * @property {SeriesTree_Transactions_Features} features * @property {SeriesTree_Transactions_Count} count * @property {SeriesTree_Transactions_Size} size * @property {SeriesTree_Transactions_Fees} fees + * @property {SeriesTree_Transactions_Patterns} patterns + * @property {SeriesTree_Transactions_Policy} policy * @property {SeriesTree_Transactions_Versions} versions * @property {SeriesTree_Transactions_Volume} volume */ @@ -5578,7 +5606,7 @@ function createTransferPattern(client, acc) { * @property {SeriesPattern19} txid * @property {SeriesPattern19} txVersion * @property {SeriesPattern19} rawLocktime - * @property {SeriesPattern19} baseSize + * @property {SeriesPattern19} weight * @property {SeriesPattern19} totalSize * @property {SeriesPattern19} totalSigopCost * @property {SeriesPattern19} isExplicitlyRbf @@ -5586,6 +5614,64 @@ function createTransferPattern(client, acc) { * @property {SeriesPattern19} firstTxoutIndex */ +/** + * @typedef {Object} SeriesTree_Transactions_Features + * @property {SeriesTree_Transactions_Features_Count} count + * @property {SeriesPattern19} hasP2pk + * @property {SeriesPattern19} hasP2ms + * @property {SeriesPattern19} hasP2pkh + * @property {SeriesPattern19} hasP2sh + * @property {SeriesPattern19} hasP2wpkh + * @property {SeriesPattern19} hasP2wsh + * @property {SeriesPattern19} hasP2tr + * @property {SeriesPattern19} hasP2a + * @property {SeriesPattern19} hasOpReturn + * @property {SeriesPattern19} hasEmpty + * @property {SeriesPattern19} hasUnknown + * @property {SeriesPattern19} hasFakePubkey + * @property {SeriesPattern19} hasFakeScripthash + * @property {SeriesPattern19} hasInscription + * @property {SeriesPattern19} hasAnnex + * @property {SeriesPattern19} hasSighashAll + * @property {SeriesPattern19} hasSighashNone + * @property {SeriesPattern19} hasSighashSingle + * @property {SeriesPattern19} hasSighashDefault + * @property {SeriesPattern19} hasSighashAnyoneCanPay + * @property {SeriesPattern19} hasDustOutput + */ + +/** + * @typedef {Object} SeriesTree_Transactions_Features_Count + * @property {SeriesPattern18} v1 + * @property {SeriesPattern18} v2 + * @property {SeriesPattern18} v3 + * @property {SeriesPattern18} otherVersion + * @property {SeriesPattern18} explicitlyRbf + * @property {SeriesPattern18} oneInput + * @property {SeriesPattern18} oneOutput + * @property {SeriesPattern18} p2pk + * @property {SeriesPattern18} p2ms + * @property {SeriesPattern18} p2pkh + * @property {SeriesPattern18} p2sh + * @property {SeriesPattern18} p2wpkh + * @property {SeriesPattern18} p2wsh + * @property {SeriesPattern18} p2tr + * @property {SeriesPattern18} p2a + * @property {SeriesPattern18} opReturn + * @property {SeriesPattern18} empty + * @property {SeriesPattern18} unknown + * @property {SeriesPattern18} fakePubkey + * @property {SeriesPattern18} fakeScripthash + * @property {SeriesPattern18} inscription + * @property {SeriesPattern18} annex + * @property {SeriesPattern18} sighashAll + * @property {SeriesPattern18} sighashNone + * @property {SeriesPattern18} sighashSingle + * @property {SeriesPattern18} sighashDefault + * @property {SeriesPattern18} sighashAnyoneCanPay + * @property {SeriesPattern18} dustOutput + */ + /** * @typedef {Object} SeriesTree_Transactions_Count * @property {AverageBlockCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern} total @@ -5593,24 +5679,60 @@ function createTransferPattern(client, acc) { /** * @typedef {Object} SeriesTree_Transactions_Size - * @property {_6bBlockTxPattern} vsize + * @property {SeriesTree_Transactions_Size_Vsize} vsize * @property {SeriesTree_Transactions_Size_Weight} weight */ /** - * @typedef {Object} SeriesTree_Transactions_Size_Weight - * @property {SeriesPattern19} txIndex + * @typedef {Object} SeriesTree_Transactions_Size_Vsize + * @property {SeriesPattern19} txIndex * @property {MaxMedianMinPct10Pct25Pct75Pct90Pattern2} block * @property {MaxMedianMinPct10Pct25Pct75Pct90Pattern2} _6b */ +/** + * @typedef {Object} SeriesTree_Transactions_Size_Weight + * @property {MaxMedianMinPct10Pct25Pct75Pct90Pattern} block + * @property {MaxMedianMinPct10Pct25Pct75Pct90Pattern} _6b + */ + /** * @typedef {Object} SeriesTree_Transactions_Fees + * @property {SeriesTree_Transactions_Fees_Count} count * @property {SeriesPattern19} inputValue * @property {SeriesPattern19} outputValue * @property {_6bBlockTxPattern} fee * @property {SeriesPattern19} feeRate * @property {_6bBlockTxPattern} effectiveFeeRate + * @property {SeriesPattern19} isCpfpParent + * @property {SeriesPattern19} isCpfpChild + */ + +/** + * @typedef {Object} SeriesTree_Transactions_Fees_Count + * @property {SeriesPattern18} cpfpParent + * @property {SeriesPattern18} cpfpChild + */ + +/** + * @typedef {Object} SeriesTree_Transactions_Patterns + * @property {SeriesTree_Transactions_Patterns_Count} count + * @property {SeriesPattern19} isCoinjoin + * @property {SeriesPattern19} isConsolidation + * @property {SeriesPattern19} isBatchPayout + */ + +/** + * @typedef {Object} SeriesTree_Transactions_Patterns_Count + * @property {SeriesPattern18} coinjoin + * @property {SeriesPattern18} consolidation + * @property {SeriesPattern18} batchPayout + */ + +/** + * @typedef {Object} SeriesTree_Transactions_Policy + * @property {SeriesPattern18} count + * @property {SeriesPattern19} isNonstandard */ /** @@ -5618,6 +5740,7 @@ function createTransferPattern(client, acc) { * @property {AverageBlockCumulativeSumPattern} v1 * @property {AverageBlockCumulativeSumPattern} v2 * @property {AverageBlockCumulativeSumPattern} v3 + * @property {AverageBlockCumulativeSumPattern} other */ /** @@ -6024,7 +6147,6 @@ function createTransferPattern(client, acc) { /** * @typedef {Object} SeriesTree_Scripts_Raw * @property {SeriesTree_Scripts_Raw_Empty} empty - * @property {SeriesTree_Scripts_Raw_OpReturn} opReturn * @property {SeriesTree_Scripts_Raw_P2ms} p2ms * @property {SeriesTree_Scripts_Raw_Unknown} unknown */ @@ -6035,22 +6157,76 @@ function createTransferPattern(client, acc) { * @property {SeriesPattern22} toTxIndex */ -/** - * @typedef {Object} SeriesTree_Scripts_Raw_OpReturn - * @property {SeriesPattern18} firstIndex - * @property {SeriesPattern23} toTxIndex - */ - /** * @typedef {Object} SeriesTree_Scripts_Raw_P2ms * @property {SeriesPattern18} firstIndex * @property {SeriesPattern25} toTxIndex + * @property {SeriesPattern25} legacySigops */ /** * @typedef {Object} SeriesTree_Scripts_Raw_Unknown * @property {SeriesPattern18} firstIndex * @property {SeriesPattern33} toTxIndex + * @property {SeriesPattern33} legacySigops + */ + +/** + * @typedef {Object} SeriesTree_OpReturn + * @property {SeriesTree_OpReturn_Raw} raw + * @property {SeriesTree_OpReturn_Total} total + * @property {SeriesTree_OpReturn_ByKind} byKind + * @property {SeriesTree_OpReturn_Policy} policy + */ + +/** + * @typedef {Object} SeriesTree_OpReturn_Raw + * @property {SeriesPattern18} firstIndex + * @property {SeriesPattern23} toTxIndex + * @property {SeriesPattern23} kind + * @property {SeriesPattern23} postOpReturnBytes + */ + +/** + * @typedef {Object} SeriesTree_OpReturn_Total + * @property {AverageBlockCumulativeSumPattern} postOpReturnBytes + * @property {AverageBlockCumulativeSumPattern} carrierTxCount + * @property {AverageBlockCumulativeSumPattern} carrierVsize + */ + +/** + * @typedef {Object} SeriesTree_OpReturn_ByKind + * @property {CarrierOutputPostPattern} runes + * @property {CarrierOutputPostPattern} veriBlock + * @property {CarrierOutputPostPattern} omni + * @property {CarrierOutputPostPattern} stacks + * @property {CarrierOutputPostPattern} blockstack + * @property {CarrierOutputPostPattern} colu + * @property {CarrierOutputPostPattern} openAssets + * @property {CarrierOutputPostPattern} komodo + * @property {CarrierOutputPostPattern} coinSpark + * @property {CarrierOutputPostPattern} poet + * @property {CarrierOutputPostPattern} docproof + * @property {CarrierOutputPostPattern} openTimestamps + * @property {CarrierOutputPostPattern} factom + * @property {CarrierOutputPostPattern} eternityWall + * @property {CarrierOutputPostPattern} memo + * @property {CarrierOutputPostPattern} bitproof + * @property {CarrierOutputPostPattern} ascribe + * @property {CarrierOutputPostPattern} stampery + * @property {CarrierOutputPostPattern} epobc + * @property {CarrierOutputPostPattern} bareHash + * @property {CarrierOutputPostPattern} text + * @property {CarrierOutputPostPattern} empty + * @property {CarrierOutputPostPattern} unknown + */ + +/** + * @typedef {Object} SeriesTree_OpReturn_Policy + * @property {CarrierOutputPostPattern} standard + * @property {CarrierOutputPostPattern} oversized + * @property {CarrierOutputPostPattern} multiple + * @property {CarrierOutputPostPattern} preV30Nonstandard */ /** @@ -9398,35 +9574,112 @@ class BrkClient extends BrkClientBase { txid: createSeriesPattern19(this, 'txid'), txVersion: createSeriesPattern19(this, 'tx_version'), rawLocktime: createSeriesPattern19(this, 'raw_locktime'), - baseSize: createSeriesPattern19(this, 'base_size'), + weight: createSeriesPattern19(this, 'tx_weight'), totalSize: createSeriesPattern19(this, 'total_size'), totalSigopCost: createSeriesPattern19(this, 'total_sigop_cost'), isExplicitlyRbf: createSeriesPattern19(this, 'is_explicitly_rbf'), firstTxinIndex: createSeriesPattern19(this, 'first_txin_index'), firstTxoutIndex: createSeriesPattern19(this, 'first_txout_index'), }, + features: { + count: { + v1: createSeriesPattern18(this, 'tx_count_v1'), + v2: createSeriesPattern18(this, 'tx_count_v2'), + v3: createSeriesPattern18(this, 'tx_count_v3'), + otherVersion: createSeriesPattern18(this, 'tx_count_other_version'), + explicitlyRbf: createSeriesPattern18(this, 'tx_count_explicitly_rbf'), + oneInput: createSeriesPattern18(this, 'tx_count_one_input'), + oneOutput: createSeriesPattern18(this, 'tx_count_one_output'), + p2pk: createSeriesPattern18(this, 'tx_count_p2pk'), + p2ms: createSeriesPattern18(this, 'tx_count_p2ms'), + p2pkh: createSeriesPattern18(this, 'tx_count_p2pkh'), + p2sh: createSeriesPattern18(this, 'tx_count_p2sh'), + p2wpkh: createSeriesPattern18(this, 'tx_count_p2wpkh'), + p2wsh: createSeriesPattern18(this, 'tx_count_p2wsh'), + p2tr: createSeriesPattern18(this, 'tx_count_p2tr'), + p2a: createSeriesPattern18(this, 'tx_count_p2a'), + opReturn: createSeriesPattern18(this, 'tx_count_op_return'), + empty: createSeriesPattern18(this, 'tx_count_empty'), + unknown: createSeriesPattern18(this, 'tx_count_unknown'), + fakePubkey: createSeriesPattern18(this, 'tx_count_fake_pubkey'), + fakeScripthash: createSeriesPattern18(this, 'tx_count_fake_scripthash'), + inscription: createSeriesPattern18(this, 'tx_count_inscription'), + annex: createSeriesPattern18(this, 'tx_count_annex'), + sighashAll: createSeriesPattern18(this, 'tx_count_sighash_all'), + sighashNone: createSeriesPattern18(this, 'tx_count_sighash_none'), + sighashSingle: createSeriesPattern18(this, 'tx_count_sighash_single'), + sighashDefault: createSeriesPattern18(this, 'tx_count_sighash_default'), + sighashAnyoneCanPay: createSeriesPattern18(this, 'tx_count_sighash_anyone_can_pay'), + dustOutput: createSeriesPattern18(this, 'tx_count_dust_output'), + }, + hasP2pk: createSeriesPattern19(this, 'has_p2pk'), + hasP2ms: createSeriesPattern19(this, 'has_p2ms'), + hasP2pkh: createSeriesPattern19(this, 'has_p2pkh'), + hasP2sh: createSeriesPattern19(this, 'has_p2sh'), + hasP2wpkh: createSeriesPattern19(this, 'has_p2wpkh'), + hasP2wsh: createSeriesPattern19(this, 'has_p2wsh'), + hasP2tr: createSeriesPattern19(this, 'has_p2tr'), + hasP2a: createSeriesPattern19(this, 'has_p2a'), + hasOpReturn: createSeriesPattern19(this, 'has_op_return'), + hasEmpty: createSeriesPattern19(this, 'has_empty'), + hasUnknown: createSeriesPattern19(this, 'has_unknown'), + hasFakePubkey: createSeriesPattern19(this, 'has_fake_pubkey'), + hasFakeScripthash: createSeriesPattern19(this, 'has_fake_scripthash'), + hasInscription: createSeriesPattern19(this, 'has_inscription'), + hasAnnex: createSeriesPattern19(this, 'has_annex'), + hasSighashAll: createSeriesPattern19(this, 'has_sighash_all'), + hasSighashNone: createSeriesPattern19(this, 'has_sighash_none'), + hasSighashSingle: createSeriesPattern19(this, 'has_sighash_single'), + hasSighashDefault: createSeriesPattern19(this, 'has_sighash_default'), + hasSighashAnyoneCanPay: createSeriesPattern19(this, 'has_sighash_anyone_can_pay'), + hasDustOutput: createSeriesPattern19(this, 'has_dust_output'), + }, count: { total: createAverageBlockCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern(this, 'tx_count'), }, size: { - vsize: create_6bBlockTxPattern(this, 'tx_vsize'), + vsize: { + txIndex: createSeriesPattern19(this, 'tx_vsize'), + block: createMaxMedianMinPct10Pct25Pct75Pct90Pattern2(this, 'tx_vsize'), + _6b: createMaxMedianMinPct10Pct25Pct75Pct90Pattern2(this, 'tx_vsize_6b'), + }, weight: { - txIndex: createSeriesPattern19(this, 'tx_weight'), - block: createMaxMedianMinPct10Pct25Pct75Pct90Pattern2(this, 'tx_weight'), - _6b: createMaxMedianMinPct10Pct25Pct75Pct90Pattern2(this, 'tx_weight_6b'), + block: createMaxMedianMinPct10Pct25Pct75Pct90Pattern(this, 'tx_weight'), + _6b: createMaxMedianMinPct10Pct25Pct75Pct90Pattern(this, 'tx_weight_6b'), }, }, fees: { + count: { + cpfpParent: createSeriesPattern18(this, 'cpfp_parent_count'), + cpfpChild: createSeriesPattern18(this, 'cpfp_child_count'), + }, inputValue: createSeriesPattern19(this, 'input_value'), outputValue: createSeriesPattern19(this, 'output_value'), fee: create_6bBlockTxPattern(this, 'fee'), feeRate: createSeriesPattern19(this, 'fee_rate'), effectiveFeeRate: create_6bBlockTxPattern(this, 'effective_fee_rate'), + isCpfpParent: createSeriesPattern19(this, 'is_cpfp_parent'), + isCpfpChild: createSeriesPattern19(this, 'is_cpfp_child'), + }, + patterns: { + count: { + coinjoin: createSeriesPattern18(this, 'coinjoin_count'), + consolidation: createSeriesPattern18(this, 'consolidation_count'), + batchPayout: createSeriesPattern18(this, 'batch_payout_count'), + }, + isCoinjoin: createSeriesPattern19(this, 'is_coinjoin'), + isConsolidation: createSeriesPattern19(this, 'is_consolidation'), + isBatchPayout: createSeriesPattern19(this, 'is_batch_payout'), + }, + policy: { + count: createSeriesPattern18(this, 'nonstandard_count'), + isNonstandard: createSeriesPattern19(this, 'is_nonstandard'), }, versions: { v1: createAverageBlockCumulativeSumPattern(this, 'tx_v1'), v2: createAverageBlockCumulativeSumPattern(this, 'tx_v2'), v3: createAverageBlockCumulativeSumPattern(this, 'tx_v3'), + other: createAverageBlockCumulativeSumPattern(this, 'tx_other_version'), }, volume: { transferVolume: createAverageBlockCumulativeSumPattern3(this, 'transfer_volume_bis'), @@ -9712,20 +9965,62 @@ class BrkClient extends BrkClientBase { firstIndex: createSeriesPattern18(this, 'first_empty_output_index'), toTxIndex: createSeriesPattern22(this, 'tx_index'), }, - opReturn: { - firstIndex: createSeriesPattern18(this, 'first_op_return_index'), - toTxIndex: createSeriesPattern23(this, 'tx_index'), - }, p2ms: { firstIndex: createSeriesPattern18(this, 'first_p2ms_output_index'), toTxIndex: createSeriesPattern25(this, 'tx_index'), + legacySigops: createSeriesPattern25(this, 'p2ms_legacy_sigops'), }, unknown: { firstIndex: createSeriesPattern18(this, 'first_unknown_output_index'), toTxIndex: createSeriesPattern33(this, 'tx_index'), + legacySigops: createSeriesPattern33(this, 'unknown_legacy_sigops'), }, }, }, + opReturn: { + raw: { + firstIndex: createSeriesPattern18(this, 'first_op_return_index'), + toTxIndex: createSeriesPattern23(this, 'tx_index'), + kind: createSeriesPattern23(this, 'kind'), + postOpReturnBytes: createSeriesPattern23(this, 'op_return_post_op_return_bytes'), + }, + total: { + postOpReturnBytes: createAverageBlockCumulativeSumPattern(this, 'op_return_post_op_return_bytes'), + carrierTxCount: createAverageBlockCumulativeSumPattern(this, 'op_return_carrier_tx_count'), + carrierVsize: createAverageBlockCumulativeSumPattern(this, 'op_return_carrier_vsize'), + }, + byKind: { + runes: createCarrierOutputPostPattern(this, 'op_return_runes'), + veriBlock: createCarrierOutputPostPattern(this, 'op_return_veri_block'), + omni: createCarrierOutputPostPattern(this, 'op_return_omni'), + stacks: createCarrierOutputPostPattern(this, 'op_return_stacks'), + blockstack: createCarrierOutputPostPattern(this, 'op_return_blockstack'), + colu: createCarrierOutputPostPattern(this, 'op_return_colu'), + openAssets: createCarrierOutputPostPattern(this, 'op_return_open_assets'), + komodo: createCarrierOutputPostPattern(this, 'op_return_komodo'), + coinSpark: createCarrierOutputPostPattern(this, 'op_return_coin_spark'), + poet: createCarrierOutputPostPattern(this, 'op_return_poet'), + docproof: createCarrierOutputPostPattern(this, 'op_return_docproof'), + openTimestamps: createCarrierOutputPostPattern(this, 'op_return_open_timestamps'), + factom: createCarrierOutputPostPattern(this, 'op_return_factom'), + eternityWall: createCarrierOutputPostPattern(this, 'op_return_eternity_wall'), + memo: createCarrierOutputPostPattern(this, 'op_return_memo'), + bitproof: createCarrierOutputPostPattern(this, 'op_return_bitproof'), + ascribe: createCarrierOutputPostPattern(this, 'op_return_ascribe'), + stampery: createCarrierOutputPostPattern(this, 'op_return_stampery'), + epobc: createCarrierOutputPostPattern(this, 'op_return_epobc'), + bareHash: createCarrierOutputPostPattern(this, 'op_return_bare_hash'), + text: createCarrierOutputPostPattern(this, 'op_return_text'), + empty: createCarrierOutputPostPattern(this, 'op_return_empty'), + unknown: createCarrierOutputPostPattern(this, 'op_return_unknown'), + }, + policy: { + standard: createCarrierOutputPostPattern(this, 'op_return_policy_standard'), + oversized: createCarrierOutputPostPattern(this, 'op_return_policy_oversized'), + multiple: createCarrierOutputPostPattern(this, 'op_return_policy_multiple'), + preV30Nonstandard: createCarrierOutputPostPattern(this, 'op_return_policy_pre_v30_nonstandard'), + }, + }, mining: { rewards: { coinbase: createAverageBlockCumulativeSumPattern3(this, 'coinbase'), diff --git a/packages/brk_client/brk_client/__init__.py b/packages/brk_client/brk_client/__init__.py index 1d6e0bd67..2b630e05e 100644 --- a/packages/brk_client/brk_client/__init__.py +++ b/packages/brk_client/brk_client/__init__.py @@ -192,6 +192,7 @@ Month6 = int # Opening price value for a time period Open = Dollars OpReturnIndex = TypeIndex +OpReturnKind = Literal["runes", "veri_block", "omni", "stacks", "blockstack", "colu", "open_assets", "komodo", "coin_spark", "poet", "docproof", "open_timestamps", "factom", "eternity_wall", "memo", "bitproof", "ascribe", "stampery", "epobc", "bare_hash", "text", "empty", "unknown"] OutPoint = int P2AAddrIndex = TypeIndex U8x2 = List[int] @@ -3350,13 +3351,13 @@ class MaxMedianMinPct10Pct25Pct75Pct90Pattern2: def __init__(self, client: BrkClient, acc: str): """Create pattern node with accumulated series name.""" - self.max: SeriesPattern18[Weight] = SeriesPattern18(client, _m(acc, 'max')) - self.median: SeriesPattern18[Weight] = SeriesPattern18(client, _m(acc, 'median')) - self.min: SeriesPattern18[Weight] = SeriesPattern18(client, _m(acc, 'min')) - self.pct10: SeriesPattern18[Weight] = SeriesPattern18(client, _m(acc, 'pct10')) - self.pct25: SeriesPattern18[Weight] = SeriesPattern18(client, _m(acc, 'pct25')) - self.pct75: SeriesPattern18[Weight] = SeriesPattern18(client, _m(acc, 'pct75')) - self.pct90: SeriesPattern18[Weight] = SeriesPattern18(client, _m(acc, 'pct90')) + self.max: SeriesPattern18[VSize] = SeriesPattern18(client, _m(acc, 'max')) + self.median: SeriesPattern18[VSize] = SeriesPattern18(client, _m(acc, 'median')) + self.min: SeriesPattern18[VSize] = SeriesPattern18(client, _m(acc, 'min')) + self.pct10: SeriesPattern18[VSize] = SeriesPattern18(client, _m(acc, 'pct10')) + self.pct25: SeriesPattern18[VSize] = SeriesPattern18(client, _m(acc, 'pct25')) + self.pct75: SeriesPattern18[VSize] = SeriesPattern18(client, _m(acc, 'pct75')) + self.pct90: SeriesPattern18[VSize] = SeriesPattern18(client, _m(acc, 'pct90')) class MaxMedianMinPct10Pct25Pct75Pct90Pattern(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -3756,6 +3757,16 @@ class BtcCentsSatsUsdPattern3: self.sats: SeriesPattern18[Sats] = SeriesPattern18(client, _m(acc, 'sats')) self.usd: SeriesPattern18[Dollars] = SeriesPattern18(client, _m(acc, 'usd')) +class CarrierOutputPostPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClient, acc: str): + """Create pattern node with accumulated series name.""" + self.carrier_tx_count: AverageBlockCumulativeSumPattern[StoredU64] = AverageBlockCumulativeSumPattern(client, _m(acc, 'carrier_tx_count')) + self.carrier_vsize: AverageBlockCumulativeSumPattern[VSize] = AverageBlockCumulativeSumPattern(client, _m(acc, 'carrier_vsize')) + self.output_count: AverageBlockCumulativeSumPattern[StoredU64] = AverageBlockCumulativeSumPattern(client, _m(acc, 'output_count')) + self.post_op_return_bytes: AverageBlockCumulativeSumPattern[StoredU64] = AverageBlockCumulativeSumPattern(client, _m(acc, 'post_op_return_bytes')) + class CentsDeltaToUsdPattern: """Pattern struct for repeated tree structure.""" @@ -4401,43 +4412,144 @@ class SeriesTree_Transactions_Raw: self.txid: SeriesPattern19[Txid] = SeriesPattern19(client, 'txid') self.tx_version: SeriesPattern19[TxVersion] = SeriesPattern19(client, 'tx_version') self.raw_locktime: SeriesPattern19[RawLockTime] = SeriesPattern19(client, 'raw_locktime') - self.base_size: SeriesPattern19[StoredU32] = SeriesPattern19(client, 'base_size') + self.weight: SeriesPattern19[Weight] = SeriesPattern19(client, 'tx_weight') self.total_size: SeriesPattern19[StoredU32] = SeriesPattern19(client, 'total_size') self.total_sigop_cost: SeriesPattern19[SigOps] = SeriesPattern19(client, 'total_sigop_cost') self.is_explicitly_rbf: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'is_explicitly_rbf') self.first_txin_index: SeriesPattern19[TxInIndex] = SeriesPattern19(client, 'first_txin_index') self.first_txout_index: SeriesPattern19[TxOutIndex] = SeriesPattern19(client, 'first_txout_index') +class SeriesTree_Transactions_Features_Count: + """Series tree node.""" + + def __init__(self, client: BrkClient, base_path: str = ''): + self.v1: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_v1') + self.v2: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_v2') + self.v3: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_v3') + self.other_version: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_other_version') + self.explicitly_rbf: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_explicitly_rbf') + self.one_input: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_one_input') + self.one_output: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_one_output') + self.p2pk: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_p2pk') + self.p2ms: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_p2ms') + self.p2pkh: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_p2pkh') + self.p2sh: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_p2sh') + self.p2wpkh: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_p2wpkh') + self.p2wsh: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_p2wsh') + self.p2tr: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_p2tr') + self.p2a: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_p2a') + self.op_return: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_op_return') + self.empty: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_empty') + self.unknown: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_unknown') + self.fake_pubkey: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_fake_pubkey') + self.fake_scripthash: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_fake_scripthash') + self.inscription: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_inscription') + self.annex: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_annex') + self.sighash_all: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_sighash_all') + self.sighash_none: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_sighash_none') + self.sighash_single: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_sighash_single') + self.sighash_default: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_sighash_default') + self.sighash_anyone_can_pay: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_sighash_anyone_can_pay') + self.dust_output: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'tx_count_dust_output') + +class SeriesTree_Transactions_Features: + """Series tree node.""" + + def __init__(self, client: BrkClient, base_path: str = ''): + self.count: SeriesTree_Transactions_Features_Count = SeriesTree_Transactions_Features_Count(client) + self.has_p2pk: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_p2pk') + self.has_p2ms: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_p2ms') + self.has_p2pkh: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_p2pkh') + self.has_p2sh: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_p2sh') + self.has_p2wpkh: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_p2wpkh') + self.has_p2wsh: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_p2wsh') + self.has_p2tr: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_p2tr') + self.has_p2a: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_p2a') + self.has_op_return: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_op_return') + self.has_empty: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_empty') + self.has_unknown: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_unknown') + self.has_fake_pubkey: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_fake_pubkey') + self.has_fake_scripthash: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_fake_scripthash') + self.has_inscription: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_inscription') + self.has_annex: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_annex') + self.has_sighash_all: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_sighash_all') + self.has_sighash_none: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_sighash_none') + self.has_sighash_single: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_sighash_single') + self.has_sighash_default: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_sighash_default') + self.has_sighash_anyone_can_pay: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_sighash_anyone_can_pay') + self.has_dust_output: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'has_dust_output') + class SeriesTree_Transactions_Count: """Series tree node.""" def __init__(self, client: BrkClient, base_path: str = ''): self.total: AverageBlockCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern = AverageBlockCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern(client, 'tx_count') +class SeriesTree_Transactions_Size_Vsize: + """Series tree node.""" + + def __init__(self, client: BrkClient, base_path: str = ''): + self.tx_index: SeriesPattern19[VSize] = SeriesPattern19(client, 'tx_vsize') + self.block: MaxMedianMinPct10Pct25Pct75Pct90Pattern2 = MaxMedianMinPct10Pct25Pct75Pct90Pattern2(client, 'tx_vsize') + self._6b: MaxMedianMinPct10Pct25Pct75Pct90Pattern2 = MaxMedianMinPct10Pct25Pct75Pct90Pattern2(client, 'tx_vsize_6b') + class SeriesTree_Transactions_Size_Weight: """Series tree node.""" def __init__(self, client: BrkClient, base_path: str = ''): - self.tx_index: SeriesPattern19[Weight] = SeriesPattern19(client, 'tx_weight') - self.block: MaxMedianMinPct10Pct25Pct75Pct90Pattern2 = MaxMedianMinPct10Pct25Pct75Pct90Pattern2(client, 'tx_weight') - self._6b: MaxMedianMinPct10Pct25Pct75Pct90Pattern2 = MaxMedianMinPct10Pct25Pct75Pct90Pattern2(client, 'tx_weight_6b') + self.block: MaxMedianMinPct10Pct25Pct75Pct90Pattern[Weight] = MaxMedianMinPct10Pct25Pct75Pct90Pattern(client, 'tx_weight') + self._6b: MaxMedianMinPct10Pct25Pct75Pct90Pattern[Weight] = MaxMedianMinPct10Pct25Pct75Pct90Pattern(client, 'tx_weight_6b') class SeriesTree_Transactions_Size: """Series tree node.""" def __init__(self, client: BrkClient, base_path: str = ''): - self.vsize: _6bBlockTxPattern[VSize] = _6bBlockTxPattern(client, 'tx_vsize') + self.vsize: SeriesTree_Transactions_Size_Vsize = SeriesTree_Transactions_Size_Vsize(client) self.weight: SeriesTree_Transactions_Size_Weight = SeriesTree_Transactions_Size_Weight(client) +class SeriesTree_Transactions_Fees_Count: + """Series tree node.""" + + def __init__(self, client: BrkClient, base_path: str = ''): + self.cpfp_parent: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'cpfp_parent_count') + self.cpfp_child: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'cpfp_child_count') + class SeriesTree_Transactions_Fees: """Series tree node.""" def __init__(self, client: BrkClient, base_path: str = ''): + self.count: SeriesTree_Transactions_Fees_Count = SeriesTree_Transactions_Fees_Count(client) self.input_value: SeriesPattern19[Sats] = SeriesPattern19(client, 'input_value') self.output_value: SeriesPattern19[Sats] = SeriesPattern19(client, 'output_value') self.fee: _6bBlockTxPattern[Sats] = _6bBlockTxPattern(client, 'fee') self.fee_rate: SeriesPattern19[FeeRate] = SeriesPattern19(client, 'fee_rate') self.effective_fee_rate: _6bBlockTxPattern[FeeRate] = _6bBlockTxPattern(client, 'effective_fee_rate') + self.is_cpfp_parent: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'is_cpfp_parent') + self.is_cpfp_child: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'is_cpfp_child') + +class SeriesTree_Transactions_Patterns_Count: + """Series tree node.""" + + def __init__(self, client: BrkClient, base_path: str = ''): + self.coinjoin: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'coinjoin_count') + self.consolidation: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'consolidation_count') + self.batch_payout: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'batch_payout_count') + +class SeriesTree_Transactions_Patterns: + """Series tree node.""" + + def __init__(self, client: BrkClient, base_path: str = ''): + self.count: SeriesTree_Transactions_Patterns_Count = SeriesTree_Transactions_Patterns_Count(client) + self.is_coinjoin: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'is_coinjoin') + self.is_consolidation: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'is_consolidation') + self.is_batch_payout: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'is_batch_payout') + +class SeriesTree_Transactions_Policy: + """Series tree node.""" + + def __init__(self, client: BrkClient, base_path: str = ''): + self.count: SeriesPattern18[StoredU64] = SeriesPattern18(client, 'nonstandard_count') + self.is_nonstandard: SeriesPattern19[StoredBool] = SeriesPattern19(client, 'is_nonstandard') class SeriesTree_Transactions_Versions: """Series tree node.""" @@ -4446,6 +4558,7 @@ class SeriesTree_Transactions_Versions: self.v1: AverageBlockCumulativeSumPattern[StoredU64] = AverageBlockCumulativeSumPattern(client, 'tx_v1') self.v2: AverageBlockCumulativeSumPattern[StoredU64] = AverageBlockCumulativeSumPattern(client, 'tx_v2') self.v3: AverageBlockCumulativeSumPattern[StoredU64] = AverageBlockCumulativeSumPattern(client, 'tx_v3') + self.other: AverageBlockCumulativeSumPattern[StoredU64] = AverageBlockCumulativeSumPattern(client, 'tx_other_version') class SeriesTree_Transactions_Volume: """Series tree node.""" @@ -4459,9 +4572,12 @@ class SeriesTree_Transactions: def __init__(self, client: BrkClient, base_path: str = ''): self.raw: SeriesTree_Transactions_Raw = SeriesTree_Transactions_Raw(client) + self.features: SeriesTree_Transactions_Features = SeriesTree_Transactions_Features(client) self.count: SeriesTree_Transactions_Count = SeriesTree_Transactions_Count(client) self.size: SeriesTree_Transactions_Size = SeriesTree_Transactions_Size(client) self.fees: SeriesTree_Transactions_Fees = SeriesTree_Transactions_Fees(client) + self.patterns: SeriesTree_Transactions_Patterns = SeriesTree_Transactions_Patterns(client) + self.policy: SeriesTree_Transactions_Policy = SeriesTree_Transactions_Policy(client) self.versions: SeriesTree_Transactions_Versions = SeriesTree_Transactions_Versions(client) self.volume: SeriesTree_Transactions_Volume = SeriesTree_Transactions_Volume(client) @@ -4902,19 +5018,13 @@ class SeriesTree_Scripts_Raw_Empty: self.first_index: SeriesPattern18[EmptyOutputIndex] = SeriesPattern18(client, 'first_empty_output_index') self.to_tx_index: SeriesPattern22[TxIndex] = SeriesPattern22(client, 'tx_index') -class SeriesTree_Scripts_Raw_OpReturn: - """Series tree node.""" - - def __init__(self, client: BrkClient, base_path: str = ''): - self.first_index: SeriesPattern18[OpReturnIndex] = SeriesPattern18(client, 'first_op_return_index') - self.to_tx_index: SeriesPattern23[TxIndex] = SeriesPattern23(client, 'tx_index') - class SeriesTree_Scripts_Raw_P2ms: """Series tree node.""" def __init__(self, client: BrkClient, base_path: str = ''): self.first_index: SeriesPattern18[P2MSOutputIndex] = SeriesPattern18(client, 'first_p2ms_output_index') self.to_tx_index: SeriesPattern25[TxIndex] = SeriesPattern25(client, 'tx_index') + self.legacy_sigops: SeriesPattern25[SigOps] = SeriesPattern25(client, 'p2ms_legacy_sigops') class SeriesTree_Scripts_Raw_Unknown: """Series tree node.""" @@ -4922,13 +5032,13 @@ class SeriesTree_Scripts_Raw_Unknown: def __init__(self, client: BrkClient, base_path: str = ''): self.first_index: SeriesPattern18[UnknownOutputIndex] = SeriesPattern18(client, 'first_unknown_output_index') self.to_tx_index: SeriesPattern33[TxIndex] = SeriesPattern33(client, 'tx_index') + self.legacy_sigops: SeriesPattern33[SigOps] = SeriesPattern33(client, 'unknown_legacy_sigops') class SeriesTree_Scripts_Raw: """Series tree node.""" def __init__(self, client: BrkClient, base_path: str = ''): self.empty: SeriesTree_Scripts_Raw_Empty = SeriesTree_Scripts_Raw_Empty(client) - self.op_return: SeriesTree_Scripts_Raw_OpReturn = SeriesTree_Scripts_Raw_OpReturn(client) self.p2ms: SeriesTree_Scripts_Raw_P2ms = SeriesTree_Scripts_Raw_P2ms(client) self.unknown: SeriesTree_Scripts_Raw_Unknown = SeriesTree_Scripts_Raw_Unknown(client) @@ -4938,6 +5048,69 @@ class SeriesTree_Scripts: def __init__(self, client: BrkClient, base_path: str = ''): self.raw: SeriesTree_Scripts_Raw = SeriesTree_Scripts_Raw(client) +class SeriesTree_OpReturn_Raw: + """Series tree node.""" + + def __init__(self, client: BrkClient, base_path: str = ''): + self.first_index: SeriesPattern18[OpReturnIndex] = SeriesPattern18(client, 'first_op_return_index') + self.to_tx_index: SeriesPattern23[TxIndex] = SeriesPattern23(client, 'tx_index') + self.kind: SeriesPattern23[OpReturnKind] = SeriesPattern23(client, 'kind') + self.post_op_return_bytes: SeriesPattern23[StoredU32] = SeriesPattern23(client, 'op_return_post_op_return_bytes') + +class SeriesTree_OpReturn_Total: + """Series tree node.""" + + def __init__(self, client: BrkClient, base_path: str = ''): + self.post_op_return_bytes: AverageBlockCumulativeSumPattern[StoredU64] = AverageBlockCumulativeSumPattern(client, 'op_return_post_op_return_bytes') + self.carrier_tx_count: AverageBlockCumulativeSumPattern[StoredU64] = AverageBlockCumulativeSumPattern(client, 'op_return_carrier_tx_count') + self.carrier_vsize: AverageBlockCumulativeSumPattern[VSize] = AverageBlockCumulativeSumPattern(client, 'op_return_carrier_vsize') + +class SeriesTree_OpReturn_ByKind: + """Series tree node.""" + + def __init__(self, client: BrkClient, base_path: str = ''): + self.runes: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_runes') + self.veri_block: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_veri_block') + self.omni: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_omni') + self.stacks: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_stacks') + self.blockstack: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_blockstack') + self.colu: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_colu') + self.open_assets: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_open_assets') + self.komodo: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_komodo') + self.coin_spark: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_coin_spark') + self.poet: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_poet') + self.docproof: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_docproof') + self.open_timestamps: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_open_timestamps') + self.factom: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_factom') + self.eternity_wall: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_eternity_wall') + self.memo: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_memo') + self.bitproof: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_bitproof') + self.ascribe: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_ascribe') + self.stampery: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_stampery') + self.epobc: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_epobc') + self.bare_hash: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_bare_hash') + self.text: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_text') + self.empty: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_empty') + self.unknown: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_unknown') + +class SeriesTree_OpReturn_Policy: + """Series tree node.""" + + def __init__(self, client: BrkClient, base_path: str = ''): + self.standard: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_policy_standard') + self.oversized: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_policy_oversized') + self.multiple: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_policy_multiple') + self.pre_v30_nonstandard: CarrierOutputPostPattern = CarrierOutputPostPattern(client, 'op_return_policy_pre_v30_nonstandard') + +class SeriesTree_OpReturn: + """Series tree node.""" + + def __init__(self, client: BrkClient, base_path: str = ''): + self.raw: SeriesTree_OpReturn_Raw = SeriesTree_OpReturn_Raw(client) + self.total: SeriesTree_OpReturn_Total = SeriesTree_OpReturn_Total(client) + self.by_kind: SeriesTree_OpReturn_ByKind = SeriesTree_OpReturn_ByKind(client) + self.policy: SeriesTree_OpReturn_Policy = SeriesTree_OpReturn_Policy(client) + class SeriesTree_Mining_Rewards_Subsidy: """Series tree node.""" @@ -7118,6 +7291,7 @@ class SeriesTree: self.outputs: SeriesTree_Outputs = SeriesTree_Outputs(client) self.addrs: SeriesTree_Addrs = SeriesTree_Addrs(client) self.scripts: SeriesTree_Scripts = SeriesTree_Scripts(client) + self.op_return: SeriesTree_OpReturn = SeriesTree_OpReturn(client) self.mining: SeriesTree_Mining = SeriesTree_Mining(client) self.cointime: SeriesTree_Cointime = SeriesTree_Cointime(client) self.constants: SeriesTree_Constants = SeriesTree_Constants(client) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 398f3f015..724360432 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.97.0" +channel = "1.97.1"