@@ -3,13 +3,17 @@ package evm_exporter
33import (
44 "fmt"
55 "os"
6+ "path/filepath"
67
78 "github.com/rs/zerolog/log"
89 "github.com/spf13/cobra"
910
11+ "github.com/onflow/atree"
12+
1013 "github.com/onflow/flow-go/cmd/util/ledger/util"
1114 "github.com/onflow/flow-go/fvm/evm"
1215 "github.com/onflow/flow-go/fvm/evm/emulator/state"
16+ "github.com/onflow/flow-go/fvm/evm/testutils"
1317 "github.com/onflow/flow-go/ledger"
1418 "github.com/onflow/flow-go/ledger/common/convert"
1519 "github.com/onflow/flow-go/model/flow"
2024 flagExecutionStateDir string
2125 flagOutputDir string
2226 flagStateCommitment string
27+ flagEVMStateGobDir string
28+ flagEVMStateGobHeight uint64
2329)
2430
2531var Cmd = & cobra.Command {
@@ -34,21 +40,33 @@ func init() {
3440
3541 Cmd .Flags ().StringVar (& flagExecutionStateDir , "execution-state-dir" , "" ,
3642 "Execution Node state dir (where WAL logs are written" )
37- _ = Cmd .MarkFlagRequired ("execution-state-dir" )
3843
3944 Cmd .Flags ().StringVar (& flagOutputDir , "output-dir" , "" ,
4045 "Directory to write new Execution State to" )
4146 _ = Cmd .MarkFlagRequired ("output-dir" )
4247
4348 Cmd .Flags ().StringVar (& flagStateCommitment , "state-commitment" , "" ,
4449 "State commitment (hex-encoded, 64 characters)" )
50+
51+ Cmd .Flags ().StringVar (& flagEVMStateGobDir , "evm_state_gob_dir" , "/var/flow/data/evm_state_gob" ,
52+ "directory that stores the evm state gob files as checkpoint" )
53+
54+ Cmd .Flags ().Uint64Var (& flagEVMStateGobHeight , "evm_state_gob_height" , 0 ,
55+ "the flow height of the evm state gob files" )
4556}
4657
4758func run (* cobra.Command , []string ) {
4859 log .Info ().Msg ("start exporting evm state" )
49- err := ExportEVMState (flagChain , flagExecutionStateDir , flagStateCommitment , flagOutputDir )
50- if err != nil {
51- log .Fatal ().Err (err ).Msg ("cannot get export evm state" )
60+ if flagExecutionStateDir != "" {
61+ err := ExportEVMState (flagChain , flagExecutionStateDir , flagStateCommitment , flagOutputDir )
62+ if err != nil {
63+ log .Fatal ().Err (err ).Msg ("cannot get export evm state" )
64+ }
65+ } else if flagEVMStateGobDir != "" {
66+ err := ExportEVMStateFromGob (flagChain , flagEVMStateGobDir , flagEVMStateGobHeight , flagOutputDir )
67+ if err != nil {
68+ log .Fatal ().Err (err ).Msg ("cannot get export evm state from gob files" )
69+ }
5270 }
5371}
5472
@@ -83,7 +101,40 @@ func ExportEVMState(
83101
84102 payloadsLedger := util .NewPayloadsLedger (filteredPayloads )
85103
86- exporter , err := state .NewExporter (payloadsLedger , storageRoot )
104+ return ExportEVMStateFromPayloads (payloadsLedger , storageRoot , outputPath )
105+ }
106+
107+ func ExportEVMStateFromGob (
108+ chainName string ,
109+ evmStateGobDir string ,
110+ flowHeight uint64 ,
111+ outputPath string ) error {
112+
113+ valueFileName , allocatorFileName := evmStateGobFileNamesByEndHeight (evmStateGobDir , flowHeight )
114+ chainID := flow .ChainID (chainName )
115+
116+ storageRoot := evm .StorageAccountAddress (chainID )
117+ valuesGob , err := testutils .DeserializeState (valueFileName )
118+ if err != nil {
119+ return err
120+ }
121+
122+ allocatorGobs , err := testutils .DeserializeAllocator (allocatorFileName )
123+ if err != nil {
124+ return err
125+ }
126+
127+ store := testutils .GetSimpleValueStorePopulated (valuesGob , allocatorGobs )
128+
129+ return ExportEVMStateFromPayloads (store , storageRoot , outputPath )
130+ }
131+
132+ func ExportEVMStateFromPayloads (
133+ ledger atree.Ledger ,
134+ storageRoot flow.Address ,
135+ outputPath string ,
136+ ) error {
137+ exporter , err := state .NewExporter (ledger , storageRoot )
87138 if err != nil {
88139 return fmt .Errorf ("failed to create exporter: %w" , err )
89140 }
@@ -95,15 +146,15 @@ func ExportEVMState(
95146 }
96147 }
97148
98- fi , err := os .Create (outputPath )
99- if err != nil {
100- return err
101- }
102- defer fi .Close ()
103-
104- err = exporter .Export (outputPath )
149+ err = exporter .ExportGob (outputPath )
105150 if err != nil {
106151 return fmt .Errorf ("failed to export: %w" , err )
107152 }
108153 return nil
109154}
155+
156+ func evmStateGobFileNamesByEndHeight (evmStateGobDir string , endHeight uint64 ) (string , string ) {
157+ valueFileName := filepath .Join (evmStateGobDir , fmt .Sprintf ("values-%d.gob" , endHeight ))
158+ allocatorFileName := filepath .Join (evmStateGobDir , fmt .Sprintf ("allocators-%d.gob" , endHeight ))
159+ return valueFileName , allocatorFileName
160+ }
0 commit comments