diff --git a/canister/src/state.rs b/canister/src/state.rs index 734d13ab..6c0e63a0 100644 --- a/canister/src/state.rs +++ b/canister/src/state.rs @@ -177,7 +177,8 @@ pub fn ingest_stable_blocks_into_utxoset(state: &mut State) -> bool { } pub fn main_chain_height(state: &State) -> Height { - unstable_blocks::get_main_chain(&state.unstable_blocks).len() as u32 + state.utxos.next_height() + unstable_blocks::get_main_chain_length(&state.unstable_blocks) as u32 + + state.utxos.next_height() - 1 } diff --git a/canister/src/unstable_blocks.rs b/canister/src/unstable_blocks.rs index a9f27feb..2859017f 100644 --- a/canister/src/unstable_blocks.rs +++ b/canister/src/unstable_blocks.rs @@ -228,6 +228,22 @@ pub fn get_main_chain(blocks: &UnstableBlocks) -> BlockChain { main_chain } +/// Returns the length of the "main chain". +/// See `get_main_chain` for what defines a main chain. +pub fn get_main_chain_length(blocks: &UnstableBlocks) -> usize { + let blocks_by_height = blocks.blocks_with_depths_by_heights(); + + // Traverse the heights in reverse order. The highest height with a single block corresponds to + // the tip of the main chain. + for height in (0..blocks_by_height.len()).rev() { + if blocks_by_height[height].len() == 1 { + return height + 1; + } + } + + unreachable!("There must be at least one height with exactly one block."); +} + pub fn get_blocks(blocks: &UnstableBlocks) -> Vec<&Block> { blocktree::blockchains(&blocks.tree) .into_iter()