Skip to content

Commit

Permalink
allow for node resolution in Delete (#230)
Browse files Browse the repository at this point in the history
  • Loading branch information
gballet authored Jun 6, 2022
1 parent b40dee8 commit 4e4c3f6
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 19 deletions.
2 changes: 1 addition & 1 deletion empty.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (e Empty) InsertOrdered(key []byte, value []byte, _ NodeFlushFn) error {
return e.Insert(key, value, nil)
}

func (Empty) Delete([]byte) error {
func (Empty) Delete([]byte, NodeResolverFn) error {
return errors.New("cant delete an empty node")
}

Expand Down
2 changes: 1 addition & 1 deletion empty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestEmptyFuncs(t *testing.T) {
if err == nil {
t.Fatal("got nil error when inserting into empty")
}
err = e.Delete(zeroKeyTest)
err = e.Delete(zeroKeyTest, nil)
if err == nil {
t.Fatal("got nil error when deleting from empty")
}
Expand Down
2 changes: 1 addition & 1 deletion hashednode.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (*HashedNode) InsertOrdered([]byte, []byte, NodeFlushFn) error {
return errInsertIntoHash
}

func (*HashedNode) Delete([]byte) error {
func (*HashedNode) Delete([]byte, NodeResolverFn) error {
return errors.New("cant delete a hashed node in-place")
}

Expand Down
2 changes: 1 addition & 1 deletion hashednode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestHashedNodeFuncs(t *testing.T) {
if err == nil {
t.Fatal("got nil error when inserting into a hashed node")
}
err = e.Delete(zeroKeyTest)
err = e.Delete(zeroKeyTest, nil)
if err == nil {
t.Fatal("got nil error when deleting from a hashed node")
}
Expand Down
4 changes: 2 additions & 2 deletions stateless.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ func (*StatelessNode) InsertOrdered([]byte, []byte, NodeFlushFn) error {
return errNotSupportedInStateless
}

func (n *StatelessNode) Delete(key []byte) error {
func (n *StatelessNode) Delete(key []byte, resolver NodeResolverFn) error {
// Case of an ext node
if n.values != nil {
var zero [32]byte
Expand All @@ -303,7 +303,7 @@ func (n *StatelessNode) Delete(key []byte) error {
child := n.children[nChild]
var pre Fr
CopyFr(&pre, child.hash)
if err := child.Delete(key); err != nil {
if err := child.Delete(key, resolver); err != nil {
return err
}

Expand Down
4 changes: 2 additions & 2 deletions stateless_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ func TestStatelessDelete(t *testing.T) {
t.Fatal("second insert didn't update")
}

root.Delete(oneKeyTest)
root.Delete(oneKeyTest, nil)

rootRef := New()
rootRef.Insert(zeroKeyTest, fourtyKeyTest, nil)
rootRef.Insert(oneKeyTest, fourtyKeyTest, nil)
rootRef.Delete(oneKeyTest)
rootRef.Delete(oneKeyTest, nil)

if !Equal(rootRef.ComputeCommitment(), root.commitment) {
t.Fatal("error in delete", rootRef.ComputeCommitment(), root.hash)
Expand Down
25 changes: 20 additions & 5 deletions tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ type VerkleNode interface {
InsertOrdered([]byte, []byte, NodeFlushFn) error

// Delete a leaf with the given key
Delete([]byte) error
Delete([]byte, NodeResolverFn) error

// Get value at a given key
Get([]byte, NodeResolverFn) ([]byte, error)
Expand Down Expand Up @@ -549,7 +549,7 @@ func (n *InternalNode) InsertStemOrdered(key []byte, leaf *LeafNode, flush NodeF
return nil
}

func (n *InternalNode) Delete(key []byte) error {
func (n *InternalNode) Delete(key []byte, resolver NodeResolverFn) error {
// Clear cached commitment on modification
n.commitment = nil

Expand All @@ -558,9 +558,24 @@ func (n *InternalNode) Delete(key []byte) error {
case Empty:
return errDeleteNonExistent
case *HashedNode:
return errDeleteHash
if resolver == nil {
return errDeleteHash
}
comm := child.commitment.Bytes()
payload, err := resolver(comm[:])
if err != nil {
return err
}
// deserialize the payload and set it as the child
c, err := ParseNode(payload, n.depth+1, comm[:])
if err != nil {
return err
}
c.ComputeCommitment()
n.children[nChild] = c
return n.Delete(key, resolver)
default:
return child.Delete(key)
return child.Delete(key, resolver)
}
}

Expand Down Expand Up @@ -855,7 +870,7 @@ func (n *LeafNode) InsertOrdered(key []byte, value []byte, _ NodeFlushFn) error
return n.Insert(key, value, nil)
}

func (n *LeafNode) Delete(k []byte) error {
func (n *LeafNode) Delete(k []byte, _ NodeResolverFn) error {
// Sanity check: ensure the key header is the same:
if !equalPaths(k, n.stem) {
return errDeleteNonExistent
Expand Down
45 changes: 39 additions & 6 deletions tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ func TestDelLeaf(t *testing.T) {
hash := tree.ComputeCommitment()

tree.Insert(key3, fourtyKeyTest, nil)
if err := tree.Delete(key3); err != nil {
if err := tree.Delete(key3, nil); err != nil {
t.Error(err)
}

Expand All @@ -354,7 +354,7 @@ func TestDeleteNonExistent(t *testing.T) {
tree := New()
tree.Insert(key1, fourtyKeyTest, nil)
tree.Insert(key2, fourtyKeyTest, nil)
if err := tree.Delete(key3); err != errDeleteNonExistent {
if err := tree.Delete(key3, nil); err != errDeleteNonExistent {
t.Error("should fail to delete non-existent key")
}
}
Expand All @@ -373,7 +373,7 @@ func TestDeletePrune(t *testing.T) {
hash2 := tree.ComputeCommitment()
tree.Insert(key4, fourtyKeyTest, nil)

if err := tree.Delete(key4); err != nil {
if err := tree.Delete(key4, nil); err != nil {
t.Error(err)
}
postHash := tree.ComputeCommitment()
Expand All @@ -388,7 +388,7 @@ func TestDeletePrune(t *testing.T) {
t.Error("leaf hasnt been deleted")
}

if err := tree.Delete(key3); err != nil {
if err := tree.Delete(key3, nil); err != nil {
t.Error(err)
}
postHash = tree.ComputeCommitment()
Expand All @@ -413,7 +413,7 @@ func TestDeleteHash(t *testing.T) {
tree.InsertOrdered(key2, fourtyKeyTest, nil)
tree.InsertOrdered(key3, fourtyKeyTest, nil)
tree.ComputeCommitment()
if err := tree.Delete(key2); err != errDeleteHash {
if err := tree.Delete(key2, nil); err != errDeleteHash {
t.Fatalf("did not report the correct error while deleting from a hash: %v", err)
}
}
Expand All @@ -427,10 +427,43 @@ func TestDeleteUnequalPath(t *testing.T) {
tree.Insert(key3, fourtyKeyTest, nil)
tree.ComputeCommitment()

if err := tree.Delete(key2); err != errDeleteNonExistent {
if err := tree.Delete(key2, nil); err != errDeleteNonExistent {
t.Fatalf("didn't catch the deletion of non-existing key, err =%v", err)
}
}
func TestDeleteResolve(t *testing.T) {
key1, _ := hex.DecodeString("0105000000000000000000000000000000000000000000000000000000000000")
key2, _ := hex.DecodeString("0107000000000000000000000000000000000000000000000000000000000000")
key3, _ := hex.DecodeString("0405000000000000000000000000000000000000000000000000000000000000")
tree := New()
var savedNodes []VerkleNode
saveNode := func(node VerkleNode) {
savedNodes = append(savedNodes, node)
}
tree.InsertOrdered(key1, fourtyKeyTest, saveNode)
tree.InsertOrdered(key2, fourtyKeyTest, saveNode)
tree.InsertOrdered(key3, fourtyKeyTest, saveNode)
tree.ComputeCommitment()

var called bool
err := tree.Delete(key2, func(comm []byte) ([]byte, error) {
called = true
for _, node := range savedNodes {
c := node.ComputeCommitment().Bytes()
if bytes.Equal(comm, c[:]) {
return node.Serialize()
}
}
t.Fatal("could not find node")
return nil, fmt.Errorf("node not found")
})
if !called {
t.Fatal("should have called the resolve function")
}
if err != nil {
t.Fatalf("error deleting key: %v", err)
}
}

func TestConcurrentTrees(t *testing.T) {
tree := New()
Expand Down

0 comments on commit 4e4c3f6

Please sign in to comment.