44package evm
55
66import (
7+ "context"
8+ "errors"
9+ "path/filepath"
10+ "strconv"
711 "time"
812
913 "github.com/ava-labs/libevm/common"
@@ -13,13 +17,15 @@ import (
1317 "github.com/ava-labs/avalanchego/database/prefixdb"
1418 "github.com/ava-labs/avalanchego/database/versiondb"
1519 "github.com/ava-labs/avalanchego/vms/evm/database"
20+ "github.com/ava-labs/avalanchego/vms/evm/database/blockdb"
1621
1722 avalanchedatabase "github.com/ava-labs/avalanchego/database"
23+ heightindexdb "github.com/ava-labs/avalanchego/x/blockdb"
1824)
1925
2026// initializeDBs initializes the databases used by the VM.
2127// coreth always uses the avalanchego provided database.
22- func (vm * VM ) initializeDBs (db avalanchedatabase.Database ) {
28+ func (vm * VM ) initializeDBs (db avalanchedatabase.Database ) error {
2329 // Use NewNested rather than New so that the structure of the database
2430 // remains the same regardless of the provided baseDB type.
2531 vm .chaindb = rawdb .NewDatabase (database .New (prefixdb .NewNested (ethDBPrefix , db )))
@@ -30,6 +36,12 @@ func (vm *VM) initializeDBs(db avalanchedatabase.Database) {
3036 // that warp signatures are committed to the database atomically with
3137 // the last accepted block.
3238 vm .warpDB = prefixdb .New (warpPrefix , db )
39+
40+ // initBlockDB must be called after acceptedBlockDB and chaindb is created.
41+ if err := vm .initBlockDB (db ); err != nil {
42+ return err
43+ }
44+ return nil
3345}
3446
3547func (vm * VM ) inspectDatabases () error {
@@ -80,3 +92,48 @@ func inspectDB(db avalanchedatabase.Database, label string) error {
8092 log .Info ("Database statistics" , "label" , label , "total" , total .String (), "count" , count )
8193 return nil
8294}
95+
96+ // initBlockDB wraps the chaindb with a blockdb.Database that
97+ // stores blocks data in separate databases when enabled.
98+ func (vm * VM ) initBlockDB (db avalanchedatabase.Database ) error {
99+ // Error if block database has been created and then disabled
100+ metaDB := prefixdb .New (blockDBPrefix , db )
101+ enabled , err := blockdb .IsEnabled (metaDB )
102+ if err != nil {
103+ return err
104+ }
105+ if ! vm .config .BlockDatabaseEnabled {
106+ if enabled {
107+ return errors .New ("block database should not be disabled after it has been enabled" )
108+ }
109+ return nil
110+ }
111+
112+ version := strconv .FormatUint (heightindexdb .IndexFileVersion , 10 )
113+ path := filepath .Join (vm .ctx .ChainDataDir , "blockdb" , version )
114+ _ , lastAcceptedHeight , err := vm .ReadLastAccepted ()
115+ if err != nil {
116+ return err
117+ }
118+ stateSyncEnabled := vm .stateSyncEnabled (lastAcceptedHeight )
119+ cfg := heightindexdb .DefaultConfig ().WithSyncToDisk (false )
120+ blockDB , initialized , err := blockdb .New (
121+ metaDB ,
122+ vm .chaindb ,
123+ path ,
124+ stateSyncEnabled ,
125+ cfg ,
126+ vm .ctx .Log ,
127+ vm .sdkMetrics ,
128+ )
129+ if err != nil {
130+ return err
131+ }
132+ if initialized && ! vm .config .SkipBlockDatabaseAutoMigrate {
133+ if err := blockDB .StartMigration (context .Background ()); err != nil {
134+ return err
135+ }
136+ }
137+ vm .chaindb = blockDB
138+ return nil
139+ }
0 commit comments