//! Shared state reading code. //! //! Used by [`StateService`] and [`ReadStateService`] //! to read from the best [`Chain`] in the [`NonFinalizedState`], //! and the database in the [`FinalizedState`]. use std::sync::Arc; use zebra_chain::{ block::Block, transaction::{self, Transaction}, }; use crate::{ service::{finalized_state::ZebraDb, non_finalized_state::Chain}, HashOrHeight, }; /// Returns the [`Block`] with [`block::Hash`](zebra_chain::block::Hash) or /// [`Height`](zebra_chain::block::Height), /// if it exists in the non-finalized `chain` or finalized `db`. pub(crate) fn block( chain: Option, db: &ZebraDb, hash_or_height: HashOrHeight, ) -> Option> where C: AsRef, { // # Correctness // // The StateService commits blocks to the finalized state before updating the latest chain, // and it can commit additional blocks after we've cloned this `chain` variable. // // Since blocks are the same in the finalized and non-finalized state, // we check the most efficient alternative first. // (`chain` is always in memory, but `db` stores blocks on disk, with a memory cache.) chain .as_ref() .and_then(|chain| chain.as_ref().block(hash_or_height)) .map(|contextual| contextual.block.clone()) .or_else(|| db.block(hash_or_height)) } /// Returns the [`Transaction`] with [`transaction::Hash`], /// if it exists in the non-finalized `chain` or finalized `db`. pub(crate) fn transaction( chain: Option, db: &ZebraDb, hash: transaction::Hash, ) -> Option> where C: AsRef, { // # Correctness // // The StateService commits blocks to the finalized state before updating the latest chain, // and it can commit additional blocks after we've cloned this `chain` variable. // // Since transactions are the same in the finalized and non-finalized state, // we check the most efficient alternative first. // (`chain` is always in memory, but `db` stores transactions on disk, with a memory cache.) chain .as_ref() .and_then(|chain| chain.as_ref().transaction(hash).cloned()) .or_else(|| db.transaction(hash)) }