Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up merkleDB interface and duplicate code #2445

Merged
merged 36 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c417eec
Clean Up interfaces
dboehm-avalabs Nov 22, 2023
e54d60c
Merge branch 'dev' into CleanUpInterfaces
dboehm-avalabs Dec 7, 2023
0de83eb
rename
dboehm-avalabs Dec 7, 2023
e193cd7
Update db.go
dboehm-avalabs Dec 7, 2023
494de38
cleanup
dboehm-avalabs Dec 12, 2023
84df3c9
Update mock_db.go
dboehm-avalabs Dec 13, 2023
18ffba9
Merge branch 'dev' into CleanUpInterfaces
dboehm-avalabs Dec 13, 2023
8a56516
Update trieview.go
dboehm-avalabs Dec 13, 2023
7334c03
Merge branch 'dev' into CleanUpInterfaces
dboehm-avalabs Dec 14, 2023
127f367
Update db_test.go
dboehm-avalabs Dec 14, 2023
7a1029c
Update db.go
dboehm-avalabs Dec 14, 2023
a455451
rename trieview -> view
dboehm-avalabs Dec 14, 2023
b96ffe8
rename
dboehm-avalabs Dec 14, 2023
60a919d
gofumpt
dboehm-avalabs Dec 14, 2023
d5187f1
Update db.go
dboehm-avalabs Dec 14, 2023
6c5f4dc
Merge remote-tracking branch 'upstream/dev' into CleanUpInterfaces
Dec 19, 2023
22eec2d
newline nits
Dec 19, 2023
6cf97ec
nit if --> switch
Dec 19, 2023
0637ed9
prioritize returning error from getting proof, not validity
Dec 19, 2023
6438c68
Merge branch 'dev' into CleanUpInterfaces
Dec 19, 2023
07eaf12
Merge branch 'dev' into CleanUpInterfaces
dboehm-avalabs Dec 19, 2023
1a6dc5e
Merge branch 'CleanUpInterfaces' of https://github.com/ava-labs/avala…
dboehm-avalabs Dec 19, 2023
6428ae1
comments
dboehm-avalabs Dec 19, 2023
ad6bcf0
Update db.go
dboehm-avalabs Dec 19, 2023
95c7eca
Update trie_test.go
dboehm-avalabs Dec 19, 2023
a5c23d8
comments
dboehm-avalabs Dec 19, 2023
4cdb1aa
remove references to trieView
Dec 22, 2023
dc31fe1
fix test name
Dec 27, 2023
84c35a0
Merge branch 'dev' into CleanUpInterfaces
Dec 27, 2023
5cba51d
re-add database closed checks in GetProof
Dec 27, 2023
01bc75c
Merge branch 'CleanUpInterfaces' of github.com:ava-labs/avalanchego i…
Dec 27, 2023
ff774ad
nit
Dec 27, 2023
82019a0
nits
Dec 27, 2023
dc36c65
comments
Dec 27, 2023
2b5982e
comment
Dec 27, 2023
837a1b7
Merge branch 'dev' into CleanUpInterfaces
Dec 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 33 additions & 67 deletions x/merkledb/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,13 +449,8 @@ func (db *merkleDB) PrefetchPaths(keys [][]byte) error {
return database.ErrClosed
}

// reuse the view so that it can keep repeated nodes in memory
tempView, err := newTrieView(db, db, ViewChanges{})
if err != nil {
return err
}
for _, key := range keys {
if err := db.prefetchPath(tempView, key); err != nil {
if err := db.prefetchPath(key); err != nil {
return err
}
}
Expand All @@ -470,16 +465,11 @@ func (db *merkleDB) PrefetchPath(key []byte) error {
if db.closed {
return database.ErrClosed
}
tempView, err := newTrieView(db, db, ViewChanges{})
if err != nil {
return err
}

return db.prefetchPath(tempView, key)
return db.prefetchPath(key)
}

func (db *merkleDB) prefetchPath(view *trieView, keyBytes []byte) error {
return view.visitPathToKey(ToKey(keyBytes), func(n *node) error {
func (db *merkleDB) prefetchPath(keyBytes []byte) error {
return visitPathToKey(db, ToKey(keyBytes), func(n *node) error {
if !n.hasValue() {
return db.intermediateNodeDB.nodeCache.Put(n.key, n)
}
Expand Down Expand Up @@ -583,33 +573,13 @@ func (db *merkleDB) getMerkleRoot() ids.ID {
return db.rootID
}

// isSentinelNodeTheRoot returns true if the passed in sentinel node has a value and or multiple child nodes
// When this is true, the root of the trie is the sentinel node
// When this is false, the root of the trie is the sentinel node's single child
func isSentinelNodeTheRoot(sentinel *node) bool {
return sentinel.valueDigest.HasValue() || len(sentinel.children) != 1
}

func (db *merkleDB) GetProof(ctx context.Context, key []byte) (*Proof, error) {
db.commitLock.RLock()
defer db.commitLock.RUnlock()

return db.getProof(ctx, key)
}

// Assumes [db.commitLock] is read locked.
// Assumes [db.lock] is not held
func (db *merkleDB) getProof(ctx context.Context, key []byte) (*Proof, error) {
if db.closed {
return nil, database.ErrClosed
}

view, err := newTrieView(db, db, ViewChanges{})
if err != nil {
return nil, err
}
// Don't need to lock [view] because nobody else has a reference to it.
return view.getProof(ctx, key)
_, span := db.infoTracer.Start(ctx, "MerkleDB.GetProof")
defer span.End()
return getProof(db, key)
}

func (db *merkleDB) GetRangeProof(
Expand All @@ -618,10 +588,7 @@ func (db *merkleDB) GetRangeProof(
end maybe.Maybe[[]byte],
maxLength int,
) (*RangeProof, error) {
db.commitLock.RLock()
defer db.commitLock.RUnlock()

return db.getRangeProofAtRoot(ctx, db.getMerkleRoot(), start, end, maxLength)
return db.GetRangeProofAtRoot(ctx, db.getMerkleRoot(), start, end, maxLength)
}

func (db *merkleDB) GetRangeProofAtRoot(
Expand All @@ -634,30 +601,21 @@ func (db *merkleDB) GetRangeProofAtRoot(
db.commitLock.RLock()
defer db.commitLock.RUnlock()

return db.getRangeProofAtRoot(ctx, rootID, start, end, maxLength)
}
_, span := db.infoTracer.Start(ctx, "MerkleDB.GetRangeProofAtRoot")
defer span.End()

// Assumes [db.commitLock] is read locked.
// Assumes [db.lock] is not held
func (db *merkleDB) getRangeProofAtRoot(
ctx context.Context,
rootID ids.ID,
start maybe.Maybe[[]byte],
end maybe.Maybe[[]byte],
maxLength int,
) (*RangeProof, error) {
if db.closed {
return nil, database.ErrClosed
}
if maxLength <= 0 {
return nil, fmt.Errorf("%w but was %d", ErrInvalidMaxLength, maxLength)
}

historicalView, err := db.getHistoricalViewForRange(rootID, start, end)
historicalTrie, err := db.getHistoricalTrieForRange(rootID, start, end)
if err != nil {
return nil, err
}
return historicalView.GetRangeProof(ctx, start, end, maxLength)
return getRangeProof(historicalTrie, start, end, maxLength)
}

func (db *merkleDB) GetChangeProof(
Expand All @@ -668,6 +626,9 @@ func (db *merkleDB) GetChangeProof(
end maybe.Maybe[[]byte],
maxLength int,
) (*ChangeProof, error) {
_, span := db.infoTracer.Start(ctx, "MerkleDB.GetChangeProof")
defer span.End()

if start.HasValue() && end.HasValue() && bytes.Compare(start.Value(), end.Value()) == 1 {
return nil, ErrStartAfterEnd
}
Expand Down Expand Up @@ -714,21 +675,21 @@ func (db *merkleDB) GetChangeProof(

// Since we hold [db.commitlock] we must still have sufficient
// history to recreate the trie at [endRootID].
historicalView, err := db.getHistoricalViewForRange(endRootID, start, largestKey)
historicalTrie, err := db.getHistoricalTrieForRange(endRootID, start, largestKey)
if err != nil {
return nil, err
}

if largestKey.HasValue() {
endProof, err := historicalView.getProof(ctx, largestKey.Value())
endProof, err := getProof(historicalTrie, largestKey.Value())
if err != nil {
return nil, err
}
result.EndProof = endProof.Path
}

if start.HasValue() {
startProof, err := historicalView.getProof(ctx, start.Value())
startProof, err := getProof(historicalTrie, start.Value())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -765,7 +726,7 @@ func (db *merkleDB) GetChangeProof(
func (db *merkleDB) NewView(
_ context.Context,
changes ViewChanges,
) (TrieView, error) {
) (View, error) {
// ensure the db doesn't change while creating the new view
db.commitLock.RLock()
defer db.commitLock.RUnlock()
Expand Down Expand Up @@ -1183,7 +1144,7 @@ func (db *merkleDB) initializeRoot() error {
}

db.rootID = db.sentinelNode.calculateID(db.metrics)
if !isSentinelNodeTheRoot(db.sentinelNode) {
if !isSentinelNodeTheRoot(db) {
// If the sentinel node is not the root, the trie's root is the sentinel node's only child
for _, childEntry := range db.sentinelNode.children {
db.rootID = childEntry.id
Expand All @@ -1197,24 +1158,21 @@ func (db *merkleDB) initializeRoot() error {
// If [end] is Nothing, there's no upper bound on the range.
// Assumes [db.commitLock] is read locked.
// Assumes [db.lock] isn't held.
dboehm-avalabs marked this conversation as resolved.
Show resolved Hide resolved
func (db *merkleDB) getHistoricalViewForRange(
func (db *merkleDB) getHistoricalTrieForRange(
rootID ids.ID,
start maybe.Maybe[[]byte],
end maybe.Maybe[[]byte],
) (*trieView, error) {
currentRootID := db.getMerkleRoot()

) (Trie, error) {
// looking for the trie's current root id, so return the trie unmodified
if currentRootID == rootID {
// create an empty trie
return newTrieView(db, db, ViewChanges{})
if rootID == db.getMerkleRoot() {
return db, nil
}

changeHistory, err := db.history.getChangesToGetToRoot(rootID, start, end)
if err != nil {
return nil, err
}
return newHistoricalTrieView(db, changeHistory)
return newHistoricalView(db, changeHistory)
}

// Returns all keys in range [start, end] that aren't in [keySet].
Expand Down Expand Up @@ -1302,6 +1260,14 @@ func (db *merkleDB) Clear() error {
return nil
}

func (db *merkleDB) getSentinelNode() *node {
return db.sentinelNode
}

func (db *merkleDB) getTokenSize() int {
return db.tokenSize
}

// Returns [key] prefixed by [prefix].
// The returned []byte is taken from [bufferPool] and
// should be returned to it when the caller is done with it.
Expand Down
47 changes: 45 additions & 2 deletions x/merkledb/mock_db.go

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

Loading
Loading