71 lines
2.2 KiB
Rust
71 lines
2.2 KiB
Rust
//! 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,
|
|
};
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|
|
|
|
/// 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<C>(
|
|
chain: Option<C>,
|
|
db: &ZebraDb,
|
|
hash_or_height: HashOrHeight,
|
|
) -> Option<Arc<Block>>
|
|
where
|
|
C: AsRef<Chain>,
|
|
{
|
|
// # 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<C>(
|
|
chain: Option<C>,
|
|
db: &ZebraDb,
|
|
hash: transaction::Hash,
|
|
) -> Option<Arc<Transaction>>
|
|
where
|
|
C: AsRef<Chain>,
|
|
{
|
|
// # 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))
|
|
}
|