-
Notifications
You must be signed in to change notification settings - Fork 12
/
config.go
686 lines (589 loc) · 24.2 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
package utils
import (
"errors"
"fmt"
"log"
"math"
"math/big"
"math/rand"
"os"
"regexp"
"strconv"
"strings"
"github.com/Fantom-foundation/Aida/logger"
_ "github.com/Fantom-foundation/Tosca/go/vm"
"github.com/ethereum/go-ethereum/core/rawdb"
_ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
"github.com/urfave/cli/v2"
)
type ArgumentMode int
type ChainID int
type ChainIDs []ChainID
// An enums of argument modes used by trace subcommands
const (
BlockRangeArgs ArgumentMode = iota // requires 2 arguments: first block and last block
LastBlockArg // requires 1 argument: last block
NoArgs // requires no arguments
OneToNArgs // requires at least one argument, but accepts up to N
)
const (
UnknownChainID ChainID = 0
EthereumChainID ChainID = 1
MainnetChainID ChainID = 250
TestnetChainID ChainID = 4002
)
var AvailableChainIDs = ChainIDs{MainnetChainID, TestnetChainID, EthereumChainID}
const (
AidaDbRepositoryMainnetUrl = "https://aida.repository.fantom.network"
AidaDbRepositoryTestnetUrl = "https://aida.testnet.repository.fantom.network"
AidaDbRepositoryEthereumUrl = "https://aida.ethereum.repository.fantom.network"
)
var (
FirstOperaBlock uint64 // id of the first block in substate
AidaDbRepositoryUrl string // url of the Aida DB repository
)
// Type of validation performs on stateDB during Tx processing.
type ValidationMode int
const (
SubsetCheck ValidationMode = iota // confirms whether a substate is contained in stateDB.
EqualityCheck // confirms whether a substate and StateDB are identical.
)
// A map of key blocks on Fantom chain
var keywordBlocks = map[ChainID]map[string]uint64{
MainnetChainID: {
"zero": 0,
"opera": 4_564_026,
"berlin": 37_455_223,
"london": 37_534_833,
"first": 0,
"last": math.MaxUint64,
"lastpatch": 0,
},
TestnetChainID: {
"zero": 0,
"opera": 479_327,
"berlin": 1_559_470,
"london": 7_513_335,
"first": 0,
"last": math.MaxUint64,
"lastpatch": 0,
},
// ethereum fork blocks are not stored in this structure as ethereum has already prepared config
// at params.MainnetChainConfig and it has bigger amount of forks than Fantom chain
EthereumChainID: {
"zero": 0,
"opera": 0,
"first": 0,
"last": math.MaxUint64,
"lastpatch": 0,
},
}
// special transaction number for pseudo transactions
const PseudoTx = 99999
// GitCommit represents the GitHub commit hash the app was built from.
var GitCommit = "0000000000000000000000000000000000000000"
// Config represents execution configuration for Aida tools.
type Config struct {
AppName string
CommandName string
// user defined values by arguments
First uint64 // first block
Last uint64 // last block
// internal values
IsExistingStateDb bool // this is true if we are using an existing StateDb
PathToStateDb string // Path to a working state-db directory
SrcDbReadonly bool // if false, make a copy the source statedb
StateValidationMode ValidationMode // state validation mode
// user defined values by flags
AidaDb string // directory to profiling database containing substate, update, delete accounts data
ArchiveMaxQueryAge int // the maximum age for archive queries (in blocks)
ArchiveMode bool // enable archive mode
ArchiveQueryRate int // the queries per second send to the archive
ArchiveVariant string // selects the implementation variant of the archive
BalanceRange int64 // balance range for stochastic simulation/replay
BasicBlockProfiling bool // enable profiling of basic block
BlockLength uint64 // length of a block in number of transactions
Cache int // Cache for StateDb or Priming
CarmenSchema int // the current DB schema ID to use in Carmen
ChainID ChainID // Blockchain ID (mainnet: 250/testnet: 4002)
ChannelBufferSize int // set a buffer size for profiling channel
CompactDb bool // compact database after merging
ContinueOnFailure bool // continue validation when an error detected
ContractNumber int64 // number of contracts to create
CPUProfile string // pprof cpu profile output file name
CPUProfilePerInterval bool // a different CPU profile is taken per 100k block interval
DbComponent string // options for util-db info are 'all', 'substate', 'delete', 'update', 'state-hash'
DbImpl string // storage implementation
DbLogging string // set to true if all DB operations should be logged
DbTmp string // path to temporary database
DbVariant string // database variant
Debug bool // enable trace debug flag
DebugFrom uint64 // the first block to print trace debug
DeleteSourceDbs bool // delete source databases
DeletionDb string // directory of deleted account database
DiagnosticServer int64 // if not zero, the port used for hosting a HTTP server for performance diagnostics
ErrorLogging string // if defined, error logging to file is enabled
Genesis string // genesis file
IncludeStorage bool // represents a flag for contract storage inclusion in an operation
KeepDb bool // set to true if db is kept after run
KeysNumber int64 // number of keys to generate
LogLevel string // level of the logging of the app action
MaxNumErrors int // maximum number of errors when ContinueOnFailure is enabled
MaxNumTransactions int // the maximum number of processed transactions
MemoryBreakdown bool // enable printing of memory breakdown
MemoryProfile string // capture the memory heap profile into the file
MicroProfiling bool // enable micro-profiling of EVM
NoHeartbeatLogging bool // disables heartbeat logging
NonceRange int // nonce range for stochastic simulation/replay
OnlySuccessful bool // only runs transactions that have been successful
OperaBinary string // path to opera binary
OperaDb string // path to opera database
Output string // output directory for aida-db patches or path to events.json file in stochastic generation
PrimeRandom bool // enable randomized priming
PrimeThreshold int // set account threshold before commit
Profile bool // enable micro profiling
ProfileBlocks bool // enables block profiler extension
ProfileDB string // profile db for parallel transaction execution
ProfileDepth int // 0 = Interval, 1 = Interval+Block, 2 = Interval+Block+Tx
ProfileEVMCall bool // enable profiling for EVM call
ProfileFile string // output file containing profiling result
ProfileInterval uint64 // interval of printing profile result
ProfileSqlite3 string // output profiling results to sqlite3 DB
ProfilingDbName string // set a database name for storing micro-profiling results
RandomSeed int64 // set random seed for stochastic testing
RpcRecordingFile string // path to source file with recorded RPC requests
ShadowDb bool // defines we want to open an existing db as shadow
ShadowImpl string // implementation of the shadow DB to use, empty if disabled
ShadowVariant string // database variant of the shadow DB to be used
SkipMetadata bool // skip metadata insert/getting into AidaDb
SkipPriming bool // skip priming of the state DB
SkipStateHashScrapping bool // if enabled, then state-hashes are not loaded from rpc
SnapshotDepth int // depth of snapshot history
SourceTableName string // represents the name of a source DB table
StateDbSrc string // directory to load an existing State DB data
SubstateDb string // substate directory
SyncPeriodLength uint64 // length of a sync-period in number of blocks
TargetBlock uint64 // represents the ID of target block to be reached by state evolve process or in dump state
TargetDb string // represents the path of a target DB
TargetEpoch uint64 // represents the ID of target epoch to be reached by autogen patch generator
Trace bool // trace flag
TraceDirectory string // name of trace directory
TraceFile string // name of trace file
TrackProgress bool // enables track progress logging
TransactionLength uint64 // determines indirectly the length of a transaction
TrieRootHash string // represents a hash of a state trie root to be decoded
UpdateBufferSize uint64 // cache size in Bytes
UpdateDb string // update-set directory
UpdateOnFailure bool // if enabled and continue-on-failure is also enabled, this updates any error found in StateDb
UpdateType string // download datatype
Validate bool // validate validate aida-db
ValidateStateHashes bool // if this is true state hash validation is enabled in Executor
ValidateTxState bool // validate stateDB before and after transaction
ValuesNumber int64 // number of values to generate
VmImpl string // vm implementation (geth/lfvm)
Workers int // number of worker threads
WorldStateDb string // path to worldstate
}
type configContext struct {
cfg *Config // run configuration
log logger.Logger // logger for printing logs in config functions
hasMetadata bool // if true, Aida-db has a valid metadata table
}
func NewConfigContext(cfg *Config) *configContext {
return &configContext{
log: logger.NewLogger(cfg.LogLevel, "Config"),
cfg: cfg,
hasMetadata: false,
}
}
// NewConfig creates and initializes Config with commandline arguments.
func NewConfig(ctx *cli.Context, mode ArgumentMode) (*Config, error) {
var err error
// create config with user flag values, if not set default values are used
cfg, specifiedFlags, err := createConfigFromFlags(ctx)
// create config context for sharing common arguments
cc := NewConfigContext(cfg)
// check if chainID is set correctly
err = cc.setChainId()
if err != nil {
return nil, fmt.Errorf("cannot get chain id; %v", err)
}
// set first Opera block according to chian id
cc.setFirstOperaBlock()
// set aida db repository url
err = cc.setAidaDbRepositoryUrl()
if err != nil {
return cfg, fmt.Errorf("unable to prepareUrl from chain id %v; %v", cfg.ChainID, err)
}
// set numbers of first block, last block and path to profilingDB
err = cc.updateConfigBlockRange(ctx.Args().Slice(), mode)
if err != nil {
return cfg, fmt.Errorf("unable to parse cli arguments; %v", err)
}
err = cc.adjustMissingConfigValues()
if err != nil {
return nil, fmt.Errorf("cannot adjust missing config values; %v", err)
}
err = cc.reportNewConfig(specifiedFlags)
if err != nil {
return nil, fmt.Errorf("cannot report new config; %v", err)
}
return cfg, nil
}
func (cc *configContext) setFirstOperaBlock() {
if !(cc.cfg.ChainID == MainnetChainID || cc.cfg.ChainID == TestnetChainID || cc.cfg.ChainID == EthereumChainID) {
log.Fatalf("unknown chain id %v", cc.cfg.ChainID)
}
FirstOperaBlock = keywordBlocks[cc.cfg.ChainID]["opera"]
}
// setAidaDbRepositoryUrl based on chain id selects correct aida-db repository url
func (cc *configContext) setAidaDbRepositoryUrl() error {
if cc.cfg.ChainID == MainnetChainID {
AidaDbRepositoryUrl = AidaDbRepositoryMainnetUrl
} else if cc.cfg.ChainID == TestnetChainID {
AidaDbRepositoryUrl = AidaDbRepositoryTestnetUrl
} else if cc.cfg.ChainID == EthereumChainID {
AidaDbRepositoryUrl = AidaDbRepositoryEthereumUrl
} else {
return fmt.Errorf("invalid chain id %d", cc.cfg.ChainID)
}
return nil
}
// GetChainConfig returns chain configuration of either mainnet or testnets.
func GetChainConfig(chainId ChainID) *params.ChainConfig {
if !(chainId == MainnetChainID || chainId == TestnetChainID || chainId == EthereumChainID) {
log.Fatalf("unknown chain id %v", chainId)
}
// use prepared Ethereum ChainConfig instead
if chainId == EthereumChainID {
chainConfig := params.MainnetChainConfig
chainConfig.DAOForkSupport = false
return chainConfig
}
// Make a copy of of the basic config before modifying it to avoid
// unexpected side-effects and synchronization issues in parallel runs.
chainConfig := *params.AllEthashProtocolChanges
chainConfig.ChainID = big.NewInt(int64(chainId))
chainConfig.BerlinBlock = new(big.Int).SetUint64(keywordBlocks[chainId]["berlin"])
chainConfig.LondonBlock = new(big.Int).SetUint64(keywordBlocks[chainId]["london"])
return &chainConfig
}
// directoryExists returns true if a directory exists
func directoryExists(path string) bool {
if _, err := os.Stat(path); err != nil {
return false
}
return true
}
// SetBlockRange checks the validity of a block range and return the first and last block as numbers.
func SetBlockRange(firstArg string, lastArg string, chainId ChainID) (uint64, uint64, error) {
var err error = nil
first, ferr := strconv.ParseUint(firstArg, 10, 64)
last, lerr := strconv.ParseUint(lastArg, 10, 64)
if ferr != nil {
first, err = setBlockNumber(firstArg, chainId)
if err != nil {
return 0, 0, err
}
}
if lerr != nil {
last, err = setBlockNumber(lastArg, chainId)
if err != nil {
return 0, 0, err
}
}
if first > last {
return 0, 0, fmt.Errorf("first block %v has larger number than last block %v", first, last)
}
return first, last, err
}
// setBlockNumber parse the command line argument (number, hardfork keyword or keyword with offset)
// returns calculated block number
func setBlockNumber(arg string, chainId ChainID) (uint64, error) {
var blkNum uint64
var hasOffset bool
var keyword string
var symbol string
var offset uint64
// check if keyword has an offset and extract the keyword, offset direction (arithmetical symbol) and offset value
re := regexp.MustCompile(`^[a-zA-Z]+\w*[+-]\d+$`)
if hasOffset = re.MatchString(arg); hasOffset {
var err error
if keyword, symbol, offset, err = parseOffset(arg); err != nil {
return 0, err
}
} else {
keyword = strings.ToLower(arg)
}
// find base block number from keyword
if val, ok := keywordBlocks[chainId][keyword]; ok {
blkNum = val
} else {
return 0, fmt.Errorf("block number not a valid keyword or integer")
}
// shift base block number by the offset
if hasOffset {
blkNum = offsetBlockNum(blkNum, symbol, offset)
}
return blkNum, nil
}
// parseOffset parse the hardfork keyword, offset value and a direction of the offset
func parseOffset(arg string) (string, string, uint64, error) {
if strings.Contains(arg, "+") {
if keyword, offset, ok := splitKeywordOffset(arg, "+"); ok {
return strings.ToLower(keyword), "+", offset, nil
}
return "", "", 0, fmt.Errorf("block number not a valid keyword with offset")
} else if strings.Contains(arg, "-") {
if keyword, offset, ok := splitKeywordOffset(arg, "-"); ok {
return strings.ToLower(keyword), "-", offset, nil
}
return "", "", 0, fmt.Errorf("block number not a valid keyword with offset")
}
return "", "", 0, fmt.Errorf("block number has invalid arithmetical sign")
}
// splitKeywordOffset split the hardfork keyword and the arithmetical sign determining the direction of the offset
func splitKeywordOffset(arg string, symbol string) (string, uint64, bool) {
res := strings.Split(arg, symbol)
// if the keyword doesn't exist, return.
if _, ok := keywordBlocks[MainnetChainID][strings.ToLower(res[0])]; !ok {
return "", 0, false
}
offset, err := strconv.ParseUint(res[1], 10, 64)
if err != nil {
return "", 0, false
}
return res[0], offset, true
}
// offsetBlockNum adds/subtracts the offset to/from block number
func offsetBlockNum(blkNum uint64, symbol string, offset uint64) uint64 {
res := uint64(0)
if symbol == "+" {
res = blkNum + offset
} else if symbol == "-" {
res = blkNum - offset
}
return res
}
// getMdBlockRange gets block range from aidaDB metadata
func (cc *configContext) getMdBlockRange() (uint64, uint64, uint64, error) {
defaultFirst := keywordBlocks[cc.cfg.ChainID]["first"]
defaultLast := keywordBlocks[cc.cfg.ChainID]["last"]
defaultLastPatch := keywordBlocks[cc.cfg.ChainID]["lastpatch"]
if !directoryExists(cc.cfg.AidaDb) {
cc.log.Warningf("Unable to open Aida-db in %s", cc.cfg.AidaDb)
return defaultFirst, defaultLast, defaultLastPatch, nil
}
// read meta data
aidaDb, err := rawdb.NewLevelDBDatabase(cc.cfg.AidaDb, 1024, 100, "profiling", true)
if err != nil {
cc.log.Warningf("Cannot open AidaDB; %v", err)
return defaultFirst, defaultLast, defaultLastPatch, nil
}
md := NewAidaDbMetadata(aidaDb, cc.cfg.LogLevel)
mdFirst, mdLast, err := md.getBlockRange()
if err != nil {
cc.log.Warningf("Cannot get first and last block of given AidaDB; %v", err)
return defaultFirst, defaultLast, defaultLastPatch, nil
}
cc.hasMetadata = true
lastPatchBlock, err := getPatchFirstBlock(mdLast)
if err != nil {
cc.log.Warningf("Cannot get first block of the last patch of given AidaDB; %v", err)
}
err = aidaDb.Close()
if err != nil {
return defaultFirst, defaultLast, defaultLastPatch, fmt.Errorf("cannot close db; %v", err)
}
return mdFirst, mdLast, lastPatchBlock, nil
}
// adjustBlockRange finds overlap between metadata block range and block range specified by user in command line
func (cc *configContext) adjustBlockRange(firstArg, lastArg uint64) (uint64, uint64, error) {
var first, last, firstMd, lastMd uint64
firstMd = keywordBlocks[cc.cfg.ChainID]["first"]
lastMd = keywordBlocks[cc.cfg.ChainID]["last"]
if lastArg >= firstMd && lastMd >= firstArg {
// get first block number
if firstArg >= firstMd {
first = firstArg
} else {
first = firstMd
cc.log.Warningf("First block arg (%v) is out of range of AidaDb - adjusted to the first block of AidaDb (%v)", firstArg, firstMd)
}
// get last block number
if lastArg <= lastMd {
last = lastArg
} else {
last = lastMd
cc.log.Warningf("Last block arg (%v) is out of range of AidaDb - adjusted to the last block of AidaDb (%v)", lastArg, lastMd)
}
return first, last, nil
} else {
return 0, 0, fmt.Errorf("block range of your AidaDb (%v-%v) cannot execute given block range %v-%v", firstMd, lastMd, firstArg, lastArg)
}
}
// setChainId set config chainID to the default (mainnet) or user specified chainID
// if the chainID is unknown type, it'll be loaded from aidaDB
func (cc *configContext) setChainId() error {
// first look for chainId since we need it for verbal block indication
if cc.cfg.ChainID == UnknownChainID {
cc.log.Warningf("ChainID (--%v) was not set; looking for it in AidaDb", ChainIDFlag.Name)
// we check if AidaDb was set with err == nil
if aidaDb, err := rawdb.NewLevelDBDatabase(cc.cfg.AidaDb, 1024, 100, "profiling", true); err == nil {
md := NewAidaDbMetadata(aidaDb, cc.cfg.LogLevel)
cc.cfg.ChainID = md.GetChainID()
if err = aidaDb.Close(); err != nil {
return fmt.Errorf("cannot close db; %v", err)
}
}
if cc.cfg.ChainID == 0 {
cc.log.Warningf("ChainID was neither specified with flag (--%v) nor was found in AidaDb (%v); setting default value for mainnet", ChainIDFlag.Name, cc.cfg.AidaDb)
cc.cfg.ChainID = MainnetChainID
} else {
cc.log.Noticef("Found chainId (%v) in AidaDb", cc.cfg.ChainID)
}
}
return nil
}
// updateConfigBlockRange parse the command line arguments according to the mode in which selected tool runs
// and store them into the config
func (cc *configContext) updateConfigBlockRange(args []string, mode ArgumentMode) error {
var (
first uint64
last uint64
)
switch mode {
case BlockRangeArgs:
// process arguments and flags
if len(args) >= 2 {
// try to extract block range from db metadata
firstMd, lastMd, lastPatchMd, err := cc.getMdBlockRange()
if err != nil {
return err
}
keywordBlocks[cc.cfg.ChainID]["first"] = firstMd
keywordBlocks[cc.cfg.ChainID]["last"] = lastMd
keywordBlocks[cc.cfg.ChainID]["lastpatch"] = lastPatchMd
// try to parse and check block range
firstArg, lastArg, argErr := SetBlockRange(args[0], args[1], cc.cfg.ChainID)
if argErr != nil {
return argErr
}
if !cc.hasMetadata {
first = firstArg
last = lastArg
break
}
// find if values overlap
first, last, err = cc.adjustBlockRange(firstArg, lastArg)
if err != nil {
return err
}
} else {
return fmt.Errorf("command requires 2 arguments")
}
case LastBlockArg:
var err error
last, err = strconv.ParseUint(args[0], 10, 64)
if err != nil {
return err
}
case OneToNArgs:
if len(args) < 1 {
return errors.New("this command requires at least 1 argument")
}
case NoArgs:
default:
return errors.New("unknown mode; unable to process commandline arguments")
}
cc.cfg.First = first
cc.cfg.Last = last
return nil
}
// adjustMissingConfigValues fill the missing values in the config
func (cc *configContext) adjustMissingConfigValues() error {
cfg := cc.cfg
log := cc.log
// set default db variant if not provided.
if cfg.DbImpl == "carmen" && cfg.DbVariant == "" {
cfg.DbVariant = "go-file"
log.Info("set a DB variant to go-file")
}
// if ErrorLogging is set we expect we want to catch all processing errors hence we enable ContinueOnFailure
if cfg.ErrorLogging != "" {
cfg.ContinueOnFailure = true
log.Warning("Enable continue-on-failure mode because error logging is used.")
}
// --continue-on-failure implicitly enables transaction state validation
cfg.ValidateTxState = cfg.Validate || cfg.ValidateTxState || cfg.ContinueOnFailure
if cfg.RandomSeed < 0 {
cfg.RandomSeed = int64(rand.Uint32())
}
// if AidaDB path is given, redirect source path to AidaDB.
if found := directoryExists(cfg.AidaDb); found {
OverwriteDbPathsByAidaDb(cfg)
}
// in-memory StateDB cannot be kept after run.
if cfg.KeepDb && strings.Contains(cfg.DbVariant, "memory") {
cfg.KeepDb = false
log.Warning("Keep DB feature is disabled because in-memory storage is used.")
}
// if path doesn't exist, use system temp directory.
if found := directoryExists(cfg.DbTmp); !found {
cc.log.Warningf("Temporary directory %v is not found. Use the system default %v.", cfg.DbTmp, os.TempDir())
cfg.DbTmp = os.TempDir()
}
return nil
}
// OverwriteDbPathsByAidaDb overwrites the paths of the DBs by the AidaDb path
func OverwriteDbPathsByAidaDb(cfg *Config) {
cfg.UpdateDb = cfg.AidaDb
cfg.DeletionDb = cfg.AidaDb
cfg.SubstateDb = cfg.AidaDb
}
// reportNewConfig logs out the state of config in current run
func (cc *configContext) reportNewConfig(specifiedFlags map[string]bool) error {
cfg := cc.cfg
log := cc.log
log.Noticef("Run config:")
log.Infof("Block range: %v to %v", cfg.First, cfg.Last)
if cfg.MaxNumTransactions >= 0 {
log.Noticef("Transaction limit: %d", cfg.MaxNumTransactions)
}
if specifiedFlags[ChainIDFlag.Name] {
log.Infof("Chain id: %v (record & run-vm only)", cfg.ChainID)
}
if specifiedFlags[SyncPeriodLengthFlag.Name] {
log.Infof("SyncPeriod length: %v", cfg.SyncPeriodLength)
}
if specifiedFlags[VmImplementation.Name] {
log.Noticef("Used VM implementation: %v", cfg.VmImpl)
}
if specifiedFlags[StateDbImplementationFlag.Name] {
log.Noticef("Used DB implementation: %v", cfg.DbImpl)
}
if specifiedFlags[AidaDbFlag.Name] {
log.Infof("Aida DB directory: %v", cfg.AidaDb)
}
// todo move to tx validator once finished
if specifiedFlags[ValidateTxStateFlag.Name] {
log.Infof("validate tx state: %v", cfg.ValidateTxState)
}
if cfg.Profile {
log.Infof("Profiling enabled - at depth: %d", cfg.ProfileDepth)
if cfg.ProfileFile != "" {
log.Infof(" Profiling results output file path: %s", cfg.ProfileFile)
}
if cfg.ProfileSqlite3 != "" {
log.Infof(" Profiling results output to sqlite3: %s", cfg.ProfileSqlite3)
}
}
if cfg.ShadowDb {
log.Warning("DB shadowing enabled, reducing Tx throughput and increasing memory and storage usage")
}
if cfg.DbLogging != "" {
log.Warning("Db logging enabled, reducing Tx throughput")
}
return nil
}