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,13 @@ 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 are initialized
41+ // because it uses them.
42+ if err := vm .initBlockDB (db ); err != nil {
43+ return err
44+ }
45+ return nil
3346}
3447
3548func (vm * VM ) inspectDatabases () error {
@@ -80,3 +93,48 @@ func inspectDB(db avalanchedatabase.Database, label string) error {
8093 log .Info ("Database statistics" , "label" , label , "total" , total .String (), "count" , count )
8194 return nil
8295}
96+
97+ // initBlockDB wraps the chaindb with a blockdb.Database that
98+ // stores blocks data in separate databases when enabled.
99+ func (vm * VM ) initBlockDB (db avalanchedatabase.Database ) error {
100+ // Error if block database has been enabled and then disabled
101+ metaDB := prefixdb .New (blockDBPrefix , db )
102+ enabled , err := blockdb .IsEnabled (metaDB )
103+ if err != nil {
104+ return err
105+ }
106+ if ! vm .config .BlockDatabaseEnabled {
107+ if enabled {
108+ return errors .New ("block database should not be disabled after it has been enabled" )
109+ }
110+ return nil
111+ }
112+
113+ version := strconv .FormatUint (heightindexdb .IndexFileVersion , 10 )
114+ path := filepath .Join (vm .ctx .ChainDataDir , "blockdb" , version )
115+ _ , height , err := vm .ReadLastAccepted ()
116+ if err != nil {
117+ return err
118+ }
119+ ssEnabled := vm .stateSyncEnabled (height )
120+ cfg := heightindexdb .DefaultConfig ().WithSyncToDisk (false )
121+ bdb , initialized , err := blockdb .New (
122+ metaDB ,
123+ vm .chaindb ,
124+ path ,
125+ ssEnabled ,
126+ cfg ,
127+ vm .ctx .Log ,
128+ vm .sdkMetrics ,
129+ )
130+ if err != nil {
131+ return err
132+ }
133+ if initialized && ! vm .config .SkipBlockDatabaseAutoMigrate {
134+ if err := bdb .StartMigration (context .Background ()); err != nil {
135+ return err
136+ }
137+ }
138+ vm .chaindb = bdb
139+ return nil
140+ }
0 commit comments