diff --git a/zebra-state/src/service/finalized_state/zebra_db/block.rs b/zebra-state/src/service/finalized_state/zebra_db/block.rs index e10fd3b43..c69f3b261 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/block.rs +++ b/zebra-state/src/service/finalized_state/zebra_db/block.rs @@ -392,7 +392,7 @@ impl ZebraDb { spent_utxos_by_outpoint, spent_utxos_by_out_loc, address_balances, - self.finalized_value_pool(), + self.finalized_tip_value_pool(), prev_note_commitment_trees, )?; diff --git a/zebra-state/src/service/finalized_state/zebra_db/chain.rs b/zebra-state/src/service/finalized_state/zebra_db/chain.rs index 5653af1c3..f05414ca2 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/chain.rs +++ b/zebra-state/src/service/finalized_state/zebra_db/chain.rs @@ -60,7 +60,7 @@ pub const CHAIN_VALUE_POOLS: &str = "tip_chain_value_pool"; /// /// This constant should be used so the compiler can detect incorrectly typed accesses to the /// column family. -pub type ChainValuePoolsCf<'cf> = TypedColumnFamily<'cf, (), ValueBalance>; +pub type ChainValuePoolsCf<'cf> = TypedColumnFamily<'cf, Height, ValueBalance>; impl ZebraDb { // Column family convenience methods @@ -154,12 +154,22 @@ impl ZebraDb { // Value pool methods - /// Returns the stored `ValueBalance` for the best chain at the finalized tip height. - pub fn finalized_value_pool(&self) -> ValueBalance { + /// Returns the stored `ValueBalance` for the best chain at the provided height. + pub fn finalized_value_pool(&self, height: Height) -> ValueBalance { let chain_value_pools_cf = self.chain_value_pools_cf(); chain_value_pools_cf - .zs_get(&()) + .zs_get(&height) + .unwrap_or_else(ValueBalance::zero) + } + + /// Returns the stored `ValueBalance` for the best chain at the finalized tip. + pub fn finalized_tip_value_pool(&self) -> ValueBalance { + let chain_value_pools_cf = self.chain_value_pools_cf(); + + chain_value_pools_cf + .zs_last_key_value() + .map(|(_k, v)| v) .unwrap_or_else(ValueBalance::zero) } } @@ -231,7 +241,7 @@ impl DiskWriteBatch { .chain_value_pools_cf() .with_batch_for_writing(self) .zs_insert( - &(), + &finalized.height, &value_pool.add_chain_value_pool_change( finalized.block.chain_value_pool_change( &utxos_spent_by_block, diff --git a/zebra-state/src/service/non_finalized_state.rs b/zebra-state/src/service/non_finalized_state.rs index 08d644550..c687a16ab 100644 --- a/zebra-state/src/service/non_finalized_state.rs +++ b/zebra-state/src/service/non_finalized_state.rs @@ -288,7 +288,7 @@ impl NonFinalizedState { finalized_state.sapling_tree_for_tip(), finalized_state.orchard_tree_for_tip(), finalized_state.history_tree(), - finalized_state.finalized_value_pool(), + finalized_state.finalized_tip_value_pool(), ); let (height, hash) = (prepared.height, prepared.hash); diff --git a/zebra-state/src/service/read/find.rs b/zebra-state/src/service/read/find.rs index e9d557dbf..3ac7dcb9f 100644 --- a/zebra-state/src/service/read/find.rs +++ b/zebra-state/src/service/read/find.rs @@ -104,7 +104,7 @@ where return Ok(None); }; - let value_balance = db.finalized_value_pool(); + let value_balance = db.finalized_tip_value_pool(); if tip == db.tip() { return Ok(Some((tip_height, tip_hash, value_balance))); diff --git a/zebra-state/src/service/tests.rs b/zebra-state/src/service/tests.rs index 9b2e6f32f..0d1400818 100644 --- a/zebra-state/src/service/tests.rs +++ b/zebra-state/src/service/tests.rs @@ -403,7 +403,7 @@ proptest! { // We're waiting to verify each block here, so we don't need the maximum checkpoint height. let (mut state_service, _, _, _) = StateService::new(Config::ephemeral(), &network, Height::MAX, 0); - prop_assert_eq!(state_service.read_service.db.finalized_value_pool(), ValueBalance::zero()); + prop_assert_eq!(state_service.read_service.db.finalized_tip_value_pool(), ValueBalance::zero()); prop_assert_eq!( state_service.read_service.latest_non_finalized_state().best_chain().map(|chain| chain.chain_value_pools).unwrap_or_else(ValueBalance::zero), ValueBalance::zero() @@ -414,14 +414,14 @@ proptest! { // the expected transparent pool value, calculated using the slow start rate let mut expected_transparent_pool = ValueBalance::zero(); - let mut expected_finalized_value_pool = Ok(ValueBalance::zero()); + let mut expected_finalized_tip_value_pool = Ok(ValueBalance::zero()); for block in finalized_blocks { // the genesis block has a zero-valued transparent output, // which is not included in the UTXO set if block.height > block::Height(0) { let utxos = &block.new_outputs.iter().map(|(k, ordered_utxo)| (*k, ordered_utxo.utxo.clone())).collect(); let block_value_pool = &block.block.chain_value_pool_change(utxos, None)?; - expected_finalized_value_pool += *block_value_pool; + expected_finalized_tip_value_pool += *block_value_pool; } let result_receiver = state_service.queue_and_commit_to_finalized_state(block.clone()); @@ -430,8 +430,8 @@ proptest! { prop_assert!(result.is_ok(), "unexpected failed finalized block commit: {:?}", result); prop_assert_eq!( - state_service.read_service.db.finalized_value_pool(), - expected_finalized_value_pool.clone()?.constrain()? + state_service.read_service.db.finalized_tip_value_pool(), + expected_finalized_tip_value_pool.clone()?.constrain()? ); let transparent_value = SLOW_START_RATE * i64::from(block.height.0); @@ -439,16 +439,16 @@ proptest! { let transparent_value = ValueBalance::from_transparent_amount(transparent_value); expected_transparent_pool = (expected_transparent_pool + transparent_value).unwrap(); prop_assert_eq!( - state_service.read_service.db.finalized_value_pool(), + state_service.read_service.db.finalized_tip_value_pool(), expected_transparent_pool ); } - let mut expected_non_finalized_value_pool = Ok(expected_finalized_value_pool?); + let mut expected_non_finalized_tip_value_pool = Ok(expected_finalized_tip_value_pool?); for block in non_finalized_blocks { let utxos = block.new_outputs.clone(); let block_value_pool = &block.block.chain_value_pool_change(&transparent::utxos_from_ordered_utxos(utxos), None)?; - expected_non_finalized_value_pool += *block_value_pool; + expected_non_finalized_tip_value_pool += *block_value_pool; let result_receiver = state_service.queue_and_commit_to_non_finalized_state(block.clone()); let result = result_receiver.blocking_recv(); @@ -457,7 +457,7 @@ proptest! { prop_assert_eq!( state_service.read_service.latest_non_finalized_state().best_chain().unwrap().chain_value_pools, - expected_non_finalized_value_pool.clone()?.constrain()? + expected_non_finalized_tip_value_pool.clone()?.constrain()? ); let transparent_value = SLOW_START_RATE * i64::from(block.height.0);