Skip to content

Commit

Permalink
Fix node reset race condition
Browse files Browse the repository at this point in the history
  • Loading branch information
HerbertJordan committed Jun 29, 2024
1 parent b470cb1 commit 1cf2b59
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 4 deletions.
8 changes: 4 additions & 4 deletions go/database/mpt/forest.go
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ func (s *Forest) createAccount() (NodeReference, shared.WriteHandle[Node], error
instance, present := s.addToCache(&ref, shared.MakeShared[Node](node))
if present {
write := instance.GetWriteHandle()
*write.Get().(*AccountNode) = *node
write.Get().Reset()
write.Release()
}
return ref, instance.GetWriteHandle(), err
Expand All @@ -927,7 +927,7 @@ func (s *Forest) createBranch() (NodeReference, shared.WriteHandle[Node], error)
instance, present := s.addToCache(&ref, shared.MakeShared[Node](node))
if present {
write := instance.GetWriteHandle()
*write.Get().(*BranchNode) = *node
write.Get().Reset()
write.Release()
}
return ref, instance.GetWriteHandle(), err
Expand All @@ -943,7 +943,7 @@ func (s *Forest) createExtension() (NodeReference, shared.WriteHandle[Node], err
instance, present := s.addToCache(&ref, shared.MakeShared[Node](node))
if present {
write := instance.GetWriteHandle()
*write.Get().(*ExtensionNode) = *node
write.Get().Reset()
write.Release()
}
return ref, instance.GetWriteHandle(), err
Expand All @@ -959,7 +959,7 @@ func (s *Forest) createValue() (NodeReference, shared.WriteHandle[Node], error)
instance, present := s.addToCache(&ref, shared.MakeShared[Node](node))
if present {
write := instance.GetWriteHandle()
*write.Get().(*ValueNode) = *node
write.Get().Reset()
write.Release()
}
return ref, instance.GetWriteHandle(), err
Expand Down
45 changes: 45 additions & 0 deletions go/database/mpt/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ type Node interface {
// rooted by this node. Only non-frozen nodes can be released.
Release(manager NodeManager, thisRef *NodeReference, this shared.WriteHandle[Node]) error

// Reset resets the node to its zero state.
Reset()

// IsDirty returns whether this node's state is different in memory than it
// is on disk. All nodes are created dirty and may only be cleaned by marking
// them as such.
Expand Down Expand Up @@ -554,6 +557,12 @@ func (n *nodeBase) Release() {
n.hashStatus = hashStatusClean
}

func (n *nodeBase) reset() {
n.markDirty()
n.hashStatus = hashStatusDirty
n.frozen = false
}

func (n *nodeBase) check(thisRef *NodeReference) error {
var errs []error
if !n.IsDirty() && n.hashStatus == hashStatusDirty {
Expand Down Expand Up @@ -636,6 +645,10 @@ func (e EmptyNode) Release(NodeManager, *NodeReference, shared.WriteHandle[Node]
return nil
}

func (e EmptyNode) Reset() {
// nothing to do
}

func (e EmptyNode) IsDirty() bool {
return false
}
Expand Down Expand Up @@ -929,6 +942,14 @@ func (n *BranchNode) Release(manager NodeManager, thisRef *NodeReference, this s
return manager.release(thisRef)
}

func (n *BranchNode) Reset() {
n.nodeBase.reset()
n.children = [16]NodeReference{}
n.dirtyHashes = 0
n.embeddedChildren = 0
n.frozenChildren = 0
}

func (n *BranchNode) MarkFrozen() {
n.nodeBase.MarkFrozen()
n.frozenChildren = ^uint16(0)
Expand Down Expand Up @@ -1404,6 +1425,14 @@ func (n *ExtensionNode) Release(manager NodeManager, thisRef *NodeReference, thi
return manager.release(thisRef)
}

func (n *ExtensionNode) Reset() {
n.nodeBase.reset()
n.path = Path{}
n.next = NodeReference{}
n.nextHashDirty = true
n.nextIsEmbedded = false
}

func (n *ExtensionNode) Freeze(manager NodeManager, this shared.WriteHandle[Node]) error {
if n.IsFrozen() {
return nil
Expand Down Expand Up @@ -1802,6 +1831,15 @@ func (n *AccountNode) Release(manager NodeManager, thisRef *NodeReference, this
return manager.release(thisRef)
}

func (n *AccountNode) Reset() {
n.nodeBase.reset()
n.address = common.Address{}
n.info = AccountInfo{}
n.storage = NodeReference{}
n.storageHashDirty = true
n.pathLength = 0
}

func (n *AccountNode) setPathLength(manager NodeManager, thisRef *NodeReference, this shared.WriteHandle[Node], length byte) (NodeReference, bool, error) {
if n.pathLength == length {
return *thisRef, false, nil
Expand Down Expand Up @@ -2041,6 +2079,13 @@ func (n *ValueNode) Release(manager NodeManager, thisRef *NodeReference, this sh
return manager.release(thisRef)
}

func (n *ValueNode) Reset() {
n.nodeBase.reset()
n.key = common.Key{}
n.value = common.Value{}
n.pathLength = 0
}

func (n *ValueNode) setPathLength(manager NodeManager, thisRef *NodeReference, this shared.WriteHandle[Node], length byte) (NodeReference, bool, error) {
if n.pathLength == length {
return *thisRef, false, nil
Expand Down
24 changes: 24 additions & 0 deletions go/database/mpt/nodes_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1cf2b59

Please sign in to comment.