@@ -9,10 +9,9 @@ import (
99 "github.com/dgraph-io/badger/v2"
1010 badgerds "github.com/ipfs/go-ds-badger2"
1111 "github.com/rs/zerolog"
12+ "github.com/rs/zerolog/log"
1213
1314 "github.com/onflow/flow-go/cmd/util/cmd/common"
14- "github.com/onflow/flow-go/fvm/environment"
15- "github.com/onflow/flow-go/fvm/evm"
1615 "github.com/onflow/flow-go/fvm/evm/offchain/utils"
1716 "github.com/onflow/flow-go/fvm/evm/testutils"
1817 "github.com/onflow/flow-go/model/flow"
@@ -23,13 +22,26 @@ import (
2322
2423// Verify verifies the offchain replay of EVM blocks from the given height range
2524// and updates the EVM state gob files with the latest state
26- func Verify (log zerolog.Logger , from uint64 , to uint64 , chainID flow.ChainID , dataDir string , executionDataDir string , evmStateGobDir string ) error {
27- log .Info ().
25+ func Verify (
26+ log zerolog.Logger ,
27+ from uint64 ,
28+ to uint64 ,
29+ chainID flow.ChainID ,
30+ dataDir string ,
31+ executionDataDir string ,
32+ evmStateGobDir string ,
33+ saveEveryNBlocks uint64 ,
34+ ) error {
35+ lg := log .With ().
36+ Uint64 ("from" , from ).Uint64 ("to" , to ).
2837 Str ("chain" , chainID .String ()).
2938 Str ("dataDir" , dataDir ).
3039 Str ("executionDataDir" , executionDataDir ).
3140 Str ("evmStateGobDir" , evmStateGobDir ).
32- Msgf ("verifying range from %d to %d" , from , to )
41+ Uint64 ("saveEveryNBlocks" , saveEveryNBlocks ).
42+ Logger ()
43+
44+ lg .Info ().Msgf ("verifying range from %d to %d" , from , to )
3345
3446 db , storages , executionDataStore , dsStore , err := initStorages (dataDir , executionDataDir )
3547 if err != nil {
@@ -40,34 +52,32 @@ func Verify(log zerolog.Logger, from uint64, to uint64, chainID flow.ChainID, da
4052 defer dsStore .Close ()
4153
4254 var store * testutils.TestValueStore
43- isRoot := isEVMRootHeight (chainID , from )
44- if isRoot {
45- log .Info ().Msgf ("initializing EVM state for root height %d" , from )
4655
56+ // root block require the account status registers to be saved
57+ isRoot := utils .IsEVMRootHeight (chainID , from )
58+ if isRoot {
4759 store = testutils .GetSimpleValueStore ()
48- as := environment .NewAccountStatus ()
49- rootAddr := evm .StorageAccountAddress (chainID )
50- err = store .SetValue (rootAddr [:], []byte (flow .AccountStatusKey ), as .ToBytes ())
51- if err != nil {
52- return err
53- }
5460 } else {
5561 prev := from - 1
56- log .Info ().Msgf ("loading EVM state from previous height %d" , prev )
57-
58- valueFileName , allocatorFileName := evmStateGobFileNamesByEndHeight (evmStateGobDir , prev )
59- values , err := testutils .DeserializeState (valueFileName )
62+ store , err = loadState (prev , evmStateGobDir )
6063 if err != nil {
61- return fmt .Errorf ("could not deserialize state %v : %w" , valueFileName , err )
64+ return fmt .Errorf ("could not load EVM state from previous height %d : %w" , prev , err )
6265 }
66+ }
6367
64- allocators , err := testutils .DeserializeAllocator (allocatorFileName )
65- if err != nil {
66- return fmt .Errorf ("could not deserialize allocator %v: %w" , allocatorFileName , err )
68+ // save state every N blocks
69+ onHeightReplayed := func (height uint64 ) error {
70+ log .Info ().Msgf ("replayed height %d" , height )
71+ if height % saveEveryNBlocks == 0 {
72+ err := saveState (store , height , evmStateGobDir )
73+ if err != nil {
74+ return err
75+ }
6776 }
68- store = testutils . GetSimpleValueStorePopulated ( values , allocators )
77+ return nil
6978 }
7079
80+ // replay blocks
7181 err = utils .OffchainReplayBackwardCompatibilityTest (
7282 log ,
7383 chainID ,
@@ -77,16 +87,27 @@ func Verify(log zerolog.Logger, from uint64, to uint64, chainID flow.ChainID, da
7787 storages .Results ,
7888 executionDataStore ,
7989 store ,
80- func ( uint64 ) error { return nil } ,
90+ onHeightReplayed ,
8191 )
8292
8393 if err != nil {
8494 return err
8595 }
8696
87- valueFileName , allocatorFileName := evmStateGobFileNamesByEndHeight (evmStateGobDir , to )
97+ err = saveState (store , to , evmStateGobDir )
98+ if err != nil {
99+ return err
100+ }
101+
102+ lg .Info ().Msgf ("successfully verified range from %d to %d" , from , to )
103+
104+ return nil
105+ }
106+
107+ func saveState (store * testutils.TestValueStore , height uint64 , gobDir string ) error {
108+ valueFileName , allocatorFileName := evmStateGobFileNamesByEndHeight (gobDir , height )
88109 values , allocators := store .Dump ()
89- err = testutils .SerializeState (valueFileName , values )
110+ err : = testutils .SerializeState (valueFileName , values )
90111 if err != nil {
91112 return err
92113 }
@@ -100,6 +121,23 @@ func Verify(log zerolog.Logger, from uint64, to uint64, chainID flow.ChainID, da
100121 return nil
101122}
102123
124+ func loadState (height uint64 , gobDir string ) (* testutils.TestValueStore , error ) {
125+ valueFileName , allocatorFileName := evmStateGobFileNamesByEndHeight (gobDir , height )
126+ values , err := testutils .DeserializeState (valueFileName )
127+ if err != nil {
128+ return nil , fmt .Errorf ("could not deserialize state %v: %w" , valueFileName , err )
129+ }
130+
131+ allocators , err := testutils .DeserializeAllocator (allocatorFileName )
132+ if err != nil {
133+ return nil , fmt .Errorf ("could not deserialize allocator %v: %w" , allocatorFileName , err )
134+ }
135+ store := testutils .GetSimpleValueStorePopulated (values , allocators )
136+
137+ log .Info ().Msgf ("loaded EVM state for height %d from gob file %v" , height , valueFileName )
138+ return store , nil
139+ }
140+
103141func initStorages (dataDir string , executionDataDir string ) (
104142 * badger.DB ,
105143 * storage.All ,
@@ -128,16 +166,6 @@ func initStorages(dataDir string, executionDataDir string) (
128166 return db , storages , executionDataStore , ds , nil
129167}
130168
131- // EVM Root Height is the first block that has EVM Block Event where the EVM block height is 1
132- func isEVMRootHeight (chainID flow.ChainID , flowHeight uint64 ) bool {
133- if chainID == flow .Testnet {
134- return flowHeight == 211176671
135- } else if chainID == flow .Mainnet {
136- return flowHeight == 85981136
137- }
138- return flowHeight == 1
139- }
140-
141169func evmStateGobFileNamesByEndHeight (evmStateGobDir string , endHeight uint64 ) (string , string ) {
142170 valueFileName := filepath .Join (evmStateGobDir , fmt .Sprintf ("values-%d.gob" , endHeight ))
143171 allocatorFileName := filepath .Join (evmStateGobDir , fmt .Sprintf ("allocators-%d.gob" , endHeight ))
0 commit comments