diff --git a/x/merkledb/history.go b/x/merkledb/history.go index fbaeca3bd8e3..e58dedbd3e19 100644 --- a/x/merkledb/history.go +++ b/x/merkledb/history.go @@ -96,28 +96,34 @@ func (th *trieHistory) getValueChanges(startRoot, endRoot ids.ID, start, end []b return nil, ErrRootIDNotPresent } - // [lastStartRootChange] is the latest appearance of [startRoot] - // which came before [lastEndRootChange]. - var lastStartRootChange *changeSummaryAndIndex - th.history.DescendLessOrEqual( - lastEndRootChange, - func(item *changeSummaryAndIndex) bool { - if item == lastEndRootChange { - return true // Skip first iteration - } - if item.rootID == startRoot { - lastStartRootChange = item - return false - } - return true - }, - ) - - // There's no change resulting in [startRoot] before the latest change resulting in [endRoot]. - if lastStartRootChange == nil { + // [startRootChanges] is the last appearance of [startRoot] + startRootChanges, ok := th.lastChanges[startRoot] + if !ok { return nil, ErrStartRootNotFound } + // startRootChanges is after the lastEndRootChange, but that is just the latest appearance of start root + // there may be an earlier entry, so attempt to find an entry that comes before lastEndRootChange + if startRootChanges.index > lastEndRootChange.index { + th.history.DescendLessOrEqual( + lastEndRootChange, + func(item *changeSummaryAndIndex) bool { + if item == lastEndRootChange { + return true // Skip first iteration + } + if item.rootID == startRoot { + startRootChanges = item + return false + } + return true + }, + ) + // There's no change resulting in [startRoot] before the latest change resulting in [endRoot]. + if startRootChanges.index > lastEndRootChange.index { + return nil, ErrStartRootNotFound + } + } + // Keep changes sorted so the largest can be removed in order to stay within the maxLength limit. sortedKeys := btree.NewG( 2, @@ -135,13 +141,13 @@ func (th *trieHistory) getValueChanges(startRoot, endRoot ids.ID, start, end []b // Only the key-value pairs with the greatest [maxLength] keys will be kept. combinedChanges := newChangeSummary(maxLength) - // For each change after [lastStartRootChange] up to and including + // For each change after [startRootChanges] up to and including // [lastEndRootChange], record the change in [combinedChanges]. th.history.AscendGreaterOrEqual( - lastStartRootChange, + startRootChanges, func(item *changeSummaryAndIndex) bool { - if item == lastStartRootChange { - // Start from the first change after [lastStartRootChange]. + if item == startRootChanges { + // Start from the first change after [startRootChanges]. return true } if item.index > lastEndRootChange.index {