From 0a535ee3f8c12ec7468f450ab655c90abba79b9c Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Tue, 1 Nov 2022 12:37:31 -0700 Subject: [PATCH] Track ordinal ranges (#756) --- src/index.rs | 25 +++++++---- src/index/updater.rs | 11 +++++ src/subcommand/server.rs | 96 ++++++++++++++++++++++++++++++++++++++++ tests/info.rs | 19 ++++---- 4 files changed, 133 insertions(+), 18 deletions(-) diff --git a/src/index.rs b/src/index.rs index 3259675aee..8ec125da4c 100644 --- a/src/index.rs +++ b/src/index.rs @@ -67,6 +67,7 @@ pub(crate) enum List { pub(crate) enum Statistic { OutputsTraversed = 0, Commits = 1, + OrdinalRanges = 2, } impl From for u64 { @@ -188,6 +189,11 @@ impl Index { let utxos_indexed = wtx.open_table(OUTPOINT_TO_ORDINAL_RANGES)?.len()?; + let ordinal_ranges = wtx + .open_table(STATISTIC_TO_COUNT)? + .get(&Statistic::OrdinalRanges.into())? + .unwrap_or(0); + let outputs_traversed = wtx .open_table(STATISTIC_TO_COUNT)? .get(&Statistic::OutputsTraversed.into())? @@ -195,16 +201,17 @@ impl Index { let stats = wtx.stats()?; - println!("blocks indexed: {}", blocks_indexed); - println!("utxos indexed: {}", utxos_indexed); - println!("outputs traversed: {}", outputs_traversed); - println!("tree height: {}", stats.tree_height()); - println!("free pages: {}", stats.free_pages()); - println!("stored: {}", Bytes(stats.stored_bytes())); - println!("overhead: {}", Bytes(stats.metadata_bytes())); - println!("fragmented: {}", Bytes(stats.fragmented_bytes())); + println!("blocks indexed\t{}", blocks_indexed); + println!("utxos indexed\t{}", utxos_indexed); + println!("outputs traversed\t{}", outputs_traversed); + println!("ordinal ranges\t{}", ordinal_ranges); + println!("tree height\t{}", stats.tree_height()); + println!("free pages\t{}", stats.free_pages()); + println!("stored\t{}", Bytes(stats.stored_bytes())); + println!("overhead\t{}", Bytes(stats.metadata_bytes())); + println!("fragmented\t{}", Bytes(stats.fragmented_bytes())); println!( - "index size: {}", + "index size\t{}", Bytes(std::fs::metadata(&self.database_path)?.len().try_into()?) ); diff --git a/src/index/updater.rs b/src/index/updater.rs index ecfedda600..6866dbb1ce 100644 --- a/src/index/updater.rs +++ b/src/index/updater.rs @@ -4,6 +4,7 @@ pub struct Updater { cache: HashMap<[u8; 36], Vec>, outputs_traversed: u64, outputs_cached: u64, + ordinal_ranges_since_flush: u64, outputs_inserted_since_flush: u64, height: u64, } @@ -25,6 +26,7 @@ impl Updater { outputs_traversed: 0, outputs_cached: 0, outputs_inserted_since_flush: 0, + ordinal_ranges_since_flush: 0, height, }; @@ -201,6 +203,7 @@ impl Updater { if h.subsidy() > 0 { let start = h.starting_ordinal(); coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); + self.ordinal_ranges_since_flush += 1; } for (tx_offset, tx) in block.txdata.iter().enumerate().skip(1) { @@ -301,6 +304,7 @@ impl Updater { let count = range.1 - range.0; let assigned = if count > remaining { + self.ordinal_ranges_since_flush += 1; let middle = range.0 + remaining; input_ordinal_ranges.push_front((middle, range.1)); (range.0, middle) @@ -357,6 +361,13 @@ impl Updater { } Index::increment_statistic(&wtx, Statistic::OutputsTraversed, self.outputs_traversed)?; + self.outputs_traversed = 0; + Index::increment_statistic( + &wtx, + Statistic::OrdinalRanges, + self.ordinal_ranges_since_flush, + )?; + self.ordinal_ranges_since_flush = 0; Index::increment_statistic(&wtx, Statistic::Commits, 1)?; wtx.commit()?; Ok(()) diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 004d722a37..1122e0b463 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -1452,6 +1452,7 @@ mod tests { 1 ); + server.bitcoin_rpc_server.mine_blocks(1); server.bitcoin_rpc_server.mine_blocks(1); server.index.update().unwrap(); @@ -1461,7 +1462,102 @@ mod tests { .index .statistic(crate::index::Statistic::OutputsTraversed) .unwrap(), + 3 + ); + } + + #[test] + fn coinbase_ordinal_ranges_are_tracked() { + let server = TestServer::new(); + + assert_eq!( + server + .index + .statistic(crate::index::Statistic::OrdinalRanges) + .unwrap(), + 1 + ); + + server.bitcoin_rpc_server.mine_blocks(1); + server.index.update().unwrap(); + + assert_eq!( + server + .index + .statistic(crate::index::Statistic::OrdinalRanges) + .unwrap(), 2 ); + + server.bitcoin_rpc_server.mine_blocks(1); + server.index.update().unwrap(); + + assert_eq!( + server + .index + .statistic(crate::index::Statistic::OrdinalRanges) + .unwrap(), + 3 + ); + } + + #[test] + fn split_ordinal_ranges_are_tracked() { + let server = TestServer::new(); + + assert_eq!( + server + .index + .statistic(crate::index::Statistic::OrdinalRanges) + .unwrap(), + 1 + ); + + server.bitcoin_rpc_server.mine_blocks(1); + server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { + input_slots: &[(1, 0, 0)], + output_count: 2, + fee: 0, + }); + server.bitcoin_rpc_server.mine_blocks(1); + server.index.update().unwrap(); + + assert_eq!( + server + .index + .statistic(crate::index::Statistic::OrdinalRanges) + .unwrap(), + 4, + ); + } + + #[test] + fn fee_ordinal_ranges_are_tracked() { + let server = TestServer::new(); + + assert_eq!( + server + .index + .statistic(crate::index::Statistic::OrdinalRanges) + .unwrap(), + 1 + ); + + server.bitcoin_rpc_server.mine_blocks(1); + server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { + input_slots: &[(1, 0, 0)], + output_count: 2, + fee: 2, + }); + server.bitcoin_rpc_server.mine_blocks(1); + server.index.update().unwrap(); + + assert_eq!( + server + .index + .statistic(crate::index::Statistic::OrdinalRanges) + .unwrap(), + 5, + ); } } diff --git a/tests/info.rs b/tests/info.rs index a4a9e87638..66d5c8df4a 100644 --- a/tests/info.rs +++ b/tests/info.rs @@ -6,15 +6,16 @@ fn basic() { CommandBuilder::new("info") .rpc_server(&rpc_server) .stdout_regex( - r" - blocks indexed: 1 - utxos indexed: 1 - outputs traversed: 1 - tree height: \d+ - free pages: \d+ - stored: .* - overhead: .* - fragmented: .* + " + blocks indexed\t1 + utxos indexed\t1 + outputs traversed\t1 + ordinal ranges\t1 + tree height\t\\d+ + free pages\t\\d+ + stored\t.* + overhead\t.* + fragmented\t.* " .unindent(), )