Skip to content

Commit 824c3b2

Browse files
dboehm-avalabsDan LaineDarioush Jalali
authored
MerkleDB Cleanup (ava-labs#1465)
Signed-off-by: Dan Laine <daniel.laine@avalabs.org> Co-authored-by: Dan Laine <daniel.laine@avalabs.org> Co-authored-by: Darioush Jalali <darioush.jalali@avalabs.org>
1 parent 2e44364 commit 824c3b2

File tree

8 files changed

+148
-183
lines changed

8 files changed

+148
-183
lines changed

x/merkledb/db.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ var (
4343

4444
Codec, Version = newCodec()
4545

46-
rootKey = []byte{}
46+
rootKey []byte
4747
nodePrefix = []byte("node")
4848
metadataPrefix = []byte("metadata")
4949
cleanShutdownKey = []byte("cleanShutdown")
@@ -65,7 +65,7 @@ type Config struct {
6565
Tracer trace.Tracer
6666
}
6767

68-
// Can only be edited by committing changes from a trieView.
68+
// Database can only be edited by committing changes from a trieView.
6969
type Database struct {
7070
// Must be held when reading/writing fields.
7171
lock sync.RWMutex
@@ -225,7 +225,7 @@ func New(ctx context.Context, db database.Database, config Config) (*Database, e
225225
return newDatabase(ctx, db, config, metrics)
226226
}
227227

228-
// Commits the key/value pairs within the [proof] to the db.
228+
// CommitChangeProof commits the key/value pairs within the [proof] to the db.
229229
func (db *Database) CommitChangeProof(ctx context.Context, proof *ChangeProof) error {
230230
db.commitLock.Lock()
231231
defer db.commitLock.Unlock()
@@ -241,7 +241,7 @@ func (db *Database) CommitChangeProof(ctx context.Context, proof *ChangeProof) e
241241
return view.commitToDB(ctx)
242242
}
243243

244-
// Commits the key/value pairs within the [proof] to the db.
244+
// CommitRangeProof commits the key/value pairs within the [proof] to the db.
245245
// [start] is the smallest key in the range this [proof] covers.
246246
func (db *Database) CommitRangeProof(ctx context.Context, start []byte, proof *RangeProof) error {
247247
db.commitLock.Lock()
@@ -354,7 +354,7 @@ func (db *Database) getValueCopy(key path, lock bool) ([]byte, error) {
354354
// getValue returns the value for the given [key].
355355
// Returns database.ErrNotFound if it doesn't exist.
356356
// If [lock], [db.lock]'s read lock is acquired.
357-
// Otherwise assumes [db.lock] is already held.
357+
// Otherwise, assumes [db.lock] is already held.
358358
func (db *Database) getValue(key path, lock bool) ([]byte, error) {
359359
if lock {
360360
db.lock.RLock()
@@ -375,7 +375,7 @@ func (db *Database) getValue(key path, lock bool) ([]byte, error) {
375375
return n.value.value, nil
376376
}
377377

378-
// Returns the ID of the root node of the merkle trie.
378+
// GetMerkleRoot returns the ID of the root node of the merkle trie.
379379
func (db *Database) GetMerkleRoot(ctx context.Context) (ids.ID, error) {
380380
_, span := db.tracer.Start(ctx, "MerkleDB.GetMerkleRoot")
381381
defer span.End()
@@ -396,7 +396,7 @@ func (db *Database) getMerkleRoot() ids.ID {
396396
return db.root.id
397397
}
398398

399-
// Returns a proof of the existence/non-existence of [key] in this trie.
399+
// GetProof returns a proof of the existence/non-existence of [key] in this trie.
400400
func (db *Database) GetProof(ctx context.Context, key []byte) (*Proof, error) {
401401
db.commitLock.RLock()
402402
defer db.commitLock.RUnlock()
@@ -419,7 +419,7 @@ func (db *Database) getProof(ctx context.Context, key []byte) (*Proof, error) {
419419
return view.getProof(ctx, key)
420420
}
421421

422-
// Returns a proof for the key/value pairs in this trie within the range
422+
// GetRangeProof returns a proof for the key/value pairs in this trie within the range
423423
// [start, end].
424424
func (db *Database) GetRangeProof(
425425
ctx context.Context,
@@ -433,7 +433,7 @@ func (db *Database) GetRangeProof(
433433
return db.getRangeProofAtRoot(ctx, db.getMerkleRoot(), start, end, maxLength)
434434
}
435435

436-
// Returns a proof for the key/value pairs in this trie within the range
436+
// GetRangeProofAtRoot returns a proof for the key/value pairs in this trie within the range
437437
// [start, end] when the root of the trie was [rootID].
438438
func (db *Database) GetRangeProofAtRoot(
439439
ctx context.Context,
@@ -470,7 +470,7 @@ func (db *Database) getRangeProofAtRoot(
470470
return historicalView.GetRangeProof(ctx, start, end, maxLength)
471471
}
472472

473-
// Returns a proof for a subset of the key/value changes in key range
473+
// GetChangeProof returns a proof for a subset of the key/value changes in key range
474474
// [start, end] that occurred between [startRootID] and [endRootID].
475475
// Returns at most [maxLength] key/value pairs.
476476
func (db *Database) GetChangeProof(
@@ -577,7 +577,7 @@ func (db *Database) GetChangeProof(
577577
return result, nil
578578
}
579579

580-
// Returns a new view on top of this trie.
580+
// NewView returns a new view on top of this trie.
581581
// Changes made to the view will only be reflected in the original trie if Commit is called.
582582
// Assumes [db.lock] isn't held.
583583
func (db *Database) NewView() (TrieView, error) {
@@ -591,7 +591,7 @@ func (db *Database) newUntrackedView(estimatedSize int) (*trieView, error) {
591591
return newTrieView(db, db, db.root.clone(), estimatedSize)
592592
}
593593

594-
// Returns a new view preallocated to hold at least [estimatedSize] value changes at a time.
594+
// NewPreallocatedView returns a new view with memory allocated to hold at least [estimatedSize] value changes at a time.
595595
// If more changes are made, additional memory will be allocated.
596596
// The returned view is added to [db.childViews].
597597
// Assumes [db.lock] isn't held.
@@ -721,7 +721,7 @@ func (db *Database) onEviction(node *node) error {
721721
return nil
722722
}
723723

724-
// Inserts the key/value pair into the db.
724+
// Put upserts the key/value pair into the db.
725725
func (db *Database) Put(k, v []byte) error {
726726
return db.Insert(context.Background(), k, v)
727727
}

x/merkledb/db_test.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -710,10 +710,8 @@ func applyOperations(t *Database, ops []*testOperation) (Trie, error) {
710710
if err := view.Remove(context.Background(), op.key); err != nil {
711711
return nil, err
712712
}
713-
} else {
714-
if err := view.Insert(context.Background(), op.key, op.value); err != nil {
715-
return nil, err
716-
}
713+
} else if err := view.Insert(context.Background(), op.key, op.value); err != nil {
714+
return nil, err
717715
}
718716
}
719717
return view, nil

x/merkledb/history.go

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -158,31 +158,33 @@ func (th *trieHistory) getValueChanges(startRoot, endRoot ids.ID, start, end []b
158158

159159
// Add the changes from this commit to [combinedChanges].
160160
for key, valueChange := range item.values {
161-
if (len(startPath) == 0 || key.Compare(startPath) >= 0) &&
162-
(len(endPath) == 0 || key.Compare(endPath) <= 0) {
163-
// The key is in the range [start, end].
164-
if existing, ok := combinedChanges.values[key]; ok {
165-
// A change to this key already exists in [combinedChanges].
166-
existing.after = valueChange.after
167-
if existing.before.hasValue == existing.after.hasValue &&
168-
bytes.Equal(existing.before.value, existing.after.value) {
169-
// The change to this key is a no-op, so remove it from [combinedChanges].
170-
delete(combinedChanges.values, key)
171-
sortedKeys.Delete(key)
172-
}
173-
} else {
174-
combinedChanges.values[key] = &change[Maybe[[]byte]]{
175-
before: valueChange.before,
176-
after: valueChange.after,
177-
}
178-
sortedKeys.ReplaceOrInsert(key)
161+
// The key is outside the range [start, end].
162+
if (len(startPath) > 0 && key.Compare(startPath) < 0) ||
163+
(len(endPath) > 0 && key.Compare(endPath) > 0) {
164+
continue
165+
}
166+
167+
// A change to this key already exists in [combinedChanges]
168+
// so update its before value with the earlier before value
169+
if existing, ok := combinedChanges.values[key]; ok {
170+
existing.after = valueChange.after
171+
if existing.before.hasValue == existing.after.hasValue &&
172+
bytes.Equal(existing.before.value, existing.after.value) {
173+
// The change to this key is a no-op, so remove it from [combinedChanges].
174+
delete(combinedChanges.values, key)
175+
sortedKeys.Delete(key)
176+
}
177+
} else {
178+
combinedChanges.values[key] = &change[Maybe[[]byte]]{
179+
before: valueChange.before,
180+
after: valueChange.after,
179181
}
182+
sortedKeys.ReplaceOrInsert(key)
180183
}
181184
}
182-
185+
// continue to next change list
183186
return true
184-
},
185-
)
187+
})
186188

187189
// Keep only the smallest [maxLength] items in [combinedChanges.values].
188190
for sortedKeys.Len() > maxLength {

x/merkledb/trieview.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -997,10 +997,8 @@ func (t *trieView) applyChangedValuesToTrie(ctx context.Context) error {
997997
if err := t.removeFromTrie(key); err != nil {
998998
return err
999999
}
1000-
} else {
1001-
if _, err := t.insertIntoTrie(key, change); err != nil {
1002-
return err
1003-
}
1000+
} else if _, err := t.insertIntoTrie(key, change); err != nil {
1001+
return err
10041002
}
10051003
}
10061004
return nil
@@ -1228,7 +1226,7 @@ func (t *trieView) insertIntoTrie(
12281226

12291227
existingChildKey := key[:closestNodeKeyLength+1] + existingChildEntry.compressedPath
12301228

1231-
// the existing child's key is of length: len(closestNodekey) + 1 for the child index + len(existing child's compressed key)
1229+
// the existing child's key is of length: len(closestNodeKey) + 1 for the child index + len(existing child's compressed key)
12321230
// if that length is less than or equal to the branch node's key that implies that the existing child's key matched the key to be inserted
12331231
// since it matched the key to be inserted, it should have been returned by GetPathTo
12341232
if len(existingChildKey) <= len(branchNode.key) {

x/sync/client_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func TestGetRangeProof(t *testing.T) {
119119
smallTrieRoot, err := smallTrieDB.GetMerkleRoot(context.Background())
120120
require.NoError(t, err)
121121

122-
largeTrieKeyCount := 10_000
122+
largeTrieKeyCount := 3 * defaultRequestKeyLimit
123123
largeTrieDB, largeTrieKeys, err := generateTrieWithMinKeyLen(t, r, largeTrieKeyCount, 1)
124124
require.NoError(t, err)
125125
largeTrieRoot, err := largeTrieDB.GetMerkleRoot(context.Background())
@@ -232,7 +232,7 @@ func TestGetRangeProof(t *testing.T) {
232232
modifyResponse: func(response *merkledb.RangeProof) {
233233
response.KeyValues = response.KeyValues[:len(response.KeyValues)-2]
234234
},
235-
expectedErr: merkledb.ErrInvalidProof,
235+
expectedErr: merkledb.ErrProofNodeNotForKey,
236236
},
237237
"removed key from middle of response": {
238238
db: largeTrieDB,

0 commit comments

Comments
 (0)