126 lines
4.2 KiB
Rust
126 lines
4.2 KiB
Rust
//! Reading note commitment trees.
|
|
//!
|
|
//! In the functions in this module:
|
|
//!
|
|
//! The block write task commits blocks to the finalized state before updating
|
|
//! `chain` with a cached copy of the best non-finalized chain from
|
|
//! `NonFinalizedState.chain_set`. Then the block commit task can commit additional blocks to
|
|
//! the finalized state after we've cloned the `chain`.
|
|
//!
|
|
//! This means that some blocks can be in both:
|
|
//! - the cached [`Chain`], and
|
|
//! - the shared finalized [`ZebraDb`] reference.
|
|
|
|
use std::sync::Arc;
|
|
|
|
use zebra_chain::{
|
|
orchard, sapling,
|
|
subtree::{NoteCommitmentSubtree, NoteCommitmentSubtreeIndex},
|
|
};
|
|
|
|
use crate::{
|
|
service::{finalized_state::ZebraDb, non_finalized_state::Chain},
|
|
HashOrHeight,
|
|
};
|
|
|
|
/// Returns the Sapling
|
|
/// [`NoteCommitmentTree`](sapling::tree::NoteCommitmentTree) specified by a
|
|
/// hash or height, if it exists in the non-finalized `chain` or finalized `db`.
|
|
pub fn sapling_tree<C>(
|
|
chain: Option<C>,
|
|
db: &ZebraDb,
|
|
hash_or_height: HashOrHeight,
|
|
) -> Option<Arc<sapling::tree::NoteCommitmentTree>>
|
|
where
|
|
C: AsRef<Chain>,
|
|
{
|
|
// # Correctness
|
|
//
|
|
// Since sapling treestates 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
|
|
.and_then(|chain| chain.as_ref().sapling_tree(hash_or_height))
|
|
.or_else(|| db.sapling_tree_by_hash_or_height(hash_or_height))
|
|
}
|
|
|
|
/// Returns the Sapling
|
|
/// [`NoteCommitmentSubtree`](NoteCommitmentSubtree) specified by an
|
|
/// index, if it exists in the non-finalized `chain` or finalized `db`.
|
|
#[allow(unused)]
|
|
pub fn sapling_subtree<C>(
|
|
chain: Option<C>,
|
|
db: &ZebraDb,
|
|
index: NoteCommitmentSubtreeIndex,
|
|
) -> Option<Arc<NoteCommitmentSubtree<sapling::tree::Node>>>
|
|
where
|
|
C: AsRef<Chain>,
|
|
{
|
|
// # Correctness
|
|
//
|
|
// Since sapling treestates 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
|
|
.and_then(|chain| chain.as_ref().sapling_subtree_by_index(index))
|
|
.or_else(|| db.sapling_subtree_by_index(index))
|
|
}
|
|
|
|
/// Returns the Orchard
|
|
/// [`NoteCommitmentTree`](orchard::tree::NoteCommitmentTree) specified by a
|
|
/// hash or height, if it exists in the non-finalized `chain` or finalized `db`.
|
|
pub fn orchard_tree<C>(
|
|
chain: Option<C>,
|
|
db: &ZebraDb,
|
|
hash_or_height: HashOrHeight,
|
|
) -> Option<Arc<orchard::tree::NoteCommitmentTree>>
|
|
where
|
|
C: AsRef<Chain>,
|
|
{
|
|
// # Correctness
|
|
//
|
|
// Since orchard treestates 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
|
|
.and_then(|chain| chain.as_ref().orchard_tree(hash_or_height))
|
|
.or_else(|| db.orchard_tree_by_hash_or_height(hash_or_height))
|
|
}
|
|
|
|
/// Returns the Orchard
|
|
/// [`NoteCommitmentSubtree`](NoteCommitmentSubtree) specified by an
|
|
/// index, if it exists in the non-finalized `chain` or finalized `db`.
|
|
#[allow(unused)]
|
|
pub fn orchard_subtree<C>(
|
|
chain: Option<C>,
|
|
db: &ZebraDb,
|
|
index: NoteCommitmentSubtreeIndex,
|
|
) -> Option<Arc<NoteCommitmentSubtree<orchard::tree::Node>>>
|
|
where
|
|
C: AsRef<Chain>,
|
|
{
|
|
// # Correctness
|
|
//
|
|
// Since orchard treestates 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
|
|
.and_then(|chain| chain.as_ref().orchard_subtree_by_index(index))
|
|
.or_else(|| db.orchard_subtree_by_index(index))
|
|
}
|
|
|
|
#[cfg(feature = "getblocktemplate-rpcs")]
|
|
/// Get the history tree of the provided chain.
|
|
pub fn history_tree<C>(
|
|
chain: Option<C>,
|
|
db: &ZebraDb,
|
|
hash_or_height: HashOrHeight,
|
|
) -> Option<Arc<zebra_chain::history_tree::HistoryTree>>
|
|
where
|
|
C: AsRef<Chain>,
|
|
{
|
|
chain
|
|
.and_then(|chain| chain.as_ref().history_tree(hash_or_height))
|
|
.or_else(|| Some(db.history_tree()))
|
|
}
|