Skip to content

Invalidate boundary when converting HashList to HashArray in HashSeq#150

Merged
tersec merged 3 commits intomasterfrom
dev/etan/hl-seq
Feb 12, 2026
Merged

Invalidate boundary when converting HashList to HashArray in HashSeq#150
tersec merged 3 commits intomasterfrom
dev/etan/hl-seq

Conversation

@etan-status
Copy link
Contributor

Cache layout is equivalent, but when using readSszBytes the boundary has to be cleared first to cover the case where the resize does not incrementally fill up the list to the full capacity before converting. Also move the boundary cache invalidation from types.nim to codec.nim.

Cache layout is equivalent, but when using readSszBytes the boundary
has to be cleared first to cover the case where the resize does not
incrementally fill up the list to the full capacity before converting.
Also move the boundary cache invalidation from types.nim to codec.nim.
Comment on lines 229 to +231
# Unconditionally trigger small, O(1) updates to handle when the list
# shrinks without otherwise changing.
val.clearCaches(0)
val.clearCaches(max(val.len - 1, 0))
# resizes without otherwise changing.
val.clearCaches(max(min(val.len, oldDataLen) - 1, 0))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the one that we were missing. The shrinking to a different depth was fine, but the followup re-growth hit the stale cache. Clearing the boundary at oldDataLen fixes that.

@tersec tersec merged commit 79ed8a3 into master Feb 12, 2026
17 checks passed
@tersec tersec deleted the dev/etan/hl-seq branch February 12, 2026 21:02
@etan-status
Copy link
Contributor Author

image

Like, here the codec with more context.

  1. Imagine start with 3 items in a HashList[8, E]
  2. In the hashes, we store h(a, b) for two consecutive leaves, so it's [h(0,1), h(2,ZERO), uninitSentinel, uninitSentinel]
  3. Then the setOutputSize (first highlight) extends the list with default(E)
  4. If there is an actual default(E) in the read data, check (2) is skipped, so hash is not cleared. This is fine for the uninitSentinel case, because those entries are new, so not yet initialized
  5. However, h(2,ZERO) now needs to be h(2,default(E)), so the boundary needs clearing.

For shrinking the logic was already in place. For growing, it cleared the second boundary (within the new uninitSentinel area) rather than the boundary between retained and new data.

meny3437-blip

This comment was marked as spam.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Comments