pub fn fork(
        &self,
        fork_tip: block::Hash,
        sprout_note_commitment_tree: sprout::tree::NoteCommitmentTree,
        sapling_note_commitment_tree: sapling::tree::NoteCommitmentTree,
        orchard_note_commitment_tree: orchard::tree::NoteCommitmentTree,
        history_tree: HistoryTree,
    ) -> Result<Option<Self>, ValidateContextError> {
        if !self.height_by_hash.contains_key(&fork_tip) {
            return Ok(None);
        }

        let mut forked = self.with_trees(
            sprout_note_commitment_tree,
            sapling_note_commitment_tree,
            orchard_note_commitment_tree,
            history_tree,
        );

        while forked.non_finalized_tip_hash() != fork_tip {
            forked.pop_tip();
        }

        // Rebuild the note commitment trees, starting from the finalized tip tree.
        // TODO: change to a more efficient approach by removing nodes
        // from the tree of the original chain (in `pop_tip()`).
        // See https://github.com/ZcashFoundation/zebra/issues/2378
        for block in forked.blocks.values() {
            for transaction in block.block.transactions.iter() {
                for sprout_note_commitment in transaction.sprout_note_commitments() {
                    forked
                        .sprout_note_commitment_tree
                        .append(*sprout_note_commitment)
                        .expect("must work since it was already appended before the fork");
                }

                for sapling_note_commitment in transaction.sapling_note_commitments() {
                    forked
                        .sapling_note_commitment_tree
                        .append(*sapling_note_commitment)
                        .expect("must work since it was already appended before the fork");
                }

                for orchard_note_commitment in transaction.orchard_note_commitments() {
                    forked
                        .orchard_note_commitment_tree
                        .append(*orchard_note_commitment)
                        .expect("must work since it was already appended before the fork");
                }
            }

            // Note that anchors don't need to be recreated since they are already
            // handled in revert_chain_state_with.
            let sapling_root = forked
                .sapling_anchors_by_height
                .get(&block.height)
                .expect("Sapling anchors must exist for pre-fork blocks");

            let orchard_root = forked
                .orchard_anchors_by_height
                .get(&block.height)
                .expect("Orchard anchors must exist for pre-fork blocks");

            forked.history_tree.push(
                self.network,
                block.block.clone(),
                *sapling_root,
                *orchard_root,
            )?;
        }

        Ok(Some(forked))
    }
/// Fork a chain at the block with the given hash, if it is part of this
/// chain.
///
/// The trees must match the trees of the finalized tip and are used
/// to rebuild them after the fork.
Fork a chain at the block with the given hash, if it is part of this
chain.

The trees must match the trees of the finalized tip and are used
to rebuild them after the fork.
Fork a chain at the block with the given hash if it is part of this chain . The trees must match the trees of the finalized tip and are used to rebuild them after the fork .
pub fn fork(
        &self,
        fork_tip: block::Hash,
        sprout_note_commitment_tree: sprout::tree::NoteCommitmentTree,
        sapling_note_commitment_tree: sapling::tree::NoteCommitmentTree,
        orchard_note_commitment_tree: orchard::tree::NoteCommitmentTree,
        history_tree: HistoryTree,
    ) -> Result<Option<Self>, ValidateContextError> {
        if !self.height_by_hash.contains_key(&fork_tip) {
            return Ok(None);
        }
        let mut forked = self.with_trees(
            sprout_note_commitment_tree,
            sapling_note_commitment_tree,
            orchard_note_commitment_tree,
            history_tree,
        );
        while forked.non_finalized_tip_hash() != fork_tip {
            forked.pop_tip();
        }
        // Rebuild the note commitment trees, starting from the finalized tip tree.
        // TODO: change to a more efficient approach by removing nodes
        // from the tree of the original chain (in `pop_tip()`).
        // See https://github.com/ZcashFoundation/zebra/issues/2378
        for block in forked.blocks.values() {
            for transaction in block.block.transactions.iter() {
                for sprout_note_commitment in transaction.sprout_note_commitments() {
                    forked
                        .sprout_note_commitment_tree
                        .append(*sprout_note_commitment)
                        .expect("must work since it was already appended before the fork");
                }
                for sapling_note_commitment in transaction.sapling_note_commitments() {
                    forked
                        .sapling_note_commitment_tree
                        .append(*sapling_note_commitment)
                        .expect("must work since it was already appended before the fork");
                }
                for orchard_note_commitment in transaction.orchard_note_commitments() {
                    forked
                        .orchard_note_commitment_tree
                        .append(*orchard_note_commitment)
                        .expect("must work since it was already appended before the fork");
                }
            }
            // Note that anchors don't need to be recreated since they are already
            // handled in revert_chain_state_with.
            let sapling_root = forked
                .sapling_anchors_by_height
                .get(&block.height)
                .expect("Sapling anchors must exist for pre-fork blocks");
            let orchard_root = forked
                .orchard_anchors_by_height
                .get(&block.height)
                .expect("Orchard anchors must exist for pre-fork blocks");
            forked.history_tree.push(
                self.network,
                block.block.clone(),
                *sapling_root,
                *orchard_root,
            )?;
        }
        Ok(Some(forked))
    }
pub fn fork ( & self , fork_tip : block :: Hash , sprout_note_commitment_tree : sprout :: tree :: NoteCommitmentTree , sapling_note_commitment_tree : sapling :: tree :: NoteCommitmentTree , orchard_note_commitment_tree : orchard :: tree :: NoteCommitmentTree , history_tree : HistoryTree , ) -> Result < Option < Self > , ValidateContextError > { if ! self . height_by_hash . contains_key ( & fork_tip ) { return Ok ( None ) ; } let mut forked = self . with_trees ( sprout_note_commitment_tree , sapling_note_commitment_tree , orchard_note_commitment_tree , history_tree , ) ; while forked . non_finalized_tip_hash ( ) != fork_tip { forked . pop_tip ( ) ; } // Rebuild the note commitment trees, starting from the finalized tip tree. // TODO: change to a more efficient approach by removing nodes // from the tree of the original chain (in `pop_tip()`). // See https://github.com/ZcashFoundation/zebra/issues/2378 for block in forked . blocks . values ( ) { for transaction in block . block . transactions . iter ( ) { for sprout_note_commitment in transaction . sprout_note_commitments ( ) { forked . sprout_note_commitment_tree . append ( * sprout_note_commitment ) . expect ( " " ) ; } for sapling_note_commitment in transaction . sapling_note_commitments ( ) { forked . sapling_note_commitment_tree . append ( * sapling_note_commitment ) . expect ( " " ) ; } for orchard_note_commitment in transaction . orchard_note_commitments ( ) { forked . orchard_note_commitment_tree . append ( * orchard_note_commitment ) . expect ( " " ) ; } } // Note that anchors don't need to be recreated since they are already // handled in revert_chain_state_with. let sapling_root = forked . sapling_anchors_by_height . get ( & block . height ) . expect ( " " ) ; let orchard_root = forked . orchard_anchors_by_height . get ( & block . height ) . expect ( " " ) ; forked . history_tree . push ( self . network , block . block . clone ( ) , * sapling_root , * orchard_root , ) ? ; } Ok ( Some ( forked ) ) }
Fork a chain at the block with the given hash, if it is part of this
chain.
Fork a chain at the block with the given hash if it is part of this chain .
&self
fork_tip
block::Hash
sprout_note_commitment_tree
sprout::tree::NoteCommitmentTree
sapling_note_commitment_tree
sapling::tree::NoteCommitmentTree
orchard_note_commitment_tree
orchard::tree::NoteCommitmentTree
history_tree
HistoryTree