mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-12 01:41:36 +00:00
trie/bintrie: move dirty+mustRecompute flip into setValue
The invariant "mutating a value slot must mark the stem for re-hash and re-flush" was enforced by every caller remembering to set both flags after setValue. Moving the flip into setValue itself makes it structurally impossible to forget, and drops the duplicate flag-sets at each callsite. decodeNode's on-disk load path still writes directly to sn.values because loaded stems must retain whatever mustRecompute/dirty state the caller asked for (typically both false).
This commit is contained in:
parent
d216942b7c
commit
f676f04706
2 changed files with 11 additions and 5 deletions
|
|
@ -51,8 +51,15 @@ func (sn *StemNode) allValues() [][]byte {
|
|||
return sn.values[:]
|
||||
}
|
||||
|
||||
// setValue mutates a value slot and marks the stem for re-hash and
|
||||
// re-flush. This is the only API for post-load value mutation; direct
|
||||
// values[...] writes are reserved for the on-disk load path in
|
||||
// decodeNode, which must leave mustRecompute/dirty at their loaded
|
||||
// state.
|
||||
func (sn *StemNode) setValue(suffix byte, value []byte) {
|
||||
sn.values[suffix] = value
|
||||
sn.mustRecompute = true
|
||||
sn.dirty = true
|
||||
}
|
||||
|
||||
func (sn *StemNode) Hash() common.Hash {
|
||||
|
|
|
|||
|
|
@ -199,12 +199,10 @@ func (s *NodeStore) insertValuesAtStem(ref nodeRef, stem []byte, values [][]byte
|
|||
case kindStem:
|
||||
sn := s.getStem(ref.Index())
|
||||
if sn.Stem == [StemSize]byte(stem[:StemSize]) {
|
||||
// Same stem — merge values
|
||||
// Same stem — merge values (setValue marks dirty+mustRecompute)
|
||||
for i, v := range values {
|
||||
if v != nil {
|
||||
sn.setValue(byte(i), v)
|
||||
sn.mustRecompute = true
|
||||
sn.dirty = true
|
||||
}
|
||||
}
|
||||
return ref, nil
|
||||
|
|
@ -233,7 +231,8 @@ func (s *NodeStore) insertValuesAtStem(ref nodeRef, stem []byte, values [][]byte
|
|||
return s.insertValuesAtStem(resolved, stem, values, resolver, depth)
|
||||
|
||||
case kindEmpty:
|
||||
// Create new StemNode
|
||||
// Create new StemNode. Flag flips before the value loop so an
|
||||
// all-nil values input still marks the newly-created stem dirty.
|
||||
stemIdx := s.allocStem()
|
||||
sn := s.getStem(stemIdx)
|
||||
copy(sn.Stem[:], stem[:StemSize])
|
||||
|
|
@ -242,7 +241,7 @@ func (s *NodeStore) insertValuesAtStem(ref nodeRef, stem []byte, values [][]byte
|
|||
sn.dirty = true
|
||||
for i, v := range values {
|
||||
if v != nil {
|
||||
sn.values[i] = v
|
||||
sn.setValue(byte(i), v)
|
||||
}
|
||||
}
|
||||
return makeRef(kindStem, stemIdx), nil
|
||||
|
|
|
|||
Loading…
Reference in a new issue