Skip to content

Commit 243e313

Browse files
author
Dan Laine
authored
x/sync / x/merkledb -- add SyncableDB interface (ava-labs#1555)
1 parent b66e25e commit 243e313

File tree

9 files changed

+71
-43
lines changed

9 files changed

+71
-43
lines changed

x/merkledb/db.go

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import (
1010
"fmt"
1111
"sync"
1212

13-
"github.com/prometheus/client_golang/prometheus"
14-
1513
"go.opentelemetry.io/otel/attribute"
1614

1715
oteltrace "go.opentelemetry.io/otel/trace"
@@ -27,6 +25,7 @@ import (
2725
"github.com/ava-labs/avalanchego/utils"
2826
"github.com/ava-labs/avalanchego/utils/math"
2927
"github.com/ava-labs/avalanchego/utils/set"
28+
"github.com/prometheus/client_golang/prometheus"
3029
)
3130

3231
const (
@@ -53,22 +52,7 @@ var (
5352
errSameRoot = errors.New("start and end root are the same")
5453
)
5554

56-
type Config struct {
57-
// The number of changes to the database that we store in memory in order to
58-
// serve change proofs.
59-
HistoryLength int
60-
NodeCacheSize int
61-
// If [Reg] is nil, metrics are collected locally but not exported through
62-
// Prometheus.
63-
// This may be useful for testing.
64-
Reg prometheus.Registerer
65-
Tracer trace.Tracer
66-
}
67-
68-
type MerkleDB interface {
69-
database.Database
70-
Trie
71-
55+
type ChangeProofer interface {
7256
// GetChangeProof returns a proof for a subset of the key/value changes in key range
7357
// [start, end] that occurred between [startRootID] and [endRootID].
7458
// Returns at most [maxLength] key/value pairs.
@@ -105,7 +89,9 @@ type MerkleDB interface {
10589

10690
// CommitChangeProof commits the key/value pairs within the [proof] to the db.
10791
CommitChangeProof(ctx context.Context, proof *ChangeProof) error
92+
}
10893

94+
type RangeProofer interface {
10995
// GetRangeProofAtRoot returns a proof for the key/value pairs in this trie within the range
11096
// [start, end] when the root of the trie was [rootID].
11197
GetRangeProofAtRoot(
@@ -121,6 +107,27 @@ type MerkleDB interface {
121107
CommitRangeProof(ctx context.Context, start []byte, proof *RangeProof) error
122108
}
123109

110+
type MerkleDB interface {
111+
database.Database
112+
Trie
113+
MerkleRootGetter
114+
ProofGetter
115+
ChangeProofer
116+
RangeProofer
117+
}
118+
119+
type Config struct {
120+
// The number of changes to the database that we store in memory in order to
121+
// serve change proofs.
122+
HistoryLength int
123+
NodeCacheSize int
124+
// If [Reg] is nil, metrics are collected locally but not exported through
125+
// Prometheus.
126+
// This may be useful for testing.
127+
Reg prometheus.Registerer
128+
Tracer trace.Tracer
129+
}
130+
124131
// merkleDB can only be edited by committing changes from a trieView.
125132
type merkleDB struct {
126133
// Must be held when reading/writing fields.

x/merkledb/trie.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,21 @@ import (
1313

1414
var errNoNewRoot = errors.New("there was no updated root in change list")
1515

16+
type MerkleRootGetter interface {
17+
// GetMerkleRoot returns the merkle root of the Trie
18+
GetMerkleRoot(ctx context.Context) (ids.ID, error)
19+
}
20+
21+
type ProofGetter interface {
22+
// GetProof generates a proof of the value associated with a particular key,
23+
// or a proof of its absence from the trie
24+
GetProof(ctx context.Context, bytesPath []byte) (*Proof, error)
25+
}
26+
1627
type ReadOnlyTrie interface {
28+
MerkleRootGetter
29+
ProofGetter
30+
1731
// GetValue gets the value associated with the specified key
1832
// database.ErrNotFound if the key is not present
1933
GetValue(ctx context.Context, key []byte) ([]byte, error)
@@ -26,15 +40,9 @@ type ReadOnlyTrie interface {
2640
// database.ErrNotFound if the key is not present
2741
getValue(key path, lock bool) ([]byte, error)
2842

29-
// GetMerkleRoot returns the merkle root of the Trie
30-
GetMerkleRoot(ctx context.Context) (ids.ID, error)
31-
3243
// get an editable copy of the node with the given key path
3344
getEditableNode(key path) (*node, error)
3445

35-
// GetProof generates a proof of the value associated with a particular key, or a proof of its absence from the trie
36-
GetProof(ctx context.Context, bytesPath []byte) (*Proof, error)
37-
3846
// GetRangeProof generates a proof of up to maxLength smallest key/values with keys between start and end
3947
GetRangeProof(ctx context.Context, start, end []byte, maxLength int) (*RangeProof, error)
4048

x/sync/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ type Client interface {
4545
// GetChangeProof synchronously sends the given request, returning a parsed ChangesResponse or error
4646
// [verificationDB] is the local db that has all key/values in it for the proof's startroot within the proof's key range
4747
// Note: this verifies the response including the change proof.
48-
GetChangeProof(ctx context.Context, request *syncpb.ChangeProofRequest, verificationDB merkledb.MerkleDB) (*merkledb.ChangeProof, error)
48+
GetChangeProof(ctx context.Context, request *syncpb.ChangeProofRequest, verificationDB SyncableDB) (*merkledb.ChangeProof, error)
4949
}
5050

5151
type client struct {
@@ -79,7 +79,7 @@ func NewClient(config *ClientConfig) Client {
7979
// GetChangeProof synchronously retrieves the change proof given by [req].
8080
// Upon failure, retries until the context is expired.
8181
// The returned change proof is verified.
82-
func (c *client) GetChangeProof(ctx context.Context, req *syncpb.ChangeProofRequest, db merkledb.MerkleDB) (*merkledb.ChangeProof, error) {
82+
func (c *client) GetChangeProof(ctx context.Context, req *syncpb.ChangeProofRequest, db SyncableDB) (*merkledb.ChangeProof, error) {
8383
parseFn := func(ctx context.Context, responseBytes []byte) (*merkledb.ChangeProof, error) {
8484
if len(responseBytes) > int(req.BytesLimit) {
8585
return nil, fmt.Errorf("%w: (%d) > %d)", errTooManyBytes, len(responseBytes), req.BytesLimit)

x/sync/client_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import (
2727

2828
func sendRangeRequest(
2929
t *testing.T,
30-
db merkledb.MerkleDB,
30+
db SyncableDB,
3131
request *syncpb.RangeProofRequest,
3232
maxAttempts uint32,
3333
modifyResponse func(*merkledb.RangeProof),
@@ -123,7 +123,7 @@ func TestGetRangeProof(t *testing.T) {
123123
require.NoError(t, err)
124124

125125
tests := map[string]struct {
126-
db merkledb.MerkleDB
126+
db SyncableDB
127127
request *syncpb.RangeProofRequest
128128
modifyResponse func(*merkledb.RangeProof)
129129
expectedErr error
@@ -209,10 +209,10 @@ func TestGetRangeProof(t *testing.T) {
209209
},
210210
modifyResponse: func(response *merkledb.RangeProof) {
211211
start := response.KeyValues[1].Key
212-
proof, err := largeTrieDB.GetRangeProof(context.Background(), start, nil, defaultRequestKeyLimit)
213-
if err != nil {
214-
panic(err)
215-
}
212+
rootID, err := largeTrieDB.GetMerkleRoot(context.Background())
213+
require.NoError(t, err)
214+
proof, err := largeTrieDB.GetRangeProofAtRoot(context.Background(), rootID, start, nil, defaultRequestKeyLimit)
215+
require.NoError(t, err)
216216
response.KeyValues = proof.KeyValues
217217
response.StartProof = proof.StartProof
218218
response.EndProof = proof.EndProof
@@ -279,8 +279,8 @@ func TestGetRangeProof(t *testing.T) {
279279

280280
func sendChangeRequest(
281281
t *testing.T,
282-
db merkledb.MerkleDB,
283-
verificationDB merkledb.MerkleDB,
282+
db SyncableDB,
283+
verificationDB SyncableDB,
284284
request *syncpb.ChangeProofRequest,
285285
maxAttempts uint32,
286286
modifyResponse func(*merkledb.ChangeProof),
@@ -423,7 +423,7 @@ func TestGetChangeProof(t *testing.T) {
423423
require.NoError(t, err)
424424

425425
tests := map[string]struct {
426-
db merkledb.MerkleDB
426+
db SyncableDB
427427
request *syncpb.ChangeProofRequest
428428
modifyResponse func(*merkledb.ChangeProof)
429429
expectedErr error

x/sync/mock_client.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x/sync/network_server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ var ErrMinProofSizeIsTooLarge = errors.New("cannot generate any proof within the
4545

4646
type NetworkServer struct {
4747
appSender common.AppSender // Used to respond to peer requests via AppResponse.
48-
db merkledb.MerkleDB
48+
db SyncableDB
4949
log logging.Logger
5050
}
5151

52-
func NewNetworkServer(appSender common.AppSender, db merkledb.MerkleDB, log logging.Logger) *NetworkServer {
52+
func NewNetworkServer(appSender common.AppSender, db SyncableDB, log logging.Logger) *NetworkServer {
5353
return &NetworkServer{
5454
appSender: appSender,
5555
db: db,

x/sync/sync_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ func newNoopTracer() trace.Tracer {
3434
}
3535

3636
type mockClient struct {
37-
db merkledb.MerkleDB
37+
db SyncableDB
3838
}
3939

40-
func (client *mockClient) GetChangeProof(ctx context.Context, request *syncpb.ChangeProofRequest, _ merkledb.MerkleDB) (*merkledb.ChangeProof, error) {
40+
func (client *mockClient) GetChangeProof(ctx context.Context, request *syncpb.ChangeProofRequest, _ SyncableDB) (*merkledb.ChangeProof, error) {
4141
startRoot, err := ids.ToID(request.StartRootHash)
4242
if err != nil {
4343
return nil, err
@@ -871,7 +871,7 @@ func Test_Sync_Error_During_Sync(t *testing.T) {
871871
},
872872
).AnyTimes()
873873
client.EXPECT().GetChangeProof(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
874-
func(ctx context.Context, request *syncpb.ChangeProofRequest, _ merkledb.MerkleDB) (*merkledb.ChangeProof, error) {
874+
func(ctx context.Context, request *syncpb.ChangeProofRequest, _ SyncableDB) (*merkledb.ChangeProof, error) {
875875
startRoot, err := ids.ToID(request.StartRootHash)
876876
require.NoError(err)
877877
endRoot, err := ids.ToID(request.EndRootHash)
@@ -961,7 +961,7 @@ func Test_Sync_Result_Correct_Root_Update_Root_During(t *testing.T) {
961961
},
962962
).AnyTimes()
963963
client.EXPECT().GetChangeProof(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
964-
func(ctx context.Context, request *syncpb.ChangeProofRequest, _ merkledb.MerkleDB) (*merkledb.ChangeProof, error) {
964+
func(ctx context.Context, request *syncpb.ChangeProofRequest, _ SyncableDB) (*merkledb.ChangeProof, error) {
965965
<-updatedRootChan
966966
startRoot, err := ids.ToID(request.StartRootHash)
967967
require.NoError(err)

x/sync/syncable_db.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
2+
// See the file LICENSE for licensing terms.
3+
4+
package sync
5+
6+
import "github.com/ava-labs/avalanchego/x/merkledb"
7+
8+
type SyncableDB interface {
9+
merkledb.MerkleRootGetter
10+
merkledb.ProofGetter
11+
merkledb.ChangeProofer
12+
merkledb.RangeProofer
13+
}

x/sync/syncmanager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ type StateSyncManager struct {
106106
}
107107

108108
type StateSyncConfig struct {
109-
SyncDB merkledb.MerkleDB
109+
SyncDB SyncableDB
110110
Client Client
111111
SimultaneousWorkLimit int
112112
Log logging.Logger

0 commit comments

Comments
 (0)