From e3676d934e4bc404e3768fd83515b5aedac89228 Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Tue, 18 Oct 2022 07:35:02 +0000 Subject: [PATCH 1/3] chore(lib/trie): add `internal/trie/tracking` --- internal/trie/tracking/deltas.go | 56 +++ internal/trie/tracking/deltas_test.go | 182 ++++++++++ internal/trie/tracking/helpers_test.go | 37 ++ internal/trie/tracking/interfaces.go | 11 + lib/trie/database.go | 41 ++- lib/trie/helpers_test.go | 10 + lib/trie/interfaces.go | 32 ++ lib/trie/trie.go | 199 ++++++----- lib/trie/trie_endtoend_test.go | 13 +- lib/trie/trie_test.go | 449 ++++++++++++------------- 10 files changed, 686 insertions(+), 344 deletions(-) create mode 100644 internal/trie/tracking/deltas.go create mode 100644 internal/trie/tracking/deltas_test.go create mode 100644 internal/trie/tracking/helpers_test.go create mode 100644 internal/trie/tracking/interfaces.go create mode 100644 lib/trie/interfaces.go diff --git a/internal/trie/tracking/deltas.go b/internal/trie/tracking/deltas.go new file mode 100644 index 0000000000..4e80e37a20 --- /dev/null +++ b/internal/trie/tracking/deltas.go @@ -0,0 +1,56 @@ +// Copyright 2022 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + +package tracking + +import "github.com/ChainSafe/gossamer/lib/common" + +// Deltas tracks the trie deltas, for example deleted node hashes. +type Deltas struct { + deletedNodeHashes map[common.Hash]struct{} +} + +// New returns a new Deltas struct. +func New() *Deltas { + return &Deltas{ + deletedNodeHashes: make(map[common.Hash]struct{}), + } +} + +// RecordDeleted records a node hash as deleted. +func (d *Deltas) RecordDeleted(nodeHash common.Hash) { + d.deletedNodeHashes[nodeHash] = struct{}{} +} + +// Deleted returns a set (map) of all the recorded deleted +// node hashes. Note the map returned is not deep copied for +// performance reasons and so it's not safe for mutation. +func (d *Deltas) Deleted() (nodeHashes map[common.Hash]struct{}) { + return d.deletedNodeHashes +} + +// MergeWith merges the deltas given as argument in the receiving +// deltas struct. +func (d *Deltas) MergeWith(deltas DeletedGetter) { + for nodeHash := range deltas.Deleted() { + d.RecordDeleted(nodeHash) + } +} + +// DeepCopy returns a deep copy of the deltas. +func (d *Deltas) DeepCopy() (deepCopy *Deltas) { + if d == nil { + return nil + } + + deepCopy = &Deltas{} + + if d.deletedNodeHashes != nil { + deepCopy.deletedNodeHashes = make(map[common.Hash]struct{}, len(d.deletedNodeHashes)) + for nodeHash := range d.deletedNodeHashes { + deepCopy.deletedNodeHashes[nodeHash] = struct{}{} + } + } + + return deepCopy +} diff --git a/internal/trie/tracking/deltas_test.go b/internal/trie/tracking/deltas_test.go new file mode 100644 index 0000000000..59885dfac8 --- /dev/null +++ b/internal/trie/tracking/deltas_test.go @@ -0,0 +1,182 @@ +// Copyright 2022 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + +package tracking + +import ( + "testing" + + "github.com/ChainSafe/gossamer/lib/common" + "github.com/stretchr/testify/assert" +) + +func Test_New(t *testing.T) { + t.Parallel() + + deltas := New() + + expectedDeltas := &Deltas{ + deletedNodeHashes: make(map[common.Hash]struct{}), + } + assert.Equal(t, expectedDeltas, deltas) +} + +func Test_Deltas_RecordDeleted(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + deltas Deltas + nodeHash common.Hash + expectedDeltas Deltas + }{ + "set in empty deltas": { + deltas: Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{}, + }, + nodeHash: common.Hash{1}, + expectedDeltas: Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, + }, + }, + "set in non empty deltas": { + deltas: Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, + }, + nodeHash: common.Hash{2}, + expectedDeltas: Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{ + {1}: {}, {2}: {}, + }, + }, + }, + "override in deltas": { + deltas: Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, + }, + nodeHash: common.Hash{1}, + expectedDeltas: Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, + }, + }, + } + + for name, testCase := range testCases { + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + testCase.deltas.RecordDeleted(testCase.nodeHash) + assert.Equal(t, testCase.expectedDeltas, testCase.deltas) + }) + } +} + +func Test_Deltas_Deleted(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + deltas Deltas + nodeHashes map[common.Hash]struct{} + }{ + "empty deltas": {}, + "non empty deltas": { + deltas: Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, + }, + nodeHashes: map[common.Hash]struct{}{{1}: {}}, + }, + } + + for name, testCase := range testCases { + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + nodeHashes := testCase.deltas.Deleted() + assert.Equal(t, testCase.nodeHashes, nodeHashes) + }) + } +} + +func Test_Deltas_MergeWith(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + deltas Deltas + deltasArg DeletedGetter + expectedDeltas Deltas + }{ + "merge empty deltas": { + deltas: Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, + }, + deltasArg: &Deltas{}, + expectedDeltas: Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, + }, + }, + "merge deltas": { + deltas: Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, + }, + deltasArg: &Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{ + {1}: {}, {2}: {}, + }, + }, + expectedDeltas: Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{ + {1}: {}, {2}: {}, + }, + }, + }, + } + + for name, testCase := range testCases { + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + testCase.deltas.MergeWith(testCase.deltasArg) + assert.Equal(t, testCase.expectedDeltas, testCase.deltas) + }) + } +} + +func Test_Deltas_DeepCopy(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + deltasOriginal *Deltas + deltasCopy *Deltas + }{ + "nil deltas": {}, + "empty deltas": { + deltasOriginal: &Deltas{}, + deltasCopy: &Deltas{}, + }, + "filled deltas": { + deltasOriginal: &Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, + }, + deltasCopy: &Deltas{ + deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, + }, + }, + } + + for name, testCase := range testCases { + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + deepCopy := testCase.deltasOriginal.DeepCopy() + + assert.Equal(t, testCase.deltasCopy, deepCopy) + assertPointersNotEqual(t, testCase.deltasOriginal, deepCopy) + if testCase.deltasOriginal != nil { + assertPointersNotEqual(t, testCase.deltasOriginal.deletedNodeHashes, deepCopy.deletedNodeHashes) + } + }) + } +} diff --git a/internal/trie/tracking/helpers_test.go b/internal/trie/tracking/helpers_test.go new file mode 100644 index 0000000000..d4318aa1ab --- /dev/null +++ b/internal/trie/tracking/helpers_test.go @@ -0,0 +1,37 @@ +// Copyright 2022 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + +package tracking + +import ( + "reflect" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func getPointer(x interface{}) (pointer uintptr, ok bool) { + func() { + defer func() { + ok = recover() == nil + }() + valueOfX := reflect.ValueOf(x) + pointer = valueOfX.Pointer() + }() + return pointer, ok +} + +func assertPointersNotEqual(t *testing.T, a, b interface{}) { + t.Helper() + pointerA, okA := getPointer(a) + pointerB, okB := getPointer(b) + require.Equal(t, okA, okB) + + switch { + case pointerA == 0 && pointerB == 0: // nil and nil + case okA: + assert.NotEqual(t, pointerA, pointerB) + default: // values like `int` + } +} diff --git a/internal/trie/tracking/interfaces.go b/internal/trie/tracking/interfaces.go new file mode 100644 index 0000000000..0e4ea324fd --- /dev/null +++ b/internal/trie/tracking/interfaces.go @@ -0,0 +1,11 @@ +// Copyright 2022 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + +package tracking + +import "github.com/ChainSafe/gossamer/lib/common" + +// DeletedGetter gets deleted node hashes. +type DeletedGetter interface { + Deleted() (nodeHashes map[common.Hash]struct{}) +} diff --git a/lib/trie/database.go b/lib/trie/database.go index 4d867aad65..1b0717c89e 100644 --- a/lib/trie/database.go +++ b/lib/trie/database.go @@ -160,6 +160,37 @@ func PopulateNodeHashes(n *Node, nodeHashes map[string]struct{}) { } } +// recordAllDeleted records the node hashes of the given node and all its descendants. +// Note it does not record inlined nodes. +// It is assumed the node and its descendant nodes have their Merkle value already +// computed, or the function will panic. +func recordAllDeleted(n *Node, recorder DeltaRecorder) { + if n == nil { + return + } + + if len(n.MerkleValue) == 0 { + panic(fmt.Sprintf("node with key 0x%x has no Merkle value computed", n.PartialKey)) + } + + isInlined := len(n.MerkleValue) < 32 + if isInlined { + return + } + + nodeHash := common.NewHash(n.MerkleValue) + recorder.RecordDeleted(nodeHash) + + if n.Kind() == node.Leaf { + return + } + + branch := n + for _, child := range branch.Children { + recordAllDeleted(child, recorder) + } +} + // GetFromDB retrieves a value at the given key from the trie using the database. // It recursively descends into the trie using the database starting // from the root node until it reaches the node with the given key. @@ -316,12 +347,14 @@ func (t *Trie) GetChangedNodeHashes() (inserted, deleted map[string]struct{}, er inserted = make(map[string]struct{}) err = t.getInsertedNodeHashesAtNode(t.root, inserted) if err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("getting inserted node hashes: %w", err) } - deleted = make(map[string]struct{}, len(t.deletedMerkleValues)) - for k := range t.deletedMerkleValues { - deleted[k] = struct{}{} + deletedNodeHashes := t.deltas.Deleted() + // TODO return deletedNodeHashes directly after changing MerkleValue -> NodeHash + deleted = make(map[string]struct{}, len(deletedNodeHashes)) + for nodeHash := range deletedNodeHashes { + deleted[string(nodeHash[:])] = struct{}{} } return inserted, deleted, nil diff --git a/lib/trie/helpers_test.go b/lib/trie/helpers_test.go index 36a0e5321e..961e85163e 100644 --- a/lib/trie/helpers_test.go +++ b/lib/trie/helpers_test.go @@ -9,6 +9,8 @@ import ( "time" "github.com/ChainSafe/gossamer/internal/trie/node" + "github.com/ChainSafe/gossamer/internal/trie/tracking" + "github.com/ChainSafe/gossamer/lib/common" "github.com/stretchr/testify/require" ) @@ -135,3 +137,11 @@ func checkMerkleValuesAreSet(t *testing.T, n *Node) { checkMerkleValuesAreSet(t, child) } } + +func newDeltas(deleted []common.Hash) (deltas *tracking.Deltas) { + deltas = tracking.New() + for _, hash := range deleted { + deltas.RecordDeleted(hash) + } + return deltas +} diff --git a/lib/trie/interfaces.go b/lib/trie/interfaces.go new file mode 100644 index 0000000000..452b46dbcc --- /dev/null +++ b/lib/trie/interfaces.go @@ -0,0 +1,32 @@ +// Copyright 2022 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + +package trie + +import ( + "github.com/ChainSafe/gossamer/internal/trie/tracking" + "github.com/ChainSafe/gossamer/lib/common" +) + +// Deltas is the interface for the trie local deltas since +// the last snapshot. +type Deltas interface { + DeltaMerger + DeltaDeletedGetter +} + +// DeltaMerger merges the given deltas into the current +// deltas. +type DeltaMerger interface { + MergeWith(deltas tracking.DeletedGetter) +} + +// DeltaDeletedGetter returns the deleted node hashes recorded so far. +type DeltaDeletedGetter interface { + Deleted() (nodeHashes map[common.Hash]struct{}) +} + +// DeltaRecorder records deltas done in a ongoing trie operation. +type DeltaRecorder interface { + RecordDeleted(nodeHash common.Hash) +} diff --git a/lib/trie/trie.go b/lib/trie/trie.go index 742e0e110c..ad4502bbe7 100644 --- a/lib/trie/trie.go +++ b/lib/trie/trie.go @@ -9,6 +9,7 @@ import ( "github.com/ChainSafe/gossamer/internal/trie/codec" "github.com/ChainSafe/gossamer/internal/trie/node" + "github.com/ChainSafe/gossamer/internal/trie/tracking" "github.com/ChainSafe/gossamer/lib/common" ) @@ -20,11 +21,12 @@ type Trie struct { generation uint64 root *Node childTries map[common.Hash]*Trie - // deletedMerkleValues are the node Merkle values that were deleted - // from this trie since the last snapshot. These are used by the online - // pruner to detect with database keys (trie node Merkle values) can + // deltas stores trie deltas since the last trie snapshot. + // For example node hashes that were deleted since + // the last snapshot. These are used by the online + // pruner to detect with database keys (trie node hashes) can // be deleted. - deletedMerkleValues map[string]struct{} + deltas Deltas } // NewEmptyTrie creates a trie with a nil root @@ -35,10 +37,10 @@ func NewEmptyTrie() *Trie { // NewTrie creates a trie with an existing root node func NewTrie(root *Node) *Trie { return &Trie{ - root: root, - childTries: make(map[common.Hash]*Trie), - generation: 0, // Initially zero but increases after every snapshot. - deletedMerkleValues: make(map[string]struct{}), + root: root, + childTries: make(map[common.Hash]*Trie), + generation: 0, // Initially zero but increases after every snapshot. + deltas: tracking.New(), } } @@ -53,45 +55,42 @@ func (t *Trie) Snapshot() (newTrie *Trie) { rootCopySettings.CopyMerkleValue = true for rootHash, childTrie := range t.childTries { childTries[rootHash] = &Trie{ - generation: childTrie.generation + 1, - root: childTrie.root.Copy(rootCopySettings), - deletedMerkleValues: make(map[string]struct{}), + generation: childTrie.generation + 1, + root: childTrie.root.Copy(rootCopySettings), + deltas: tracking.New(), } } return &Trie{ - generation: t.generation + 1, - root: t.root, - childTries: childTries, - deletedMerkleValues: make(map[string]struct{}), + generation: t.generation + 1, + root: t.root, + childTries: childTries, + deltas: tracking.New(), } } // handleTrackedDeltas sets the pending deleted Merkle values in // the trie deleted merkle values set if and only if success is true. -func (t *Trie) handleTrackedDeltas(success bool, pendingDeletedMerkleValues map[string]struct{}) { +func (t *Trie) handleTrackedDeltas(success bool, pendingDeltas DeltaDeletedGetter) { if !success || t.generation == 0 { // Do not persist tracked deleted node hashes if the operation failed or // if the trie generation is zero (first block, no trie snapshot done yet). return } - for merkleValue := range pendingDeletedMerkleValues { - t.deletedMerkleValues[merkleValue] = struct{}{} - } + t.deltas.MergeWith(pendingDeltas) } func (t *Trie) prepForMutation(currentNode *Node, copySettings node.CopySettings, - pendingDeletedMerkleValues map[string]struct{}) ( + pendingDeltas DeltaRecorder) ( newNode *Node, err error) { if currentNode.Generation == t.generation { // no need to track deleted node, deep copy the node and // update the node generation. newNode = currentNode } else { - err = t.registerDeletedMerkleValue(currentNode, - pendingDeletedMerkleValues) + err = t.registerDeletedMerkleValue(currentNode, pendingDeltas) if err != nil { return nil, fmt.Errorf("registering deleted node: %w", err) } @@ -103,7 +102,7 @@ func (t *Trie) prepForMutation(currentNode *Node, } func (t *Trie) registerDeletedMerkleValue(node *Node, - pendingDeletedMerkleValues map[string]struct{}) (err error) { + pendingDeltas DeltaRecorder) (err error) { err = t.ensureMerkleValueIsCalculated(node) if err != nil { return fmt.Errorf("ensuring Merkle value is calculated: %w", err) @@ -119,7 +118,8 @@ func (t *Trie) registerDeletedMerkleValue(node *Node, if !node.Dirty { // Only register deleted nodes that were not previously modified // since the last trie snapshot. - pendingDeletedMerkleValues[string(node.MerkleValue)] = struct{}{} + nodeHash := common.NewHash(node.MerkleValue) + pendingDeltas.RecordDeleted(nodeHash) } return nil @@ -139,11 +139,10 @@ func (t *Trie) DeepCopy() (trieCopy *Trie) { generation: t.generation, } - if t.deletedMerkleValues != nil { - trieCopy.deletedMerkleValues = make(map[string]struct{}, len(t.deletedMerkleValues)) - for k := range t.deletedMerkleValues { - trieCopy.deletedMerkleValues[k] = struct{}{} - } + if t.deltas != nil { + // Because DeepCopy() is only used in tests (in this and other packages), + // it's fine to type assert deltas to access its DeepCopy method. + trieCopy.deltas = t.deltas.(*tracking.Deltas).DeepCopy() } if t.childTries != nil { @@ -321,23 +320,23 @@ func findNextKeyChild(children []*Node, startIndex byte, // Put inserts a value into the trie at the // key specified in little Endian format. func (t *Trie) Put(keyLE, value []byte) (err error) { - pendingDeletedMerkleValues := make(map[string]struct{}) + pendingDeltas := tracking.New() defer func() { const success = true - t.handleTrackedDeltas(success, pendingDeletedMerkleValues) + t.handleTrackedDeltas(success, pendingDeltas) }() - return t.insertKeyLE(keyLE, value, pendingDeletedMerkleValues) + return t.insertKeyLE(keyLE, value, pendingDeltas) } func (t *Trie) insertKeyLE(keyLE, value []byte, - deletedMerkleValues map[string]struct{}) (err error) { + pendingDeltas DeltaRecorder) (err error) { nibblesKey := codec.KeyLEToNibbles(keyLE) if value == nil { // Force nil value to be inserted to []byte{} since `nil` means there // is no value. value = []byte{} } - root, _, _, err := t.insert(t.root, nibblesKey, value, deletedMerkleValues) + root, _, _, err := t.insert(t.root, nibblesKey, value, pendingDeltas) if err != nil { return err } @@ -348,7 +347,7 @@ func (t *Trie) insertKeyLE(keyLE, value []byte, // insert inserts a value in the trie at the key specified. // It may create one or more new nodes or update an existing node. func (t *Trie) insert(parent *Node, key, value []byte, - deletedMerkleValues map[string]struct{}) (newParent *Node, + pendingDeltas DeltaRecorder) (newParent *Node, mutated bool, nodesCreated uint32, err error) { if parent == nil { mutated = true @@ -363,7 +362,7 @@ func (t *Trie) insert(parent *Node, key, value []byte, if parent.Kind() == node.Branch { newParent, mutated, nodesCreated, err = t.insertInBranch( - parent, key, value, deletedMerkleValues) + parent, key, value, pendingDeltas) if err != nil { // `insertInBranch` may call `insert` so do not wrap the // error since this may be a deep recursive call. @@ -373,7 +372,7 @@ func (t *Trie) insert(parent *Node, key, value []byte, } newParent, mutated, nodesCreated, err = t.insertInLeaf( - parent, key, value, deletedMerkleValues) + parent, key, value, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("inserting in leaf: %w", err) } @@ -382,7 +381,7 @@ func (t *Trie) insert(parent *Node, key, value []byte, } func (t *Trie) insertInLeaf(parentLeaf *Node, key, value []byte, - deletedMerkleValues map[string]struct{}) ( + pendingDeltas DeltaRecorder) ( newParent *Node, mutated bool, nodesCreated uint32, err error) { if bytes.Equal(parentLeaf.PartialKey, key) { nodesCreated = 0 @@ -393,7 +392,7 @@ func (t *Trie) insertInLeaf(parentLeaf *Node, key, value []byte, copySettings := node.DefaultCopySettings copySettings.CopyStorageValue = false - parentLeaf, err = t.prepForMutation(parentLeaf, copySettings, deletedMerkleValues) + parentLeaf, err = t.prepForMutation(parentLeaf, copySettings, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("preparing leaf for mutation: %w", err) } @@ -425,7 +424,7 @@ func (t *Trie) insertInLeaf(parentLeaf *Node, key, value []byte, childIndex := parentLeafKey[commonPrefixLength] newParentLeafKey := parentLeaf.PartialKey[commonPrefixLength+1:] if !bytes.Equal(parentLeaf.PartialKey, newParentLeafKey) { - parentLeaf, err = t.prepForMutation(parentLeaf, copySettings, deletedMerkleValues) + parentLeaf, err = t.prepForMutation(parentLeaf, copySettings, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("preparing leaf for mutation: %w", err) } @@ -448,7 +447,7 @@ func (t *Trie) insertInLeaf(parentLeaf *Node, key, value []byte, childIndex := parentLeafKey[commonPrefixLength] newParentLeafKey := parentLeaf.PartialKey[commonPrefixLength+1:] if !bytes.Equal(parentLeaf.PartialKey, newParentLeafKey) { - parentLeaf, err = t.prepForMutation(parentLeaf, copySettings, deletedMerkleValues) + parentLeaf, err = t.prepForMutation(parentLeaf, copySettings, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("preparing leaf for mutation: %w", err) } @@ -472,7 +471,7 @@ func (t *Trie) insertInLeaf(parentLeaf *Node, key, value []byte, } func (t *Trie) insertInBranch(parentBranch *Node, key, value []byte, - deletedMerkleValues map[string]struct{}) ( + pendingDeltas DeltaRecorder) ( newParent *Node, mutated bool, nodesCreated uint32, err error) { copySettings := node.DefaultCopySettings @@ -481,7 +480,7 @@ func (t *Trie) insertInBranch(parentBranch *Node, key, value []byte, mutated = false return parentBranch, mutated, 0, nil } - parentBranch, err = t.prepForMutation(parentBranch, copySettings, deletedMerkleValues) + parentBranch, err = t.prepForMutation(parentBranch, copySettings, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("preparing branch for mutation: %w", err) } @@ -505,7 +504,7 @@ func (t *Trie) insertInBranch(parentBranch *Node, key, value []byte, Dirty: true, } nodesCreated = 1 - parentBranch, err = t.prepForMutation(parentBranch, copySettings, deletedMerkleValues) + parentBranch, err = t.prepForMutation(parentBranch, copySettings, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("preparing branch for mutation: %w", err) } @@ -515,7 +514,7 @@ func (t *Trie) insertInBranch(parentBranch *Node, key, value []byte, return parentBranch, mutated, nodesCreated, nil } - child, mutated, nodesCreated, err = t.insert(child, remainingKey, value, deletedMerkleValues) + child, mutated, nodesCreated, err = t.insert(child, remainingKey, value, pendingDeltas) if err != nil { // do not wrap error since `insert` may call `insertInBranch` recursively return nil, false, 0, err @@ -523,7 +522,7 @@ func (t *Trie) insertInBranch(parentBranch *Node, key, value []byte, return parentBranch, mutated, 0, nil } - parentBranch, err = t.prepForMutation(parentBranch, copySettings, deletedMerkleValues) + parentBranch, err = t.prepForMutation(parentBranch, copySettings, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("preparing branch for mutation: %w", err) } @@ -549,7 +548,7 @@ func (t *Trie) insertInBranch(parentBranch *Node, key, value []byte, remainingOldParentKey := parentBranch.PartialKey[commonPrefixLength+1:] // Note: parentBranch.PartialKey != remainingOldParentKey - parentBranch, err = t.prepForMutation(parentBranch, copySettings, deletedMerkleValues) + parentBranch, err = t.prepForMutation(parentBranch, copySettings, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("preparing branch for mutation: %w", err) } @@ -565,7 +564,7 @@ func (t *Trie) insertInBranch(parentBranch *Node, key, value []byte, remainingKey := key[commonPrefixLength+1:] var additionalNodesCreated uint32 newParentBranch.Children[childIndex], _, additionalNodesCreated, err = t.insert( - nil, remainingKey, value, deletedMerkleValues) + nil, remainingKey, value, pendingDeltas) if err != nil { // do not wrap error since `insert` may call `insertInBranch` recursively return nil, false, 0, err @@ -584,9 +583,9 @@ func (t *Trie) insertInBranch(parentBranch *Node, key, value []byte, func LoadFromMap(data map[string]string) (trie Trie, err error) { trie = *NewEmptyTrie() - pendingDeletedMerkleValues := make(map[string]struct{}) + pendingDeltas := tracking.New() defer func() { - trie.handleTrackedDeltas(err == nil, pendingDeletedMerkleValues) + trie.handleTrackedDeltas(err == nil, pendingDeltas) }() for key, value := range data { @@ -600,7 +599,7 @@ func LoadFromMap(data map[string]string) (trie Trie, err error) { return Trie{}, fmt.Errorf("cannot convert value hex to bytes: %w", err) } - err = trie.insertKeyLE(keyLEBytes, valueBytes, pendingDeletedMerkleValues) + err = trie.insertKeyLE(keyLEBytes, valueBytes, pendingDeltas) if err != nil { return Trie{}, fmt.Errorf("inserting key value pair in trie: %w", err) } @@ -759,10 +758,10 @@ func retrieveFromBranch(branch *Node, key []byte) (value []byte) { // within the limit. func (t *Trie) ClearPrefixLimit(prefixLE []byte, limit uint32) ( deleted uint32, allDeleted bool, err error) { - pendingDeletedMerkleValues := make(map[string]struct{}) + pendingDeltas := tracking.New() defer func() { const success = true - t.handleTrackedDeltas(success, pendingDeletedMerkleValues) + t.handleTrackedDeltas(success, pendingDeltas) }() if limit == 0 { @@ -773,7 +772,7 @@ func (t *Trie) ClearPrefixLimit(prefixLE []byte, limit uint32) ( prefix = bytes.TrimSuffix(prefix, []byte{0}) root, deleted, _, allDeleted, err := t.clearPrefixLimitAtNode( - t.root, prefix, limit, pendingDeletedMerkleValues) + t.root, prefix, limit, pendingDeltas) if err != nil { return 0, false, err } @@ -786,7 +785,7 @@ func (t *Trie) ClearPrefixLimit(prefixLE []byte, limit uint32) ( // It returns the updated node newParent, the number of deleted values valuesDeleted and the // allDeleted boolean indicating if there is no key left with the prefix. func (t *Trie) clearPrefixLimitAtNode(parent *Node, prefix []byte, - limit uint32, deletedMerkleValues map[string]struct{}) ( + limit uint32, pendingDeltas DeltaRecorder) ( newParent *Node, valuesDeleted, nodesRemoved uint32, allDeleted bool, err error) { if parent == nil { return nil, 0, 0, true, nil @@ -797,7 +796,7 @@ func (t *Trie) clearPrefixLimitAtNode(parent *Node, prefix []byte, // TODO check this is the same behaviour as in substrate const allDeleted = true if bytes.HasPrefix(parent.PartialKey, prefix) { - err = t.registerDeletedMerkleValue(parent, deletedMerkleValues) + err = t.registerDeletedMerkleValue(parent, pendingDeltas) if err != nil { return nil, 0, 0, false, fmt.Errorf("registering deleted Merkle value: %w", err) @@ -811,17 +810,17 @@ func (t *Trie) clearPrefixLimitAtNode(parent *Node, prefix []byte, // Note: `clearPrefixLimitBranch` may call `clearPrefixLimitAtNode` so do not wrap // the error since that could be a deep recursive call. - return t.clearPrefixLimitBranch(parent, prefix, limit, deletedMerkleValues) + return t.clearPrefixLimitBranch(parent, prefix, limit, pendingDeltas) } func (t *Trie) clearPrefixLimitBranch(branch *Node, prefix []byte, limit uint32, - deletedMerkleValues map[string]struct{}) ( + pendingDeltas DeltaRecorder) ( newParent *Node, valuesDeleted, nodesRemoved uint32, allDeleted bool, err error) { newParent = branch if bytes.HasPrefix(branch.PartialKey, prefix) { newParent, valuesDeleted, nodesRemoved, err = t.deleteNodesLimit( - branch, limit, deletedMerkleValues) + branch, limit, pendingDeltas) if err != nil { return nil, 0, 0, false, fmt.Errorf("deleting nodes: %w", err) } @@ -832,7 +831,7 @@ func (t *Trie) clearPrefixLimitBranch(branch *Node, prefix []byte, limit uint32, if len(prefix) == len(branch.PartialKey)+1 && bytes.HasPrefix(branch.PartialKey, prefix[:len(prefix)-1]) { // Prefix is one the children of the branch - return t.clearPrefixLimitChild(branch, prefix, limit, deletedMerkleValues) + return t.clearPrefixLimitChild(branch, prefix, limit, pendingDeltas) } noPrefixForNode := len(prefix) <= len(branch.PartialKey) || @@ -848,7 +847,7 @@ func (t *Trie) clearPrefixLimitBranch(branch *Node, prefix []byte, limit uint32, child := branch.Children[childIndex] child, valuesDeleted, nodesRemoved, allDeleted, err = t.clearPrefixLimitAtNode( - child, childPrefix, limit, deletedMerkleValues) + child, childPrefix, limit, pendingDeltas) if err != nil { return nil, 0, 0, false, fmt.Errorf("clearing prefix limit at node: %w", err) } else if valuesDeleted == 0 { @@ -856,14 +855,14 @@ func (t *Trie) clearPrefixLimitBranch(branch *Node, prefix []byte, limit uint32, } copySettings := node.DefaultCopySettings - branch, err = t.prepForMutation(branch, copySettings, deletedMerkleValues) + branch, err = t.prepForMutation(branch, copySettings, pendingDeltas) if err != nil { return nil, 0, 0, false, fmt.Errorf("preparing branch for mutation: %w", err) } branch.Children[childIndex] = child branch.Descendants -= nodesRemoved - newParent, branchChildMerged, err := t.handleDeletion(branch, prefix, deletedMerkleValues) + newParent, branchChildMerged, err := t.handleDeletion(branch, prefix, pendingDeltas) if err != nil { return nil, 0, 0, false, fmt.Errorf("handling deletion: %w", err) } @@ -876,7 +875,7 @@ func (t *Trie) clearPrefixLimitBranch(branch *Node, prefix []byte, limit uint32, } func (t *Trie) clearPrefixLimitChild(branch *Node, prefix []byte, limit uint32, - deletedMerkleValues map[string]struct{}) ( + pendingDeltas DeltaRecorder) ( newParent *Node, valuesDeleted, nodesRemoved uint32, allDeleted bool, err error) { newParent = branch @@ -892,7 +891,7 @@ func (t *Trie) clearPrefixLimitChild(branch *Node, prefix []byte, limit uint32, } child, valuesDeleted, nodesRemoved, err = t.deleteNodesLimit( - child, limit, deletedMerkleValues) + child, limit, pendingDeltas) if err != nil { // Note: do not wrap error since this is recursive. return nil, 0, 0, false, err @@ -904,7 +903,7 @@ func (t *Trie) clearPrefixLimitChild(branch *Node, prefix []byte, limit uint32, } copySettings := node.DefaultCopySettings - branch, err = t.prepForMutation(branch, copySettings, deletedMerkleValues) + branch, err = t.prepForMutation(branch, copySettings, pendingDeltas) if err != nil { return nil, 0, 0, false, fmt.Errorf("preparing branch for mutation: %w", err) } @@ -912,7 +911,7 @@ func (t *Trie) clearPrefixLimitChild(branch *Node, prefix []byte, limit uint32, branch.Children[childIndex] = child branch.Descendants -= nodesRemoved - newParent, branchChildMerged, err := t.handleDeletion(branch, prefix, deletedMerkleValues) + newParent, branchChildMerged, err := t.handleDeletion(branch, prefix, pendingDeltas) if err != nil { return nil, 0, 0, false, fmt.Errorf("handling deletion: %w", err) } @@ -926,7 +925,7 @@ func (t *Trie) clearPrefixLimitChild(branch *Node, prefix []byte, limit uint32, } func (t *Trie) deleteNodesLimit(parent *Node, limit uint32, - deletedMerkleValues map[string]struct{}) ( + pendingDeltas DeltaRecorder) ( newParent *Node, valuesDeleted, nodesRemoved uint32, err error) { if limit == 0 { valuesDeleted, nodesRemoved = 0, 0 @@ -939,7 +938,7 @@ func (t *Trie) deleteNodesLimit(parent *Node, limit uint32, } if parent.Kind() == node.Leaf { - err = t.registerDeletedMerkleValue(parent, deletedMerkleValues) + err = t.registerDeletedMerkleValue(parent, pendingDeltas) if err != nil { return nil, 0, 0, fmt.Errorf("registering deleted merkle value: %w", err) } @@ -957,7 +956,7 @@ func (t *Trie) deleteNodesLimit(parent *Node, limit uint32, // Note: there is at least one non-nil child and the limit isn't zero, // therefore it is safe to prepare the branch for mutation. copySettings := node.DefaultCopySettings - branch, err = t.prepForMutation(branch, copySettings, deletedMerkleValues) + branch, err = t.prepForMutation(branch, copySettings, pendingDeltas) if err != nil { return nil, 0, 0, fmt.Errorf("preparing branch for mutation: %w", err) } @@ -970,7 +969,7 @@ func (t *Trie) deleteNodesLimit(parent *Node, limit uint32, } branch.Children[i], newDeleted, newNodesRemoved, err = t.deleteNodesLimit( - child, limit, deletedMerkleValues) + child, limit, pendingDeltas) if err != nil { // `deleteNodesLimit` is recursive, so do not wrap error. return nil, 0, 0, err @@ -984,7 +983,7 @@ func (t *Trie) deleteNodesLimit(parent *Node, limit uint32, nodesRemoved += newNodesRemoved branch.Descendants -= newNodesRemoved - newParent, branchChildMerged, err = t.handleDeletion(branch, branch.PartialKey, deletedMerkleValues) + newParent, branchChildMerged, err = t.handleDeletion(branch, branch.PartialKey, pendingDeltas) if err != nil { return nil, 0, 0, fmt.Errorf("handling deletion: %w", err) } @@ -1014,10 +1013,10 @@ func (t *Trie) deleteNodesLimit(parent *Node, limit uint32, // ClearPrefix deletes all nodes in the trie for which the key contains the // prefix given in little Endian format. func (t *Trie) ClearPrefix(prefixLE []byte) (err error) { - pendingDeletedMerkleValues := make(map[string]struct{}) + pendingDeltas := tracking.New() defer func() { const success = true - t.handleTrackedDeltas(success, pendingDeletedMerkleValues) + t.handleTrackedDeltas(success, pendingDeltas) }() if len(prefixLE) == 0 { @@ -1026,7 +1025,7 @@ func (t *Trie) ClearPrefix(prefixLE []byte) (err error) { return fmt.Errorf("ensuring Merkle values are calculated: %w", err) } - PopulateNodeHashes(t.root, pendingDeletedMerkleValues) + recordAllDeleted(t.root, pendingDeltas) t.root = nil return nil } @@ -1034,7 +1033,7 @@ func (t *Trie) ClearPrefix(prefixLE []byte) (err error) { prefix := codec.KeyLEToNibbles(prefixLE) prefix = bytes.TrimSuffix(prefix, []byte{0}) - root, _, err := t.clearPrefixAtNode(t.root, prefix, pendingDeletedMerkleValues) + root, _, err := t.clearPrefixAtNode(t.root, prefix, pendingDeltas) if err != nil { return fmt.Errorf("clearing prefix at root node: %w", err) } @@ -1044,7 +1043,7 @@ func (t *Trie) ClearPrefix(prefixLE []byte) (err error) { } func (t *Trie) clearPrefixAtNode(parent *Node, prefix []byte, - deletedMerkleValues map[string]struct{}) ( + pendingDeltas DeltaRecorder) ( newParent *Node, nodesRemoved uint32, err error) { if parent == nil { const nodesRemoved = 0 @@ -1058,7 +1057,7 @@ func (t *Trie) clearPrefixAtNode(parent *Node, prefix []byte, return parent, nodesRemoved, fmt.Errorf("ensuring Merkle values are calculated: %w", err) } - PopulateNodeHashes(parent, deletedMerkleValues) + recordAllDeleted(parent, pendingDeltas) nodesRemoved = 1 + parent.Descendants return nil, nodesRemoved, nil } @@ -1082,12 +1081,12 @@ func (t *Trie) clearPrefixAtNode(parent *Node, prefix []byte, nodesRemoved = 1 + child.Descendants copySettings := node.DefaultCopySettings - branch, err = t.prepForMutation(branch, copySettings, deletedMerkleValues) + branch, err = t.prepForMutation(branch, copySettings, pendingDeltas) if err != nil { return nil, 0, fmt.Errorf("preparing branch for mutation: %w", err) } - err = t.registerDeletedMerkleValue(child, deletedMerkleValues) + err = t.registerDeletedMerkleValue(child, pendingDeltas) if err != nil { return nil, 0, fmt.Errorf("registering deleted merkle value for child: %w", err) } @@ -1095,7 +1094,7 @@ func (t *Trie) clearPrefixAtNode(parent *Node, prefix []byte, branch.Children[childIndex] = nil branch.Descendants -= nodesRemoved var branchChildMerged bool - newParent, branchChildMerged, err = t.handleDeletion(branch, prefix, deletedMerkleValues) + newParent, branchChildMerged, err = t.handleDeletion(branch, prefix, pendingDeltas) if err != nil { return nil, 0, fmt.Errorf("handling deletion: %w", err) } @@ -1117,7 +1116,7 @@ func (t *Trie) clearPrefixAtNode(parent *Node, prefix []byte, childPrefix := prefix[len(branch.PartialKey)+1:] child := branch.Children[childIndex] - child, nodesRemoved, err = t.clearPrefixAtNode(child, childPrefix, deletedMerkleValues) + child, nodesRemoved, err = t.clearPrefixAtNode(child, childPrefix, pendingDeltas) if err != nil { nodesRemoved = 0 // Note: do not wrap error since this is recursive @@ -1127,14 +1126,14 @@ func (t *Trie) clearPrefixAtNode(parent *Node, prefix []byte, } copySettings := node.DefaultCopySettings - branch, err = t.prepForMutation(branch, copySettings, deletedMerkleValues) + branch, err = t.prepForMutation(branch, copySettings, pendingDeltas) if err != nil { return nil, 0, fmt.Errorf("preparing branch for mutation: %w", err) } branch.Descendants -= nodesRemoved branch.Children[childIndex] = child - newParent, branchChildMerged, err := t.handleDeletion(branch, prefix, deletedMerkleValues) + newParent, branchChildMerged, err := t.handleDeletion(branch, prefix, pendingDeltas) if err != nil { return nil, 0, fmt.Errorf("handling deletion: %w", err) } @@ -1150,14 +1149,14 @@ func (t *Trie) clearPrefixAtNode(parent *Node, prefix []byte, // matching the key given in little Endian format. // If no node is found at this key, nothing is deleted. func (t *Trie) Delete(keyLE []byte) (err error) { - pendingDeletedMerkleValues := make(map[string]struct{}) + pendingDeltas := tracking.New() defer func() { const success = true - t.handleTrackedDeltas(success, pendingDeletedMerkleValues) + t.handleTrackedDeltas(success, pendingDeltas) }() key := codec.KeyLEToNibbles(keyLE) - root, _, _, err := t.deleteAtNode(t.root, key, pendingDeletedMerkleValues) + root, _, _, err := t.deleteAtNode(t.root, key, pendingDeltas) if err != nil { return fmt.Errorf("deleting key %x: %w", keyLE, err) } @@ -1166,7 +1165,7 @@ func (t *Trie) Delete(keyLE []byte) (err error) { } func (t *Trie) deleteAtNode(parent *Node, key []byte, - deletedMerkleValues map[string]struct{}) ( + pendingDeltas DeltaRecorder) ( newParent *Node, deleted bool, nodesRemoved uint32, err error) { if parent == nil { const nodesRemoved = 0 @@ -1174,7 +1173,7 @@ func (t *Trie) deleteAtNode(parent *Node, key []byte, } if parent.Kind() == node.Leaf { - newParent, err = t.deleteLeaf(parent, key, deletedMerkleValues) + newParent, err = t.deleteLeaf(parent, key, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("deleting leaf: %w", err) } @@ -1187,7 +1186,7 @@ func (t *Trie) deleteAtNode(parent *Node, key []byte, return parent, false, nodesRemoved, nil } - newParent, deleted, nodesRemoved, err = t.deleteBranch(parent, key, deletedMerkleValues) + newParent, deleted, nodesRemoved, err = t.deleteBranch(parent, key, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("deleting branch: %w", err) } @@ -1196,7 +1195,7 @@ func (t *Trie) deleteAtNode(parent *Node, key []byte, } func (t *Trie) deleteLeaf(parent *Node, key []byte, - deletedMerkleValues map[string]struct{}) ( + pendingDeltas DeltaRecorder) ( newParent *Node, err error) { if len(key) > 0 && !bytes.Equal(key, parent.PartialKey) { return parent, nil @@ -1204,7 +1203,7 @@ func (t *Trie) deleteLeaf(parent *Node, key []byte, newParent = nil - err = t.registerDeletedMerkleValue(parent, deletedMerkleValues) + err = t.registerDeletedMerkleValue(parent, pendingDeltas) if err != nil { return nil, fmt.Errorf("registering deleted merkle value: %w", err) } @@ -1213,12 +1212,12 @@ func (t *Trie) deleteLeaf(parent *Node, key []byte, } func (t *Trie) deleteBranch(branch *Node, key []byte, - deletedMerkleValues map[string]struct{}) ( + pendingDeltas DeltaRecorder) ( newParent *Node, deleted bool, nodesRemoved uint32, err error) { if len(key) == 0 || bytes.Equal(branch.PartialKey, key) { copySettings := node.DefaultCopySettings copySettings.CopyStorageValue = false - branch, err = t.prepForMutation(branch, copySettings, deletedMerkleValues) + branch, err = t.prepForMutation(branch, copySettings, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("preparing branch for mutation: %w", err) } @@ -1228,7 +1227,7 @@ func (t *Trie) deleteBranch(branch *Node, key []byte, branch.StorageValue = nil deleted = true var branchChildMerged bool - newParent, branchChildMerged, err = t.handleDeletion(branch, key, deletedMerkleValues) + newParent, branchChildMerged, err = t.handleDeletion(branch, key, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("handling deletion: %w", err) } @@ -1248,7 +1247,7 @@ func (t *Trie) deleteBranch(branch *Node, key []byte, childKey := key[commonPrefixLength+1:] child := branch.Children[childIndex] - newChild, deleted, nodesRemoved, err := t.deleteAtNode(child, childKey, deletedMerkleValues) + newChild, deleted, nodesRemoved, err := t.deleteAtNode(child, childKey, pendingDeltas) if err != nil { // deleteAtNode may call deleteBranch so don't wrap the error // since this may be a recursive call. @@ -1261,7 +1260,7 @@ func (t *Trie) deleteBranch(branch *Node, key []byte, } copySettings := node.DefaultCopySettings - branch, err = t.prepForMutation(branch, copySettings, deletedMerkleValues) + branch, err = t.prepForMutation(branch, copySettings, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("preparing branch for mutation: %w", err) } @@ -1269,7 +1268,7 @@ func (t *Trie) deleteBranch(branch *Node, key []byte, branch.Descendants -= nodesRemoved branch.Children[childIndex] = newChild - newParent, branchChildMerged, err := t.handleDeletion(branch, key, deletedMerkleValues) + newParent, branchChildMerged, err := t.handleDeletion(branch, key, pendingDeltas) if err != nil { return nil, false, 0, fmt.Errorf("handling deletion: %w", err) } @@ -1288,7 +1287,7 @@ func (t *Trie) deleteBranch(branch *Node, key []byte, // of one node in callers. // If the branch has a value and no child, it will be changed into a leaf. func (t *Trie) handleDeletion(branch *Node, key []byte, - deletedMerkleValues map[string]struct{}) ( + pendingDeltas DeltaRecorder) ( newNode *Node, branchChildMerged bool, err error) { childrenCount := 0 firstChildIndex := -1 @@ -1325,7 +1324,7 @@ func (t *Trie) handleDeletion(branch *Node, key []byte, const branchChildMerged = true childIndex := firstChildIndex child := branch.Children[firstChildIndex] - err = t.registerDeletedMerkleValue(child, deletedMerkleValues) + err = t.registerDeletedMerkleValue(child, pendingDeltas) if err != nil { return nil, false, fmt.Errorf("registering deleted merkle value: %w", err) } diff --git a/lib/trie/trie_endtoend_test.go b/lib/trie/trie_endtoend_test.go index 7754787484..f05ab19211 100644 --- a/lib/trie/trie_endtoend_test.go +++ b/lib/trie/trie_endtoend_test.go @@ -315,20 +315,23 @@ func TestTrieDiff(t *testing.T) { newTrie.Put(test.key, test.value) } - deletedMerkleValues := newTrie.deletedMerkleValues - expectedDeletedMerkleValues := map[string]struct{}{ + deletedMerkleValues := newTrie.deltas.Deleted() + expectedDeletdMerkleValues := map[common.Hash]struct{}{ // root branch Merkle value which was modified (by its descendants). // Other nodes result in an encoding of less than 32B so they are not // tracked since they are inlined in the branch. - "\xa9v\xfaUme$<\x03\x80\x89\xd4\x15\r\xb1\x9a䶊`\xe5M\xeah\x9c\xab\xbf\xbb\xc0\xfcrH": {}, + {0xa9, 0x76, 0xfa, 0x55, 0x6d, 0x65, 0x24, 0x3c, + 0x3, 0x80, 0x89, 0xd4, 0x15, 0xd, 0xb1, 0x9a, + 0xe4, 0xb6, 0x8a, 0x60, 0xe5, 0x4d, 0xea, 0x68, + 0x9c, 0xab, 0xbf, 0xbb, 0xc0, 0xfc, 0x72, 0x48}: {}, } - assert.Equal(t, expectedDeletedMerkleValues, deletedMerkleValues) + assert.Equal(t, expectedDeletdMerkleValues, deletedMerkleValues) err = newTrie.WriteDirty(storageDB) require.NoError(t, err) for deletedMerkleValue := range deletedMerkleValues { - err = storageDB.Del([]byte(deletedMerkleValue)) + err = storageDB.Del(deletedMerkleValue[:]) require.NoError(t, err) } diff --git a/lib/trie/trie_test.go b/lib/trie/trie_test.go index 96d7b54e1a..007d006b61 100644 --- a/lib/trie/trie_test.go +++ b/lib/trie/trie_test.go @@ -6,10 +6,11 @@ package trie import ( "bytes" "encoding/hex" - "reflect" + reflect "reflect" "testing" "github.com/ChainSafe/gossamer/internal/trie/node" + "github.com/ChainSafe/gossamer/internal/trie/tracking" "github.com/ChainSafe/gossamer/lib/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -29,8 +30,8 @@ func Test_EmptyHash(t *testing.T) { func Test_NewEmptyTrie(t *testing.T) { expectedTrie := &Trie{ - childTries: make(map[common.Hash]*Trie), - deletedMerkleValues: map[string]struct{}{}, + childTries: make(map[common.Hash]*Trie), + deltas: tracking.New(), } trie := NewEmptyTrie() assert.Equal(t, expectedTrie, trie) @@ -46,8 +47,8 @@ func Test_NewTrie(t *testing.T) { PartialKey: []byte{0}, StorageValue: []byte{17}, }, - childTries: make(map[common.Hash]*Trie), - deletedMerkleValues: map[string]struct{}{}, + childTries: make(map[common.Hash]*Trie), + deltas: tracking.New(), } trie := NewTrie(root) assert.Equal(t, expectedTrie, trie) @@ -56,6 +57,9 @@ func Test_NewTrie(t *testing.T) { func Test_Trie_Snapshot(t *testing.T) { t.Parallel() + emptyDeltas := newDeltas(nil) + setDeltas := newDeltas([]common.Hash{{1}}) + trie := &Trie{ generation: 8, root: &Node{PartialKey: []byte{8}, StorageValue: []byte{1}}, @@ -63,22 +67,15 @@ func Test_Trie_Snapshot(t *testing.T) { {1}: { generation: 1, root: &Node{PartialKey: []byte{1}, StorageValue: []byte{1}}, - deletedMerkleValues: map[string]struct{}{ - "a": {}, - }, + deltas: setDeltas, }, {2}: { generation: 2, root: &Node{PartialKey: []byte{2}, StorageValue: []byte{1}}, - deletedMerkleValues: map[string]struct{}{ - "b": {}, - }, + deltas: setDeltas, }, }, - deletedMerkleValues: map[string]struct{}{ - "a": {}, - "b": {}, - }, + deltas: setDeltas, } expectedTrie := &Trie{ @@ -86,17 +83,17 @@ func Test_Trie_Snapshot(t *testing.T) { root: &Node{PartialKey: []byte{8}, StorageValue: []byte{1}}, childTries: map[common.Hash]*Trie{ {1}: { - generation: 2, - root: &Node{PartialKey: []byte{1}, StorageValue: []byte{1}}, - deletedMerkleValues: map[string]struct{}{}, + generation: 2, + root: &Node{PartialKey: []byte{1}, StorageValue: []byte{1}}, + deltas: emptyDeltas, }, {2}: { - generation: 3, - root: &Node{PartialKey: []byte{2}, StorageValue: []byte{1}}, - deletedMerkleValues: map[string]struct{}{}, + generation: 3, + root: &Node{PartialKey: []byte{2}, StorageValue: []byte{1}}, + deltas: emptyDeltas, }, }, - deletedMerkleValues: map[string]struct{}{}, + deltas: emptyDeltas, } newTrie := trie.Snapshot() @@ -108,62 +105,42 @@ func Test_Trie_handleTrackedDeltas(t *testing.T) { t.Parallel() testCases := map[string]struct { - trie Trie - success bool - pendingDeletedMerkleValues map[string]struct{} - expectedTrie Trie + trie Trie + success bool + pendingDeltas DeltaDeletedGetter + expectedTrie Trie }{ "no_success_and_generation_1": { trie: Trie{ generation: 1, - deletedMerkleValues: map[string]struct{}{ - "a": {}, - }, - }, - pendingDeletedMerkleValues: map[string]struct{}{ - "b": {}, + deltas: newDeltas([]common.Hash{{1}}), }, + pendingDeltas: newDeltas([]common.Hash{{2}}), expectedTrie: Trie{ generation: 1, - deletedMerkleValues: map[string]struct{}{ - "a": {}, - }, + deltas: newDeltas([]common.Hash{{1}}), }, }, "success_and_generation_0": { trie: Trie{ - deletedMerkleValues: map[string]struct{}{ - "a": {}, - }, - }, - success: true, - pendingDeletedMerkleValues: map[string]struct{}{ - "b": {}, + deltas: newDeltas([]common.Hash{{1}}), }, + success: true, + pendingDeltas: newDeltas([]common.Hash{{2}}), expectedTrie: Trie{ - deletedMerkleValues: map[string]struct{}{ - "a": {}, - }, + deltas: newDeltas([]common.Hash{{1}}), }, }, "success_and_generation_1": { trie: Trie{ generation: 1, - deletedMerkleValues: map[string]struct{}{ - "a": {}, - }, - }, - success: true, - pendingDeletedMerkleValues: map[string]struct{}{ - "a": {}, - "b": {}, + deltas: newDeltas([]common.Hash{{1}}), }, + success: true, + pendingDeltas: newDeltas([]common.Hash{{1}, {2}}), expectedTrie: Trie{ generation: 1, - deletedMerkleValues: map[string]struct{}{ - "a": {}, - "b": {}, - }, + deltas: newDeltas([]common.Hash{{1}, {2}}), }, }, } @@ -174,7 +151,7 @@ func Test_Trie_handleTrackedDeltas(t *testing.T) { t.Parallel() trie := testCase.trie - trie.handleTrackedDeltas(testCase.success, testCase.pendingDeletedMerkleValues) + trie.handleTrackedDeltas(testCase.success, testCase.pendingDeltas) assert.Equal(t, testCase.expectedTrie, trie) }) @@ -185,15 +162,15 @@ func Test_Trie_prepForMutation(t *testing.T) { t.Parallel() testCases := map[string]struct { - trie Trie - currentNode *Node - copySettings node.CopySettings - pendingDeletedMerkleValues map[string]struct{} - newNode *Node - copied bool - errSentinel error - errMessage string - expectedPendingDeletedMerkleValues map[string]struct{} + trie Trie + currentNode *Node + copySettings node.CopySettings + pendingDeltas DeltaRecorder + newNode *Node + copied bool + errSentinel error + errMessage string + expectedPendingDeltas DeltaRecorder }{ "no_update": { trie: Trie{ @@ -230,7 +207,7 @@ func Test_Trie_prepForMutation(t *testing.T) { trie: Trie{ generation: 2, }, - pendingDeletedMerkleValues: map[string]struct{}{}, + pendingDeltas: newDeltas(nil), currentNode: &Node{ Generation: 1, PartialKey: []byte{1}, @@ -252,9 +229,10 @@ func Test_Trie_prepForMutation(t *testing.T) { Dirty: true, }, copied: true, - expectedPendingDeletedMerkleValues: map[string]struct{}{ - "\x98\xfc\xd6k\xa3\x12\u009e\xf1\x93\x05/\xd0\xc1Ln8\xb1X\xbd\\\x025\x06E\x94\xca\xcc\x1a\xb5\x96]": {}, - }, + expectedPendingDeltas: newDeltas([]common.Hash{{ + 0x98, 0xfc, 0xd6, 0x6b, 0xa3, 0x12, 0xc2, 0x9e, 0xf1, 0x93, 0x5, 0x2f, 0xd0, 0xc1, 0x4c, 0x6e, + 0x38, 0xb1, 0x58, 0xbd, 0x5c, 0x2, 0x35, 0x6, 0x45, 0x94, 0xca, 0xcc, 0x1a, 0xb5, 0x96, 0x5d, + }}), }, } @@ -267,14 +245,14 @@ func Test_Trie_prepForMutation(t *testing.T) { expectedTrie := *testCase.trie.DeepCopy() newNode, err := trie.prepForMutation(testCase.currentNode, testCase.copySettings, - testCase.pendingDeletedMerkleValues) + testCase.pendingDeltas) require.ErrorIs(t, err, testCase.errSentinel) if testCase.errSentinel != nil { assert.EqualError(t, err, testCase.errMessage) } assert.Equal(t, testCase.newNode, newNode) - assert.Equal(t, testCase.expectedPendingDeletedMerkleValues, testCase.pendingDeletedMerkleValues) + assert.Equal(t, testCase.expectedPendingDeltas, testCase.pendingDeltas) assert.Equal(t, expectedTrie, trie) // Check for deep copy @@ -299,22 +277,25 @@ func Test_Trie_registerDeletedMerkleValue(t *testing.T) { } testCases := map[string]struct { - trie Trie - node *Node - pendingDeletedMerkleValues map[string]struct{} - expectedPendingDeletedMerkleValues map[string]struct{} - expectedTrie Trie + trie Trie + node *Node + pendingDeltas DeltaRecorder + expectedPendingDeltas DeltaRecorder + expectedTrie Trie }{ "dirty_node_not_registered": { node: &Node{Dirty: true}, }, "clean_root_node_registered": { - node: someSmallNode, - trie: Trie{root: someSmallNode}, - pendingDeletedMerkleValues: map[string]struct{}{}, - expectedPendingDeletedMerkleValues: map[string]struct{}{ - "`Qm\v\xb6\xe1\xbb\xfb\x12\x93\xf1\xb2v\xea\x95\x05\xe9\xf4\xa4\xe7ُb\r\x05\x11^\v\x85'J\xe1": {}, - }, + node: someSmallNode, + trie: Trie{root: someSmallNode}, + pendingDeltas: newDeltas(nil), + expectedPendingDeltas: newDeltas([]common.Hash{{ + 0x60, 0x51, 0x6d, 0x0b, 0xb6, 0xe1, 0xbb, 0xfb, + 0x12, 0x93, 0xf1, 0xb2, 0x76, 0xea, 0x95, 0x05, + 0xe9, 0xf4, 0xa4, 0xe7, 0xd9, 0x8f, 0x62, 0x0d, + 0x05, 0x11, 0x5e, 0x0b, 0x85, 0x27, 0x4a, 0xe1, + }}), expectedTrie: Trie{ root: &Node{ PartialKey: []byte{1}, @@ -342,10 +323,11 @@ func Test_Trie_registerDeletedMerkleValue(t *testing.T) { 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}, }, - pendingDeletedMerkleValues: map[string]struct{}{}, - expectedPendingDeletedMerkleValues: map[string]struct{}{ - "\x98\xfc\xd6k\xa3\x12\u009e\xf1\x93\x05/\xd0\xc1Ln8\xb1X\xbd\\\x025\x06E\x94\xca\xcc\x1a\xb5\x96]": {}, - }, + pendingDeltas: newDeltas(nil), + expectedPendingDeltas: newDeltas([]common.Hash{{ + 0x98, 0xfc, 0xd6, 0x6b, 0xa3, 0x12, 0xc2, 0x9e, 0xf1, 0x93, 0x5, 0x2f, 0xd0, 0xc1, 0x4c, 0x6e, + 0x38, 0xb1, 0x58, 0xbd, 0x5c, 0x2, 0x35, 0x6, 0x45, 0x94, 0xca, 0xcc, 0x1a, 0xb5, 0x96, 0x5d, + }}), }, } @@ -357,10 +339,10 @@ func Test_Trie_registerDeletedMerkleValue(t *testing.T) { trie := testCase.trie err := trie.registerDeletedMerkleValue(testCase.node, - testCase.pendingDeletedMerkleValues) + testCase.pendingDeltas) require.NoError(t, err) - assert.Equal(t, testCase.expectedPendingDeletedMerkleValues, testCase.pendingDeletedMerkleValues) + assert.Equal(t, testCase.expectedPendingDeltas, testCase.pendingDeltas) assert.Equal(t, testCase.expectedTrie, trie) }) } @@ -399,7 +381,7 @@ func testTrieForDeepCopy(t *testing.T, original, copy *Trie) { return } assertPointersNotEqual(t, original.generation, copy.generation) - assertPointersNotEqual(t, original.deletedMerkleValues, copy.deletedMerkleValues) + assertPointersNotEqual(t, original.deltas, copy.deltas) assertPointersNotEqual(t, original.childTries, copy.childTries) for hashKey, childTrie := range copy.childTries { originalChildTrie := original.childTries[hashKey] @@ -428,16 +410,10 @@ func Test_Trie_DeepCopy(t *testing.T) { {1, 2, 3}: { generation: 2, root: &Node{PartialKey: []byte{1}, StorageValue: []byte{1}}, - deletedMerkleValues: map[string]struct{}{ - "a": {}, - "b": {}, - }, + deltas: newDeltas([]common.Hash{{1}, {2}}), }, }, - deletedMerkleValues: map[string]struct{}{ - "a": {}, - "b": {}, - }, + deltas: newDeltas([]common.Hash{{1}, {2}}), }, trieCopy: &Trie{ generation: 1, @@ -446,16 +422,10 @@ func Test_Trie_DeepCopy(t *testing.T) { {1, 2, 3}: { generation: 2, root: &Node{PartialKey: []byte{1}, StorageValue: []byte{1}}, - deletedMerkleValues: map[string]struct{}{ - "a": {}, - "b": {}, - }, + deltas: newDeltas([]common.Hash{{1}, {2}}), }, }, - deletedMerkleValues: map[string]struct{}{ - "a": {}, - "b": {}, - }, + deltas: newDeltas([]common.Hash{{1}, {2}}), }, }, } @@ -1098,8 +1068,8 @@ func Test_Trie_Put(t *testing.T) { }{ "trie_with_key_and_value": { trie: Trie{ - generation: 1, - deletedMerkleValues: map[string]struct{}{}, + generation: 1, + deltas: newDeltas(nil), root: &Node{ PartialKey: []byte{1, 2, 0, 5}, StorageValue: []byte{1}, @@ -1109,9 +1079,12 @@ func Test_Trie_Put(t *testing.T) { value: []byte{2}, expectedTrie: Trie{ generation: 1, - deletedMerkleValues: map[string]struct{}{ - "\xa1\x95\b\x9c>\x8f\x8b[6\x97\x87\x00\xad\x95J\xed\x99\xe0\x84\x13\xcf\xc1\xe2\xb4\xc0\n]\x06J\xbef\xa9": {}, - }, + deltas: newDeltas([]common.Hash{ + { + 0xa1, 0x95, 0x08, 0x9c, 0x3e, 0x8f, 0x8b, 0x5b, 0x36, 0x97, 0x87, 0x00, 0xad, 0x95, 0x4a, 0xed, + 0x99, 0xe0, 0x84, 0x13, 0xcf, 0xc1, 0xe2, 0xb4, 0xc0, 0x0a, 0x5d, 0x06, 0x4a, 0xbe, 0x66, 0xa9, + }, + }), root: &Node{ PartialKey: []byte{1, 2}, Generation: 1, @@ -1153,15 +1126,15 @@ func Test_Trie_insert(t *testing.T) { t.Parallel() testCases := map[string]struct { - trie Trie - parent *Node - key []byte - value []byte - deletedMerkleValues map[string]struct{} - newNode *Node - mutated bool - nodesCreated uint32 - expectedDeletedMerkleValues map[string]struct{} + trie Trie + parent *Node + key []byte + value []byte + pendingDeltas DeltaRecorder + newNode *Node + mutated bool + nodesCreated uint32 + expectedPendingDeltas DeltaRecorder }{ "nil_parent": { trie: Trie{ @@ -1370,14 +1343,14 @@ func Test_Trie_insert(t *testing.T) { newNode, mutated, nodesCreated, err := trie.insert( testCase.parent, testCase.key, testCase.value, - testCase.deletedMerkleValues) + testCase.pendingDeltas) require.NoError(t, err) assert.Equal(t, testCase.newNode, newNode) assert.Equal(t, testCase.mutated, mutated) assert.Equal(t, testCase.nodesCreated, nodesCreated) assert.Equal(t, expectedTrie, trie) - assert.Equal(t, testCase.expectedDeletedMerkleValues, testCase.deletedMerkleValues) + assert.Equal(t, testCase.expectedPendingDeltas, testCase.pendingDeltas) }) } } @@ -1386,16 +1359,16 @@ func Test_Trie_insertInBranch(t *testing.T) { t.Parallel() testCases := map[string]struct { - parent *Node - key []byte - value []byte - deletedMerkleValues map[string]struct{} - newNode *Node - mutated bool - nodesCreated uint32 - errSentinel error - errMessage string - expectedDeletedMerkleValues map[string]struct{} + parent *Node + key []byte + value []byte + pendingDeltas DeltaRecorder + newNode *Node + mutated bool + nodesCreated uint32 + errSentinel error + errMessage string + expectedPendingDeltas DeltaRecorder }{ "insert_existing_value_to_branch": { parent: &Node{ @@ -1669,7 +1642,7 @@ func Test_Trie_insertInBranch(t *testing.T) { newNode, mutated, nodesCreated, err := trie.insertInBranch( testCase.parent, testCase.key, testCase.value, - testCase.deletedMerkleValues) + testCase.pendingDeltas) assert.ErrorIs(t, err, testCase.errSentinel) if testCase.errSentinel != nil { @@ -1679,7 +1652,7 @@ func Test_Trie_insertInBranch(t *testing.T) { assert.Equal(t, testCase.mutated, mutated) assert.Equal(t, testCase.nodesCreated, nodesCreated) assert.Equal(t, new(Trie), trie) // check no mutation - assert.Equal(t, testCase.expectedDeletedMerkleValues, testCase.deletedMerkleValues) + assert.Equal(t, testCase.expectedPendingDeltas, testCase.pendingDeltas) }) } } @@ -1695,15 +1668,15 @@ func Test_LoadFromMap(t *testing.T) { }{ "nil_data": { expectedTrie: Trie{ - childTries: map[common.Hash]*Trie{}, - deletedMerkleValues: map[string]struct{}{}, + childTries: map[common.Hash]*Trie{}, + deltas: newDeltas(nil), }, }, "empty_data": { data: map[string]string{}, expectedTrie: Trie{ - childTries: map[common.Hash]*Trie{}, - deletedMerkleValues: map[string]struct{}{}, + childTries: map[common.Hash]*Trie{}, + deltas: newDeltas(nil), }, }, "bad_key": { @@ -1735,8 +1708,8 @@ func Test_LoadFromMap(t *testing.T) { }, Dirty: true, }, - childTries: map[common.Hash]*Trie{}, - deletedMerkleValues: map[string]struct{}{}, + childTries: map[common.Hash]*Trie{}, + deltas: newDeltas(nil), }, }, "load_key_values": { @@ -1765,8 +1738,8 @@ func Test_LoadFromMap(t *testing.T) { }, }), }, - childTries: map[common.Hash]*Trie{}, - deletedMerkleValues: map[string]struct{}{}, + childTries: map[common.Hash]*Trie{}, + deltas: newDeltas(nil), }, }, } @@ -2282,18 +2255,18 @@ func Test_Trie_clearPrefixLimitAtNode(t *testing.T) { t.Parallel() testCases := map[string]struct { - trie Trie - parent *Node - prefix []byte - limit uint32 - deletedMerkleValues map[string]struct{} - newParent *Node - valuesDeleted uint32 - nodesRemoved uint32 - allDeleted bool - errSentinel error - errMessage string - expectedDeletedMerkleValues map[string]struct{} + trie Trie + parent *Node + prefix []byte + limit uint32 + pendingDeltas DeltaRecorder + newParent *Node + valuesDeleted uint32 + nodesRemoved uint32 + allDeleted bool + errSentinel error + errMessage string + expectedPendingDeltas DeltaRecorder }{ "limit_is_zero": { allDeleted: true, @@ -2818,7 +2791,7 @@ func Test_Trie_clearPrefixLimitAtNode(t *testing.T) { newParent, valuesDeleted, nodesRemoved, allDeleted, err := trie.clearPrefixLimitAtNode(testCase.parent, testCase.prefix, - testCase.limit, testCase.deletedMerkleValues) + testCase.limit, testCase.pendingDeltas) assert.ErrorIs(t, err, testCase.errSentinel) if testCase.errSentinel != nil { @@ -2829,7 +2802,7 @@ func Test_Trie_clearPrefixLimitAtNode(t *testing.T) { assert.Equal(t, testCase.nodesRemoved, nodesRemoved) assert.Equal(t, testCase.allDeleted, allDeleted) assert.Equal(t, expectedTrie, trie) - assert.Equal(t, testCase.expectedDeletedMerkleValues, testCase.deletedMerkleValues) + assert.Equal(t, testCase.expectedPendingDeltas, testCase.pendingDeltas) }) } } @@ -2838,16 +2811,16 @@ func Test_Trie_deleteNodesLimit(t *testing.T) { t.Parallel() testCases := map[string]struct { - trie Trie - parent *Node - limit uint32 - deletedMerkleValues map[string]struct{} - newNode *Node - valuesDeleted uint32 - nodesRemoved uint32 - errSentinel error - errMessage string - expectedDeletedMerkleValues map[string]struct{} + trie Trie + parent *Node + limit uint32 + pendingDeltas DeltaRecorder + newNode *Node + valuesDeleted uint32 + nodesRemoved uint32 + errSentinel error + errMessage string + expectedPendingDeltas DeltaRecorder }{ "zero_limit": { trie: Trie{ @@ -3004,7 +2977,7 @@ func Test_Trie_deleteNodesLimit(t *testing.T) { newNode, valuesDeleted, nodesRemoved, err := trie.deleteNodesLimit(testCase.parent, - testCase.limit, testCase.deletedMerkleValues) + testCase.limit, testCase.pendingDeltas) assert.ErrorIs(t, err, testCase.errSentinel) if testCase.errSentinel != nil { @@ -3014,7 +2987,7 @@ func Test_Trie_deleteNodesLimit(t *testing.T) { assert.Equal(t, testCase.valuesDeleted, valuesDeleted) assert.Equal(t, testCase.nodesRemoved, nodesRemoved) assert.Equal(t, expectedTrie, trie) - assert.Equal(t, testCase.expectedDeletedMerkleValues, testCase.deletedMerkleValues) + assert.Equal(t, testCase.expectedPendingDeltas, testCase.pendingDeltas) }) } } @@ -3029,29 +3002,31 @@ func Test_Trie_ClearPrefix(t *testing.T) { }{ "nil_prefix": { trie: Trie{ - root: &Node{StorageValue: []byte{1}}, - generation: 1, - deletedMerkleValues: map[string]struct{}{}, + root: &Node{StorageValue: []byte{1}}, + generation: 1, + deltas: newDeltas(nil), }, expectedTrie: Trie{ generation: 1, - deletedMerkleValues: map[string]struct{}{ - "\xf9jt\x15\"\xbc\xc1O\n\xea/p`DR$\x1dY\xb5\xf2ݫ\x9aiH\xfd\xb3\xfe\xf5\xf9\x86C": {}, - }, + deltas: newDeltas([]common.Hash{{ + 0xf9, 0x6a, 0x74, 0x15, 0x22, 0xbc, 0xc1, 0x4f, 0x0a, 0xea, 0x2f, 0x70, 0x60, 0x44, 0x52, 0x24, + 0x1d, 0x59, 0xb5, 0xf2, 0xdd, 0xab, 0x9a, 0x69, 0x48, 0xfd, 0xb3, 0xfe, 0xf5, 0xf9, 0x86, 0x43, + }}), }, }, "empty_prefix": { trie: Trie{ - root: &Node{StorageValue: []byte{1}}, - generation: 1, - deletedMerkleValues: map[string]struct{}{}, + root: &Node{StorageValue: []byte{1}}, + generation: 1, + deltas: newDeltas(nil), }, prefix: []byte{}, expectedTrie: Trie{ generation: 1, - deletedMerkleValues: map[string]struct{}{ - "\xf9jt\x15\"\xbc\xc1O\n\xea/p`DR$\x1dY\xb5\xf2ݫ\x9aiH\xfd\xb3\xfe\xf5\xf9\x86C": {}, - }, + deltas: newDeltas([]common.Hash{{ + 0xf9, 0x6a, 0x74, 0x15, 0x22, 0xbc, 0xc1, 0x4f, 0x0a, 0xea, 0x2f, 0x70, 0x60, 0x44, 0x52, 0x24, + 0x1d, 0x59, 0xb5, 0xf2, 0xdd, 0xab, 0x9a, 0x69, 0x48, 0xfd, 0xb3, 0xfe, 0xf5, 0xf9, 0x86, 0x43, + }}), }, }, "empty_trie": { @@ -3080,7 +3055,7 @@ func Test_Trie_ClearPrefix(t *testing.T) { }, }), }, - deletedMerkleValues: map[string]struct{}{}, + deltas: newDeltas(nil), }, prefix: []byte{0x12, 0x16}, expectedTrie: Trie{ @@ -3091,9 +3066,10 @@ func Test_Trie_ClearPrefix(t *testing.T) { Generation: 1, Dirty: true, }, - deletedMerkleValues: map[string]struct{}{ - "_\xe1\b\xc8=\b2\x93S֑\x8e\x01\x04\xda̝!\x87\xfd\x9d\xaf\xa5\x82\xd1\xc52\xe5\xfe{.P": {}, - }, + deltas: newDeltas([]common.Hash{{ + 0x5f, 0xe1, 0x08, 0xc8, 0x3d, 0x08, 0x32, 0x93, 0x53, 0xd6, 0x91, 0x8e, 0x01, 0x04, 0xda, 0xcc, + 0x9d, 0x21, 0x87, 0xfd, 0x9d, 0xaf, 0xa5, 0x82, 0xd1, 0xc5, 0x32, 0xe5, 0xfe, 0x7b, 0x2e, 0x50, + }}), }, }, } @@ -3122,14 +3098,14 @@ func Test_Trie_clearPrefixAtNode(t *testing.T) { t.Parallel() testCases := map[string]struct { - trie Trie - parent *Node - prefix []byte - deletedMerkleValues map[string]struct{} - newParent *Node - nodesRemoved uint32 - expectedTrie Trie - expectedDeletedMerkleValues map[string]struct{} + trie Trie + parent *Node + prefix []byte + pendingDeltas DeltaRecorder + newParent *Node + nodesRemoved uint32 + expectedTrie Trie + expectedPendingDeltas DeltaRecorder }{ "delete_one_of_two_children_of_branch": { trie: Trie{ @@ -3440,13 +3416,13 @@ func Test_Trie_clearPrefixAtNode(t *testing.T) { trie := testCase.trie newParent, nodesRemoved, err := trie.clearPrefixAtNode( - testCase.parent, testCase.prefix, testCase.deletedMerkleValues) + testCase.parent, testCase.prefix, testCase.pendingDeltas) require.NoError(t, err) assert.Equal(t, testCase.newParent, newParent) assert.Equal(t, testCase.nodesRemoved, nodesRemoved) assert.Equal(t, testCase.expectedTrie, trie) - assert.Equal(t, testCase.expectedDeletedMerkleValues, testCase.deletedMerkleValues) + assert.Equal(t, testCase.expectedPendingDeltas, testCase.pendingDeltas) }) } } @@ -3461,28 +3437,30 @@ func Test_Trie_Delete(t *testing.T) { }{ "nil_key": { trie: Trie{ - root: &Node{StorageValue: []byte{1}}, - generation: 1, - deletedMerkleValues: map[string]struct{}{}, + root: &Node{StorageValue: []byte{1}}, + generation: 1, + deltas: newDeltas(nil), }, expectedTrie: Trie{ generation: 1, - deletedMerkleValues: map[string]struct{}{ - "\xf9jt\x15\"\xbc\xc1O\n\xea/p`DR$\x1dY\xb5\xf2ݫ\x9aiH\xfd\xb3\xfe\xf5\xf9\x86C": {}, - }, + deltas: newDeltas([]common.Hash{{ + 0xf9, 0x6a, 0x74, 0x15, 0x22, 0xbc, 0xc1, 0x4f, 0x0a, 0xea, 0x2f, 0x70, 0x60, 0x44, 0x52, 0x24, + 0x1d, 0x59, 0xb5, 0xf2, 0xdd, 0xab, 0x9a, 0x69, 0x48, 0xfd, 0xb3, 0xfe, 0xf5, 0xf9, 0x86, 0x43, + }}), }, }, "empty_key": { trie: Trie{ - root: &Node{StorageValue: []byte{1}}, - generation: 1, - deletedMerkleValues: map[string]struct{}{}, + root: &Node{StorageValue: []byte{1}}, + generation: 1, + deltas: newDeltas(nil), }, expectedTrie: Trie{ generation: 1, - deletedMerkleValues: map[string]struct{}{ - "\xf9jt\x15\"\xbc\xc1O\n\xea/p`DR$\x1dY\xb5\xf2ݫ\x9aiH\xfd\xb3\xfe\xf5\xf9\x86C": {}, - }, + deltas: newDeltas([]common.Hash{{ + 0xf9, 0x6a, 0x74, 0x15, 0x22, 0xbc, 0xc1, 0x4f, 0x0a, 0xea, 0x2f, 0x70, 0x60, 0x44, 0x52, 0x24, + 0x1d, 0x59, 0xb5, 0xf2, 0xdd, 0xab, 0x9a, 0x69, 0x48, 0xfd, 0xb3, 0xfe, 0xf5, 0xf9, 0x86, 0x43, + }}), }, }, "empty_trie": { @@ -3512,7 +3490,7 @@ func Test_Trie_Delete(t *testing.T) { }, }), }, - deletedMerkleValues: map[string]struct{}{}, + deltas: newDeltas(nil), }, key: []byte{0x12, 0x16}, expectedTrie: Trie{ @@ -3536,9 +3514,10 @@ func Test_Trie_Delete(t *testing.T) { }, }), }, - deletedMerkleValues: map[string]struct{}{ - "=\x1b=r~\xe4\x04T\x9a]%1\xaa\xb9\xff\xf0\xee\xddŋ\xc3\v\xfe/\xe8+\x1a\f\xfe~v\xd5": {}, - }, + deltas: newDeltas([]common.Hash{{ + 0x3d, 0x1b, 0x3d, 0x72, 0x7e, 0xe4, 0x04, 0x54, 0x9a, 0x5d, 0x25, 0x31, 0xaa, 0xb9, 0xff, 0xf0, + 0xee, 0xdd, 0xc5, 0x8b, 0xc3, 0x0b, 0xfe, 0x2f, 0xe8, 0x2b, 0x1a, 0x0c, 0xfe, 0x7e, 0x76, 0xd5, + }}), }, }, } @@ -3567,17 +3546,17 @@ func Test_Trie_deleteAtNode(t *testing.T) { t.Parallel() testCases := map[string]struct { - trie Trie - parent *Node - key []byte - deletedMerkleValues map[string]struct{} - newParent *Node - updated bool - nodesRemoved uint32 - errSentinel error - errMessage string - expectedTrie Trie - expectedDeletedMerkleValues map[string]struct{} + trie Trie + parent *Node + key []byte + pendingDeltas DeltaRecorder + newParent *Node + updated bool + nodesRemoved uint32 + errSentinel error + errMessage string + expectedTrie Trie + expectedPendingDeltas DeltaRecorder }{ "nil_parent": { key: []byte{1}, @@ -3906,7 +3885,7 @@ func Test_Trie_deleteAtNode(t *testing.T) { } newParent, updated, nodesRemoved, err := testCase.trie.deleteAtNode( - testCase.parent, testCase.key, testCase.deletedMerkleValues) + testCase.parent, testCase.key, testCase.pendingDeltas) assert.ErrorIs(t, err, testCase.errSentinel) if testCase.errSentinel != nil { @@ -3917,7 +3896,7 @@ func Test_Trie_deleteAtNode(t *testing.T) { assert.Equal(t, testCase.nodesRemoved, nodesRemoved) assert.Equal(t, testCase.expectedTrie, testCase.trie) assert.Equal(t, expectedKey, testCase.key) - assert.Equal(t, testCase.expectedDeletedMerkleValues, testCase.deletedMerkleValues) + assert.Equal(t, testCase.expectedPendingDeltas, testCase.pendingDeltas) }) } } @@ -3926,15 +3905,15 @@ func Test_Trie_handleDeletion(t *testing.T) { t.Parallel() testCases := map[string]struct { - trie Trie - branch *Node - deletedKey []byte - deletedMerkleValues map[string]struct{} - newNode *Node - branchChildMerged bool - errSentinel error - errMessage string - expectedDeletedMerkleValues map[string]struct{} + trie Trie + branch *Node + deletedKey []byte + pendingDeltas DeltaRecorder + newNode *Node + branchChildMerged bool + errSentinel error + errMessage string + expectedPendingDeltas DeltaRecorder }{ "branch_with_value_and_without_children": { branch: &Node{ @@ -4050,7 +4029,7 @@ func Test_Trie_handleDeletion(t *testing.T) { expectedTrie := *trie.DeepCopy() newNode, branchChildMerged, err := trie.handleDeletion( - testCase.branch, testCase.deletedKey, testCase.deletedMerkleValues) + testCase.branch, testCase.deletedKey, testCase.pendingDeltas) assert.ErrorIs(t, err, testCase.errSentinel) if testCase.errSentinel != nil { @@ -4060,7 +4039,7 @@ func Test_Trie_handleDeletion(t *testing.T) { assert.Equal(t, testCase.newNode, newNode) assert.Equal(t, testCase.branchChildMerged, branchChildMerged) assert.Equal(t, expectedKey, testCase.deletedKey) - assert.Equal(t, testCase.expectedDeletedMerkleValues, testCase.deletedMerkleValues) + assert.Equal(t, testCase.expectedPendingDeltas, testCase.pendingDeltas) assert.Equal(t, expectedTrie, trie) }) } From 063e7cf465156bdba7f3a2d3ffb81a6a482eb4cf Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Thu, 20 Oct 2022 08:40:00 +0000 Subject: [PATCH 2/3] Test helper `newDeltas` --- lib/trie/helpers_test.go | 7 ++- lib/trie/trie_test.go | 118 ++++++++++++++------------------------- 2 files changed, 46 insertions(+), 79 deletions(-) diff --git a/lib/trie/helpers_test.go b/lib/trie/helpers_test.go index 961e85163e..b56c31335f 100644 --- a/lib/trie/helpers_test.go +++ b/lib/trie/helpers_test.go @@ -138,10 +138,11 @@ func checkMerkleValuesAreSet(t *testing.T, n *Node) { } } -func newDeltas(deleted []common.Hash) (deltas *tracking.Deltas) { +func newDeltas(deletedNodeHashesHex ...string) (deltas *tracking.Deltas) { deltas = tracking.New() - for _, hash := range deleted { - deltas.RecordDeleted(hash) + for _, deletedNodeHashHex := range deletedNodeHashesHex { + nodeHash := common.MustHexToHash(deletedNodeHashHex) + deltas.RecordDeleted(nodeHash) } return deltas } diff --git a/lib/trie/trie_test.go b/lib/trie/trie_test.go index 007d006b61..b9360c0654 100644 --- a/lib/trie/trie_test.go +++ b/lib/trie/trie_test.go @@ -57,8 +57,8 @@ func Test_NewTrie(t *testing.T) { func Test_Trie_Snapshot(t *testing.T) { t.Parallel() - emptyDeltas := newDeltas(nil) - setDeltas := newDeltas([]common.Hash{{1}}) + emptyDeltas := newDeltas() + setDeltas := newDeltas("0x01") trie := &Trie{ generation: 8, @@ -113,34 +113,34 @@ func Test_Trie_handleTrackedDeltas(t *testing.T) { "no_success_and_generation_1": { trie: Trie{ generation: 1, - deltas: newDeltas([]common.Hash{{1}}), + deltas: newDeltas("0x01"), }, - pendingDeltas: newDeltas([]common.Hash{{2}}), + pendingDeltas: newDeltas("0x02"), expectedTrie: Trie{ generation: 1, - deltas: newDeltas([]common.Hash{{1}}), + deltas: newDeltas("0x01"), }, }, "success_and_generation_0": { trie: Trie{ - deltas: newDeltas([]common.Hash{{1}}), + deltas: newDeltas("0x01"), }, success: true, - pendingDeltas: newDeltas([]common.Hash{{2}}), + pendingDeltas: newDeltas("0x02"), expectedTrie: Trie{ - deltas: newDeltas([]common.Hash{{1}}), + deltas: newDeltas("0x01"), }, }, "success_and_generation_1": { trie: Trie{ generation: 1, - deltas: newDeltas([]common.Hash{{1}}), + deltas: newDeltas("0x01"), }, success: true, - pendingDeltas: newDeltas([]common.Hash{{1}, {2}}), + pendingDeltas: newDeltas("0x01", "0x02"), expectedTrie: Trie{ generation: 1, - deltas: newDeltas([]common.Hash{{1}, {2}}), + deltas: newDeltas("0x01", "0x02"), }, }, } @@ -207,7 +207,7 @@ func Test_Trie_prepForMutation(t *testing.T) { trie: Trie{ generation: 2, }, - pendingDeltas: newDeltas(nil), + pendingDeltas: newDeltas(), currentNode: &Node{ Generation: 1, PartialKey: []byte{1}, @@ -228,11 +228,8 @@ func Test_Trie_prepForMutation(t *testing.T) { 25, 26, 27, 28, 29, 30, 31, 32}, Dirty: true, }, - copied: true, - expectedPendingDeltas: newDeltas([]common.Hash{{ - 0x98, 0xfc, 0xd6, 0x6b, 0xa3, 0x12, 0xc2, 0x9e, 0xf1, 0x93, 0x5, 0x2f, 0xd0, 0xc1, 0x4c, 0x6e, - 0x38, 0xb1, 0x58, 0xbd, 0x5c, 0x2, 0x35, 0x6, 0x45, 0x94, 0xca, 0xcc, 0x1a, 0xb5, 0x96, 0x5d, - }}), + copied: true, + expectedPendingDeltas: newDeltas("0x98fcd66ba312c29ef193052fd0c14c6e38b158bd5c0235064594cacc1ab5965d"), }, } @@ -287,15 +284,10 @@ func Test_Trie_registerDeletedMerkleValue(t *testing.T) { node: &Node{Dirty: true}, }, "clean_root_node_registered": { - node: someSmallNode, - trie: Trie{root: someSmallNode}, - pendingDeltas: newDeltas(nil), - expectedPendingDeltas: newDeltas([]common.Hash{{ - 0x60, 0x51, 0x6d, 0x0b, 0xb6, 0xe1, 0xbb, 0xfb, - 0x12, 0x93, 0xf1, 0xb2, 0x76, 0xea, 0x95, 0x05, - 0xe9, 0xf4, 0xa4, 0xe7, 0xd9, 0x8f, 0x62, 0x0d, - 0x05, 0x11, 0x5e, 0x0b, 0x85, 0x27, 0x4a, 0xe1, - }}), + node: someSmallNode, + trie: Trie{root: someSmallNode}, + pendingDeltas: newDeltas(), + expectedPendingDeltas: newDeltas("0x60516d0bb6e1bbfb1293f1b276ea9505e9f4a4e7d98f620d05115e0b85274ae1"), expectedTrie: Trie{ root: &Node{ PartialKey: []byte{1}, @@ -323,11 +315,8 @@ func Test_Trie_registerDeletedMerkleValue(t *testing.T) { 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}, }, - pendingDeltas: newDeltas(nil), - expectedPendingDeltas: newDeltas([]common.Hash{{ - 0x98, 0xfc, 0xd6, 0x6b, 0xa3, 0x12, 0xc2, 0x9e, 0xf1, 0x93, 0x5, 0x2f, 0xd0, 0xc1, 0x4c, 0x6e, - 0x38, 0xb1, 0x58, 0xbd, 0x5c, 0x2, 0x35, 0x6, 0x45, 0x94, 0xca, 0xcc, 0x1a, 0xb5, 0x96, 0x5d, - }}), + pendingDeltas: newDeltas(), + expectedPendingDeltas: newDeltas("0x98fcd66ba312c29ef193052fd0c14c6e38b158bd5c0235064594cacc1ab5965d"), }, } @@ -410,10 +399,10 @@ func Test_Trie_DeepCopy(t *testing.T) { {1, 2, 3}: { generation: 2, root: &Node{PartialKey: []byte{1}, StorageValue: []byte{1}}, - deltas: newDeltas([]common.Hash{{1}, {2}}), + deltas: newDeltas("0x01", "0x02"), }, }, - deltas: newDeltas([]common.Hash{{1}, {2}}), + deltas: newDeltas("0x01", "0x02"), }, trieCopy: &Trie{ generation: 1, @@ -422,10 +411,10 @@ func Test_Trie_DeepCopy(t *testing.T) { {1, 2, 3}: { generation: 2, root: &Node{PartialKey: []byte{1}, StorageValue: []byte{1}}, - deltas: newDeltas([]common.Hash{{1}, {2}}), + deltas: newDeltas("0x01", "0x02"), }, }, - deltas: newDeltas([]common.Hash{{1}, {2}}), + deltas: newDeltas("0x01", "0x02"), }, }, } @@ -1069,7 +1058,7 @@ func Test_Trie_Put(t *testing.T) { "trie_with_key_and_value": { trie: Trie{ generation: 1, - deltas: newDeltas(nil), + deltas: newDeltas(), root: &Node{ PartialKey: []byte{1, 2, 0, 5}, StorageValue: []byte{1}, @@ -1079,12 +1068,7 @@ func Test_Trie_Put(t *testing.T) { value: []byte{2}, expectedTrie: Trie{ generation: 1, - deltas: newDeltas([]common.Hash{ - { - 0xa1, 0x95, 0x08, 0x9c, 0x3e, 0x8f, 0x8b, 0x5b, 0x36, 0x97, 0x87, 0x00, 0xad, 0x95, 0x4a, 0xed, - 0x99, 0xe0, 0x84, 0x13, 0xcf, 0xc1, 0xe2, 0xb4, 0xc0, 0x0a, 0x5d, 0x06, 0x4a, 0xbe, 0x66, 0xa9, - }, - }), + deltas: newDeltas("0xa195089c3e8f8b5b36978700ad954aed99e08413cfc1e2b4c00a5d064abe66a9"), root: &Node{ PartialKey: []byte{1, 2}, Generation: 1, @@ -1669,14 +1653,14 @@ func Test_LoadFromMap(t *testing.T) { "nil_data": { expectedTrie: Trie{ childTries: map[common.Hash]*Trie{}, - deltas: newDeltas(nil), + deltas: newDeltas(), }, }, "empty_data": { data: map[string]string{}, expectedTrie: Trie{ childTries: map[common.Hash]*Trie{}, - deltas: newDeltas(nil), + deltas: newDeltas(), }, }, "bad_key": { @@ -1709,7 +1693,7 @@ func Test_LoadFromMap(t *testing.T) { Dirty: true, }, childTries: map[common.Hash]*Trie{}, - deltas: newDeltas(nil), + deltas: newDeltas(), }, }, "load_key_values": { @@ -1739,7 +1723,7 @@ func Test_LoadFromMap(t *testing.T) { }), }, childTries: map[common.Hash]*Trie{}, - deltas: newDeltas(nil), + deltas: newDeltas(), }, }, } @@ -3004,29 +2988,23 @@ func Test_Trie_ClearPrefix(t *testing.T) { trie: Trie{ root: &Node{StorageValue: []byte{1}}, generation: 1, - deltas: newDeltas(nil), + deltas: newDeltas(), }, expectedTrie: Trie{ generation: 1, - deltas: newDeltas([]common.Hash{{ - 0xf9, 0x6a, 0x74, 0x15, 0x22, 0xbc, 0xc1, 0x4f, 0x0a, 0xea, 0x2f, 0x70, 0x60, 0x44, 0x52, 0x24, - 0x1d, 0x59, 0xb5, 0xf2, 0xdd, 0xab, 0x9a, 0x69, 0x48, 0xfd, 0xb3, 0xfe, 0xf5, 0xf9, 0x86, 0x43, - }}), + deltas: newDeltas("0xf96a741522bcc14f0aea2f70604452241d59b5f2ddab9a6948fdb3fef5f98643"), }, }, "empty_prefix": { trie: Trie{ root: &Node{StorageValue: []byte{1}}, generation: 1, - deltas: newDeltas(nil), + deltas: newDeltas(), }, prefix: []byte{}, expectedTrie: Trie{ generation: 1, - deltas: newDeltas([]common.Hash{{ - 0xf9, 0x6a, 0x74, 0x15, 0x22, 0xbc, 0xc1, 0x4f, 0x0a, 0xea, 0x2f, 0x70, 0x60, 0x44, 0x52, 0x24, - 0x1d, 0x59, 0xb5, 0xf2, 0xdd, 0xab, 0x9a, 0x69, 0x48, 0xfd, 0xb3, 0xfe, 0xf5, 0xf9, 0x86, 0x43, - }}), + deltas: newDeltas("0xf96a741522bcc14f0aea2f70604452241d59b5f2ddab9a6948fdb3fef5f98643"), }, }, "empty_trie": { @@ -3055,7 +3033,7 @@ func Test_Trie_ClearPrefix(t *testing.T) { }, }), }, - deltas: newDeltas(nil), + deltas: newDeltas(), }, prefix: []byte{0x12, 0x16}, expectedTrie: Trie{ @@ -3066,10 +3044,7 @@ func Test_Trie_ClearPrefix(t *testing.T) { Generation: 1, Dirty: true, }, - deltas: newDeltas([]common.Hash{{ - 0x5f, 0xe1, 0x08, 0xc8, 0x3d, 0x08, 0x32, 0x93, 0x53, 0xd6, 0x91, 0x8e, 0x01, 0x04, 0xda, 0xcc, - 0x9d, 0x21, 0x87, 0xfd, 0x9d, 0xaf, 0xa5, 0x82, 0xd1, 0xc5, 0x32, 0xe5, 0xfe, 0x7b, 0x2e, 0x50, - }}), + deltas: newDeltas("0x5fe108c83d08329353d6918e0104dacc9d2187fd9dafa582d1c532e5fe7b2e50"), }, }, } @@ -3439,28 +3414,22 @@ func Test_Trie_Delete(t *testing.T) { trie: Trie{ root: &Node{StorageValue: []byte{1}}, generation: 1, - deltas: newDeltas(nil), + deltas: newDeltas(), }, expectedTrie: Trie{ generation: 1, - deltas: newDeltas([]common.Hash{{ - 0xf9, 0x6a, 0x74, 0x15, 0x22, 0xbc, 0xc1, 0x4f, 0x0a, 0xea, 0x2f, 0x70, 0x60, 0x44, 0x52, 0x24, - 0x1d, 0x59, 0xb5, 0xf2, 0xdd, 0xab, 0x9a, 0x69, 0x48, 0xfd, 0xb3, 0xfe, 0xf5, 0xf9, 0x86, 0x43, - }}), + deltas: newDeltas("0xf96a741522bcc14f0aea2f70604452241d59b5f2ddab9a6948fdb3fef5f98643"), }, }, "empty_key": { trie: Trie{ root: &Node{StorageValue: []byte{1}}, generation: 1, - deltas: newDeltas(nil), + deltas: newDeltas(), }, expectedTrie: Trie{ generation: 1, - deltas: newDeltas([]common.Hash{{ - 0xf9, 0x6a, 0x74, 0x15, 0x22, 0xbc, 0xc1, 0x4f, 0x0a, 0xea, 0x2f, 0x70, 0x60, 0x44, 0x52, 0x24, - 0x1d, 0x59, 0xb5, 0xf2, 0xdd, 0xab, 0x9a, 0x69, 0x48, 0xfd, 0xb3, 0xfe, 0xf5, 0xf9, 0x86, 0x43, - }}), + deltas: newDeltas("0xf96a741522bcc14f0aea2f70604452241d59b5f2ddab9a6948fdb3fef5f98643"), }, }, "empty_trie": { @@ -3490,7 +3459,7 @@ func Test_Trie_Delete(t *testing.T) { }, }), }, - deltas: newDeltas(nil), + deltas: newDeltas(), }, key: []byte{0x12, 0x16}, expectedTrie: Trie{ @@ -3514,10 +3483,7 @@ func Test_Trie_Delete(t *testing.T) { }, }), }, - deltas: newDeltas([]common.Hash{{ - 0x3d, 0x1b, 0x3d, 0x72, 0x7e, 0xe4, 0x04, 0x54, 0x9a, 0x5d, 0x25, 0x31, 0xaa, 0xb9, 0xff, 0xf0, - 0xee, 0xdd, 0xc5, 0x8b, 0xc3, 0x0b, 0xfe, 0x2f, 0xe8, 0x2b, 0x1a, 0x0c, 0xfe, 0x7e, 0x76, 0xd5, - }}), + deltas: newDeltas("0x3d1b3d727ee404549a5d2531aab9fff0eeddc58bc30bfe2fe82b1a0cfe7e76d5"), }, }, } From 364fbbe578c81ec3c16e9c47f450ce5a4d3f14dd Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Fri, 13 Jan 2023 11:37:21 +0000 Subject: [PATCH 3/3] Snake_case test case names --- internal/trie/tracking/deltas_test.go | 20 ++++++++++---------- lib/trie/trie_test.go | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/internal/trie/tracking/deltas_test.go b/internal/trie/tracking/deltas_test.go index 59885dfac8..3af891a943 100644 --- a/internal/trie/tracking/deltas_test.go +++ b/internal/trie/tracking/deltas_test.go @@ -29,7 +29,7 @@ func Test_Deltas_RecordDeleted(t *testing.T) { nodeHash common.Hash expectedDeltas Deltas }{ - "set in empty deltas": { + "set_in_empty_deltas": { deltas: Deltas{ deletedNodeHashes: map[common.Hash]struct{}{}, }, @@ -38,7 +38,7 @@ func Test_Deltas_RecordDeleted(t *testing.T) { deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, }, }, - "set in non empty deltas": { + "set_in_non_empty_deltas": { deltas: Deltas{ deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, }, @@ -49,7 +49,7 @@ func Test_Deltas_RecordDeleted(t *testing.T) { }, }, }, - "override in deltas": { + "override_in_deltas": { deltas: Deltas{ deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, }, @@ -78,8 +78,8 @@ func Test_Deltas_Deleted(t *testing.T) { deltas Deltas nodeHashes map[common.Hash]struct{} }{ - "empty deltas": {}, - "non empty deltas": { + "empty_deltas": {}, + "non_empty_deltas": { deltas: Deltas{ deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, }, @@ -106,7 +106,7 @@ func Test_Deltas_MergeWith(t *testing.T) { deltasArg DeletedGetter expectedDeltas Deltas }{ - "merge empty deltas": { + "merge_empty_deltas": { deltas: Deltas{ deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, }, @@ -115,7 +115,7 @@ func Test_Deltas_MergeWith(t *testing.T) { deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, }, }, - "merge deltas": { + "merge_deltas": { deltas: Deltas{ deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, }, @@ -150,12 +150,12 @@ func Test_Deltas_DeepCopy(t *testing.T) { deltasOriginal *Deltas deltasCopy *Deltas }{ - "nil deltas": {}, - "empty deltas": { + "nil_deltas": {}, + "empty_deltas": { deltasOriginal: &Deltas{}, deltasCopy: &Deltas{}, }, - "filled deltas": { + "filled_deltas": { deltasOriginal: &Deltas{ deletedNodeHashes: map[common.Hash]struct{}{{1}: {}}, }, diff --git a/lib/trie/trie_test.go b/lib/trie/trie_test.go index b9360c0654..35d785bba1 100644 --- a/lib/trie/trie_test.go +++ b/lib/trie/trie_test.go @@ -6,7 +6,7 @@ package trie import ( "bytes" "encoding/hex" - reflect "reflect" + "reflect" "testing" "github.com/ChainSafe/gossamer/internal/trie/node"