@@ -9,16 +9,20 @@ import (
9
9
"os"
10
10
"path"
11
11
"strconv"
12
+ "strings"
12
13
13
14
"github.com/Fantom-foundation/lachesis-base/common/bigendian"
14
15
"github.com/Fantom-foundation/lachesis-base/hash"
15
16
"github.com/Fantom-foundation/lachesis-base/inter/idx"
16
17
"github.com/Fantom-foundation/lachesis-base/kvdb"
18
+ "github.com/Fantom-foundation/lachesis-base/kvdb/pebble"
17
19
"github.com/ethereum/go-ethereum/cmd/utils"
18
20
"github.com/ethereum/go-ethereum/log"
19
21
"github.com/ethereum/go-ethereum/rlp"
22
+ "github.com/syndtr/goleveldb/leveldb/opt"
20
23
"gopkg.in/urfave/cli.v1"
21
24
25
+ "github.com/Fantom-foundation/go-opera/gossip"
22
26
"github.com/Fantom-foundation/go-opera/gossip/evmstore"
23
27
"github.com/Fantom-foundation/go-opera/inter/ibr"
24
28
"github.com/Fantom-foundation/go-opera/inter/ier"
@@ -65,6 +69,20 @@ func (it mptAndPreimageIterator) Next() bool {
65
69
return false
66
70
}
67
71
72
+ type excludingIterator struct {
73
+ kvdb.Iterator
74
+ exclude kvdb.Reader
75
+ }
76
+
77
+ func (it excludingIterator ) Next () bool {
78
+ for it .Iterator .Next () {
79
+ if ok , _ := it .exclude .Has (it .Key ()); ! ok {
80
+ return true
81
+ }
82
+ }
83
+ return false
84
+ }
85
+
68
86
type unitWriter struct {
69
87
plain io.WriteSeeker
70
88
gziper * gzip.Writer
@@ -176,6 +194,14 @@ func (w *unitWriter) Write(b []byte) (n int, err error) {
176
194
return
177
195
}
178
196
197
+ func getEpochBlock (epoch idx.Epoch , store * gossip.Store ) idx.Block {
198
+ bs , _ := store .GetHistoryBlockEpochState (epoch )
199
+ if bs == nil {
200
+ return 0
201
+ }
202
+ return bs .LastBlock .Idx
203
+ }
204
+
179
205
func exportGenesis (ctx * cli.Context ) error {
180
206
if len (ctx .Args ()) < 1 {
181
207
utils .Fatalf ("This command requires an argument." )
@@ -198,8 +224,35 @@ func exportGenesis(ctx *cli.Context) error {
198
224
to = idx .Epoch (n )
199
225
}
200
226
mode := ctx .String (EvmExportMode .Name )
201
- if mode != "full" && mode != "ext-mpt" && mode != "mpt" && mode != "none" {
202
- return errors .New ("--export.evm.mode must be one of {full, ext-mpt, mpt, none}" )
227
+ if mode != "full" && mode != "ext-mpt" && mode != "mpt" {
228
+ return errors .New ("--export.evm.mode must be one of {full, ext-mpt, mpt}" )
229
+ }
230
+
231
+ var excludeEvmDB kvdb.Store
232
+ if excludeEvmDBPath := ctx .String (EvmExportExclude .Name ); len (excludeEvmDBPath ) > 0 {
233
+ db , err := pebble .New (excludeEvmDBPath , 1024 * opt .MiB , utils .MakeDatabaseHandles ()/ 2 , nil , nil )
234
+ if err != nil {
235
+ return err
236
+ }
237
+ excludeEvmDB = db
238
+ }
239
+
240
+ sectionsStr := ctx .String (GenesisExportSections .Name )
241
+ sections := map [string ]string {}
242
+ for _ , str := range strings .Split (sectionsStr , "," ) {
243
+ before := len (sections )
244
+ if strings .HasPrefix (str , "brs" ) {
245
+ sections ["brs" ] = str
246
+ } else if strings .HasPrefix (str , "ers" ) {
247
+ sections ["ers" ] = str
248
+ } else if strings .HasPrefix (str , "evm" ) {
249
+ sections ["evm" ] = str
250
+ } else {
251
+ return fmt .Errorf ("unknown section '%s': has to start with either 'brs' or 'ers' or 'evm'" , str )
252
+ }
253
+ if len (sections ) == before {
254
+ return fmt .Errorf ("duplicate section: '%s'" , str )
255
+ }
203
256
}
204
257
205
258
cfg := makeAllConfigs (ctx )
@@ -243,12 +296,10 @@ func exportGenesis(ctx *cli.Context) error {
243
296
if to > gdb .GetEpoch () {
244
297
to = gdb .GetEpoch ()
245
298
}
246
- toBlock := idx .Block (0 )
247
- fromBlock := idx .Block (0 )
248
- {
299
+ if len (sections ["ers" ]) > 0 {
249
300
log .Info ("Exporting epochs" , "from" , from , "to" , to )
250
301
writer := newUnitWriter (plain )
251
- err := writer .Start (header , genesisstore . EpochsSection , tmpPath )
302
+ err := writer .Start (header , sections [ "ers" ] , tmpPath )
252
303
if err != nil {
253
304
return err
254
305
}
@@ -266,28 +317,29 @@ func exportGenesis(ctx *cli.Context) error {
266
317
if err != nil {
267
318
return err
268
319
}
269
- if i == from {
270
- fromBlock = er .BlockState .LastBlock .Idx
271
- }
272
- if i == to {
273
- toBlock = er .BlockState .LastBlock .Idx
274
- }
275
320
}
276
321
epochsHash , err = writer .Flush ()
277
322
if err != nil {
278
323
return err
279
324
}
280
- log .Info ("Exported epochs" , "hash" , epochsHash .String ())
325
+ log .Info ("Exported epochs" )
326
+ fmt .Printf ("- Epochs hash: %v \n " , epochsHash .String ())
281
327
}
282
328
283
- if fromBlock < 1 {
284
- // avoid underflow
285
- fromBlock = 1
286
- }
287
- {
329
+ if len (sections ["brs" ]) > 0 {
330
+ toBlock := getEpochBlock (to , gdb )
331
+ fromBlock := getEpochBlock (from , gdb )
332
+ if sections ["brs" ] != "brs" {
333
+ // to continue prev section, include blocks of prev epochs too, excluding first blocks of prev epoch (which is last block if prev section)
334
+ fromBlock = getEpochBlock (from - 1 , gdb ) + 1
335
+ }
336
+ if fromBlock < 1 {
337
+ // avoid underflow
338
+ fromBlock = 1
339
+ }
288
340
log .Info ("Exporting blocks" , "from" , fromBlock , "to" , toBlock )
289
341
writer := newUnitWriter (plain )
290
- err := writer .Start (header , genesisstore . BlocksSection , tmpPath )
342
+ err := writer .Start (header , sections [ "brs" ] , tmpPath )
291
343
if err != nil {
292
344
return err
293
345
}
@@ -313,13 +365,14 @@ func exportGenesis(ctx *cli.Context) error {
313
365
if err != nil {
314
366
return err
315
367
}
316
- log .Info ("Exported blocks" , "hash" , blocksHash .String ())
368
+ log .Info ("Exported blocks" )
369
+ fmt .Printf ("- Blocks hash: %v \n " , blocksHash .String ())
317
370
}
318
371
319
- if mode != "none" {
320
- log .Info ("Exporting EVM data" , "from" , fromBlock , "to" , toBlock )
372
+ if len ( sections [ "evm" ]) > 0 {
373
+ log .Info ("Exporting EVM data" )
321
374
writer := newUnitWriter (plain )
322
- err := writer .Start (header , genesisstore . EvmSection , tmpPath )
375
+ err := writer .Start (header , sections [ "evm" ] , tmpPath )
323
376
if err != nil {
324
377
return err
325
378
}
@@ -331,6 +384,9 @@ func exportGenesis(ctx *cli.Context) error {
331
384
// iterate only over MPT data and preimages
332
385
it = mptAndPreimageIterator {it }
333
386
}
387
+ if excludeEvmDB != nil {
388
+ it = excludingIterator {it , excludeEvmDB }
389
+ }
334
390
defer it .Release ()
335
391
err = iodb .Write (writer , it )
336
392
if err != nil {
@@ -340,12 +396,9 @@ func exportGenesis(ctx *cli.Context) error {
340
396
if err != nil {
341
397
return err
342
398
}
343
- log .Info ("Exported EVM data" , "hash" , evmHash .String ())
399
+ log .Info ("Exported EVM data" )
400
+ fmt .Printf ("- EVM hash: %v \n " , evmHash .String ())
344
401
}
345
402
346
- fmt .Printf ("- Epochs hash: %v \n " , epochsHash .String ())
347
- fmt .Printf ("- Blocks hash: %v \n " , blocksHash .String ())
348
- fmt .Printf ("- EVM hash: %v \n " , evmHash .String ())
349
-
350
403
return nil
351
404
}
0 commit comments