diff --git a/crates/chain-state/src/deferred_trie.rs b/crates/chain-state/src/deferred_trie.rs index 2bf9627632..1dfcb2f27e 100644 --- a/crates/chain-state/src/deferred_trie.rs +++ b/crates/chain-state/src/deferred_trie.rs @@ -256,36 +256,16 @@ impl DeferredTrieData { /// Merge all ancestors into a single overlay. /// /// This is the slow path used when the parent's overlay cannot be reused - /// (e.g., after persist when anchor changes). + /// (e.g., after persist when anchor changes). Iterates ancestors oldest -> newest + /// so newer state takes precedence. /// - /// # Optimization - /// Instead of iterating all ancestors from scratch, we find the most recent - /// ancestor that has a cached `anchored_trie_input` and use that as the base. - /// This reduces O(N) work to O(N - M) work where M is the cached depth. + /// Note: We intentionally do NOT reuse ancestor cached overlays here because + /// those overlays were built with a different anchor_hash. The slow path is + /// triggered precisely because the anchor changed, so we must rebuild from + /// each ancestor's per-block state changes. fn merge_ancestors_into_overlay(ancestors: &[Self]) -> TrieInputSorted { - // Find the most recent ancestor (searching from newest to oldest) that has - // a cached trie_input overlay. We can use that as our base and only merge - // the remaining ancestors. - let mut base_idx = 0; let mut overlay = TrieInputSorted::default(); - - for (idx, ancestor) in ancestors.iter().enumerate().rev() { - let ancestor_data = ancestor.wait_cloned(); - if let Some(anchored) = &ancestor_data.anchored_trie_input { - // Found a cached overlay! Use it as our base. - // We only need to merge ancestors after this one. - overlay = TrieInputSorted::new( - Arc::clone(&anchored.trie_input.nodes), - Arc::clone(&anchored.trie_input.state), - Default::default(), - ); - base_idx = idx + 1; // Start merging from the next ancestor - break; - } - } - - // Merge only the ancestors after the cached base (if any) - for ancestor in &ancestors[base_idx..] { + for ancestor in ancestors { let ancestor_data = ancestor.wait_cloned(); { let will_clone = Arc::strong_count(&overlay.state) > 1;