Skip to content

Commit 7614a26

Browse files
committed
refactor: Setup Firewood as a state syncer
1 parent 3840c82 commit 7614a26

File tree

13 files changed

+92
-35
lines changed

13 files changed

+92
-35
lines changed

graft/coreth/plugin/evm/atomic/sync/syncer_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ func setupTestInfrastructure(t *testing.T, serverTrieDB *triedb.Database) (conte
353353
handlers.NewLeafsRequestHandler(serverTrieDB, state.TrieKeyLength, nil, message.Codec, handlerstats.NewNoopHandlerStats()),
354354
nil,
355355
nil,
356+
nil,
356357
)
357358

358359
clientDB := versiondb.New(memdb.New())

graft/coreth/plugin/evm/vm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ func (vm *VM) initializeStateSync(lastAcceptedHeight uint64) error {
651651
State: vm.State,
652652
Client: client.New(
653653
&client.Config{
654-
NetworkClient: vm.Network,
654+
Network: vm.Network,
655655
Codec: vm.networkCodec,
656656
Stats: stats.NewClientSyncerStats(leafMetricsNames),
657657
StateSyncNodeIDs: stateSyncIDs,

graft/coreth/sync/block/syncer_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ func newTestEnvironment(t *testing.T, numBlocks int) *testEnvironment {
201201
nil,
202202
nil,
203203
blockHandler,
204+
nil,
204205
),
205206
}
206207
}

graft/coreth/sync/client/client.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/message"
2525
"github.com/ava-labs/avalanchego/graft/coreth/sync/client/stats"
2626
"github.com/ava-labs/avalanchego/ids"
27+
"github.com/ava-labs/avalanchego/network/p2p"
2728
"github.com/ava-labs/avalanchego/version"
2829

2930
ethparams "github.com/ava-labs/libevm/params"
@@ -65,6 +66,13 @@ type Client interface {
6566

6667
// GetCode synchronously retrieves code associated with the given hashes
6768
GetCode(ctx context.Context, hashes []common.Hash) ([][]byte, error)
69+
70+
// NewClient creates a [p2p.Client] on the underlying network with the given handlerID
71+
NewClient(handlerID uint64) *p2p.Client
72+
73+
// NodeIDs returns the list of node IDs used by this client for state sync
74+
// If the list is empty, any available node may be used
75+
NodeIDs() []ids.NodeID
6876
}
6977

7078
// parseResponseFn parses given response bytes in context of specified request
@@ -74,7 +82,7 @@ type Client interface {
7482
type parseResponseFn func(codec codec.Manager, request message.Request, response []byte) (interface{}, int, error)
7583

7684
type client struct {
77-
networkClient network.SyncedNetworkClient
85+
network network.Network
7886
codec codec.Manager
7987
stateSyncNodes []ids.NodeID
8088
stateSyncNodeIdx uint32
@@ -83,7 +91,7 @@ type client struct {
8391
}
8492

8593
type Config struct {
86-
NetworkClient network.SyncedNetworkClient
94+
Network network.Network
8795
Codec codec.Manager
8896
Stats stats.ClientSyncerStats
8997
StateSyncNodeIDs []ids.NodeID
@@ -96,14 +104,18 @@ type EthBlockParser interface {
96104

97105
func New(config *Config) *client {
98106
return &client{
99-
networkClient: config.NetworkClient,
107+
network: config.Network,
100108
codec: config.Codec,
101109
stats: config.Stats,
102110
stateSyncNodes: config.StateSyncNodeIDs,
103111
blockParser: config.BlockParser,
104112
}
105113
}
106114

115+
func (c *client) NodeIDs() []ids.NodeID {
116+
return c.stateSyncNodes
117+
}
118+
107119
// GetLeafs synchronously retrieves leafs as per given [message.LeafsRequest]
108120
// Retries when:
109121
// - response bytes could not be unmarshalled to [message.LeafsResponse]
@@ -319,14 +331,14 @@ func (c *client) get(ctx context.Context, request message.Request, parseFn parse
319331
start = time.Now()
320332
)
321333
if len(c.stateSyncNodes) == 0 {
322-
response, nodeID, err = c.networkClient.SendSyncedAppRequestAny(ctx, StateSyncVersion, requestBytes)
334+
response, nodeID, err = c.network.SendSyncedAppRequestAny(ctx, StateSyncVersion, requestBytes)
323335
} else {
324336
// get the next nodeID using the nodeIdx offset. If we're out of nodes, loop back to 0
325337
// we do this every attempt to ensure we get a different node each time if possible.
326338
nodeIdx := atomic.AddUint32(&c.stateSyncNodeIdx, 1)
327339
nodeID = c.stateSyncNodes[nodeIdx%uint32(len(c.stateSyncNodes))]
328340

329-
response, err = c.networkClient.SendSyncedAppRequest(ctx, nodeID, requestBytes)
341+
response, err = c.network.SendSyncedAppRequest(ctx, nodeID, requestBytes)
330342
}
331343
metric.UpdateRequestLatency(time.Since(start))
332344

@@ -338,25 +350,29 @@ func (c *client) get(ctx context.Context, request message.Request, parseFn parse
338350
ctx = append(ctx, "attempt", attempt, "request", request, "err", err)
339351
log.Debug("request failed, retrying", ctx...)
340352
metric.IncFailed()
341-
c.networkClient.TrackBandwidth(nodeID, 0)
353+
c.network.TrackBandwidth(nodeID, 0)
342354
time.Sleep(failedRequestSleepInterval)
343355
continue
344356
} else {
345357
responseIntf, numElements, err = parseFn(c.codec, request, response)
346358
if err != nil {
347359
lastErr = err
348360
log.Debug("could not validate response, retrying", "nodeID", nodeID, "attempt", attempt, "request", request, "err", err)
349-
c.networkClient.TrackBandwidth(nodeID, 0)
361+
c.network.TrackBandwidth(nodeID, 0)
350362
metric.IncFailed()
351363
metric.IncInvalidResponse()
352364
continue
353365
}
354366

355367
bandwidth := float64(len(response)) / (time.Since(start).Seconds() + epsilon)
356-
c.networkClient.TrackBandwidth(nodeID, bandwidth)
368+
c.network.TrackBandwidth(nodeID, bandwidth)
357369
metric.IncSucceeded()
358370
metric.IncReceived(int64(numElements))
359371
return responseIntf, nil
360372
}
361373
}
362374
}
375+
376+
func (c *client) NewClient(handlerID uint64) *p2p.Client {
377+
return c.network.P2PNetwork().NewClient(handlerID, c.network.P2PValidators())
378+
}

graft/coreth/sync/client/client_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func TestGetCode(t *testing.T) {
9595
t.Parallel()
9696
testNetClient := &testNetwork{}
9797
stateSyncClient := New(&Config{
98-
NetworkClient: testNetClient,
98+
Network: testNetClient,
9999
Codec: message.Codec,
100100
Stats: clientstats.NewNoOpStats(),
101101
StateSyncNodeIDs: nil,
@@ -324,7 +324,7 @@ func TestGetBlocks(t *testing.T) {
324324
// Construct client
325325
testNetClient := &testNetwork{}
326326
stateSyncClient := New(&Config{
327-
NetworkClient: testNetClient,
327+
Network: testNetClient,
328328
Codec: message.Codec,
329329
Stats: clientstats.NewNoOpStats(),
330330
StateSyncNodeIDs: nil,
@@ -662,7 +662,7 @@ func TestGetLeafs(t *testing.T) {
662662
t.Run(name, func(t *testing.T) {
663663
t.Parallel()
664664
client := New(&Config{
665-
NetworkClient: &testNetwork{},
665+
Network: &testNetwork{},
666666
Codec: message.Codec,
667667
Stats: clientstats.NewNoOpStats(),
668668
StateSyncNodeIDs: nil,
@@ -694,7 +694,7 @@ func TestGetLeafsRetries(t *testing.T) {
694694

695695
const maxAttempts = 8
696696
client := New(&Config{
697-
NetworkClient: testNetClient,
697+
Network: testNetClient,
698698
Codec: message.Codec,
699699
Stats: clientstats.NewNoOpStats(),
700700
StateSyncNodeIDs: nil,
@@ -752,7 +752,7 @@ func TestStateSyncNodes(t *testing.T) {
752752
ids.GenerateTestNodeID(),
753753
}
754754
client := New(&Config{
755-
NetworkClient: testNetClient,
755+
Network: testNetClient,
756756
Codec: message.Codec,
757757
Stats: clientstats.NewNoOpStats(),
758758
StateSyncNodeIDs: stateSyncNodes,

graft/coreth/sync/client/test_client.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/message"
1717
"github.com/ava-labs/avalanchego/graft/coreth/sync/handlers"
1818
"github.com/ava-labs/avalanchego/ids"
19+
"github.com/ava-labs/avalanchego/network/p2p"
1920
)
2021

2122
var (
@@ -31,6 +32,7 @@ type TestClient struct {
3132
codeReceived int32
3233
blocksHandler *handlers.BlockRequestHandler
3334
blocksReceived int32
35+
p2pClients map[uint64]*p2p.Client
3436
// GetLeafsIntercept is called on every GetLeafs request if set to a non-nil callback.
3537
// The returned response will be returned by TestClient to the caller.
3638
GetLeafsIntercept func(req message.LeafsRequest, res message.LeafsResponse) (message.LeafsResponse, error)
@@ -47,15 +49,28 @@ func NewTestClient(
4749
leafHandler handlers.LeafRequestHandler,
4850
codesHandler *handlers.CodeRequestHandler,
4951
blocksHandler *handlers.BlockRequestHandler,
52+
p2pClients map[uint64]*p2p.Client,
5053
) *TestClient {
54+
if p2pClients == nil {
55+
p2pClients = make(map[uint64]*p2p.Client)
56+
}
5157
return &TestClient{
5258
codec: codec,
5359
leafsHandler: leafHandler,
5460
codesHandler: codesHandler,
5561
blocksHandler: blocksHandler,
62+
p2pClients: p2pClients,
5663
}
5764
}
5865

66+
func (ml *TestClient) NewClient(handlerID uint64) *p2p.Client {
67+
return ml.p2pClients[handlerID]
68+
}
69+
70+
func (*TestClient) NodeIDs() []ids.NodeID {
71+
return nil
72+
}
73+
5974
func (ml *TestClient) GetLeafs(ctx context.Context, request message.LeafsRequest) (message.LeafsResponse, error) {
6075
response, err := ml.leafsHandler.OnLeafsRequest(ctx, ids.GenerateTestNodeID(), 1, request)
6176
if err != nil {

graft/coreth/sync/client/test_network.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ import (
1212
"github.com/ava-labs/avalanchego/version"
1313
)
1414

15-
var _ network.SyncedNetworkClient = (*testNetwork)(nil)
16-
1715
type testNetwork struct {
16+
network.Network
1817
// captured request data
1918
numCalls uint
2019

graft/coreth/sync/code/syncer_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func testCodeSyncer(t *testing.T, test codeSyncerTest) {
4646

4747
// Set up mockClient
4848
codeRequestHandler := handlers.NewCodeRequestHandler(serverDB, message.Codec, handlerstats.NewNoopHandlerStats())
49-
mockClient := client.NewTestClient(message.Codec, nil, codeRequestHandler, nil)
49+
mockClient := client.NewTestClient(message.Codec, nil, codeRequestHandler, nil, nil)
5050
mockClient.GetCodeIntercept = test.getCodeIntercept
5151

5252
clientDB := test.clientDB

graft/coreth/sync/engine/client.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,25 @@ import (
99
"fmt"
1010
"sync"
1111

12+
"github.com/ava-labs/libevm/core/rawdb"
1213
"github.com/ava-labs/libevm/ethdb"
1314
"github.com/ava-labs/libevm/log"
1415
"github.com/ava-labs/libevm/params"
1516

1617
"github.com/ava-labs/avalanchego/database"
1718
"github.com/ava-labs/avalanchego/database/versiondb"
19+
"github.com/ava-labs/avalanchego/firewood/syncer"
1820
"github.com/ava-labs/avalanchego/graft/coreth/eth"
1921
"github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/message"
2022
"github.com/ava-labs/avalanchego/graft/coreth/sync/code"
2123
"github.com/ava-labs/avalanchego/graft/coreth/sync/evmstate"
2224
"github.com/ava-labs/avalanchego/graft/coreth/sync/types"
2325
"github.com/ava-labs/avalanchego/graft/evm/core/state/snapshot"
26+
"github.com/ava-labs/avalanchego/graft/evm/firewood"
2427
"github.com/ava-labs/avalanchego/ids"
2528
"github.com/ava-labs/avalanchego/snow/engine/snowman/block"
2629
"github.com/ava-labs/avalanchego/vms/components/chain"
30+
"github.com/ava-labs/avalanchego/vms/evm/sync/customrawdb"
2731

2832
blocksync "github.com/ava-labs/avalanchego/graft/coreth/sync/block"
2933
syncclient "github.com/ava-labs/avalanchego/graft/coreth/sync/client"
@@ -373,11 +377,25 @@ func (c *client) newSyncerRegistry(summary message.Syncable) (*SyncerRegistry, e
373377
return nil, fmt.Errorf("failed to create code syncer: %w", err)
374378
}
375379

376-
stateSyncer, err := evmstate.NewSyncer(
377-
c.config.Client, c.config.ChainDB,
378-
summary.GetBlockRoot(),
379-
codeQueue, c.config.RequestSize,
380-
)
380+
var stateSyncer types.Syncer
381+
switch scheme := c.config.Chain.BlockChain().CacheConfig().StateScheme; scheme {
382+
case rawdb.HashScheme:
383+
stateSyncer, err = evmstate.NewSyncer(
384+
c.config.Client, c.config.ChainDB,
385+
summary.GetBlockRoot(),
386+
codeQueue, c.config.RequestSize,
387+
)
388+
case customrawdb.FirewoodScheme:
389+
stateSyncer, err = evmstate.NewFirewoodSyncer(
390+
syncer.Config{},
391+
c.config.Chain.BlockChain().TrieDB().Backend().(*firewood.TrieDB).Firewood,
392+
summary.GetBlockRoot(),
393+
codeQueue,
394+
c.config.Client,
395+
)
396+
default:
397+
err = fmt.Errorf("unsupported state scheme: %q", scheme)
398+
}
381399
if err != nil {
382400
return nil, fmt.Errorf("failed to create EVM state syncer: %w", err)
383401
}

graft/coreth/sync/evmstate/firewood_syncer.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/ava-labs/libevm/common"
1313

1414
"github.com/ava-labs/avalanchego/firewood/syncer"
15+
"github.com/ava-labs/avalanchego/graft/coreth/sync/client"
1516
"github.com/ava-labs/avalanchego/graft/coreth/sync/code"
1617
"github.com/ava-labs/avalanchego/graft/coreth/sync/types"
1718
"github.com/ava-labs/avalanchego/ids"
@@ -32,14 +33,15 @@ type FirewoodSyncer struct {
3233
finalizeOnce func() error
3334
}
3435

35-
func NewFirewoodSyncer(config syncer.Config, db *ffi.Database, target common.Hash, codeQueue *code.Queue, rangeProofClient, changeProofClient *p2p.Client) (*FirewoodSyncer, error) {
36+
func NewFirewoodSyncer(config syncer.Config, db *ffi.Database, target common.Hash, codeQueue *code.Queue, network client.Client) (*FirewoodSyncer, error) {
37+
config.StateSyncNodes = network.NodeIDs()
3638
s, err := syncer.NewEVM(
3739
config,
3840
db,
3941
codeQueue,
4042
ids.ID(target),
41-
rangeProofClient,
42-
changeProofClient,
43+
network.NewClient(p2p.FirewoodRangeProofHandlerID),
44+
network.NewClient(p2p.FirewoodChangeProofHandlerID),
4345
)
4446
if err != nil {
4547
return nil, err

0 commit comments

Comments
 (0)