@@ -40,6 +40,11 @@ import (
40
40
"gopkg.in/urfave/cli.v1"
41
41
)
42
42
43
+ var (
44
+ // secureKeyPrefix is the database key prefix used to store trie node preimages.
45
+ secureKeyPrefix = []byte ("secure-key-" )
46
+ )
47
+
43
48
var (
44
49
initCommand = cli.Command {
45
50
Action : utils .MigrateFlags (initGenesis ),
@@ -141,6 +146,34 @@ Remove blockchain and state databases`,
141
146
The arguments are interpreted as block numbers or hashes.
142
147
Use "ethereum dump 0" to dump the genesis block.` ,
143
148
}
149
+ preimageDumpCommand = cli.Command {
150
+ Action : utils .MigrateFlags (dumpPreimage ),
151
+ Name : "preimagedump" ,
152
+ Usage : "Dump the preimage database in json format" ,
153
+ ArgsUsage : "<dumpfile>" ,
154
+ Flags : []cli.Flag {
155
+ utils .DataDirFlag ,
156
+ utils .CacheFlag ,
157
+ utils .LightModeFlag ,
158
+ },
159
+ Category : "BLOCKCHAIN COMMANDS" ,
160
+ Description : `
161
+ Dump the preimage database in json format` ,
162
+ }
163
+ preimageImportCommand = cli.Command {
164
+ Action : utils .MigrateFlags (importPreimage ),
165
+ Name : "preimageimport" ,
166
+ Usage : "Import the preimage data from the specified file" ,
167
+ ArgsUsage : "<datafile>" ,
168
+ Flags : []cli.Flag {
169
+ utils .DataDirFlag ,
170
+ utils .CacheFlag ,
171
+ utils .LightModeFlag ,
172
+ },
173
+ Category : "BLOCKCHAIN COMMANDS" ,
174
+ Description : `
175
+ Import the preimage data from the specified file` ,
176
+ }
144
177
)
145
178
146
179
// initGenesis will initialise the given JSON format genesis file and writes it as
@@ -406,6 +439,86 @@ func dump(ctx *cli.Context) error {
406
439
return nil
407
440
}
408
441
442
+ // PreimageEntry represents a map between preimage and hash.
443
+ type PreimageEntry struct {
444
+ Hash string `json:"hash"`
445
+ Preimage string `json:"preimage"`
446
+ }
447
+
448
+ // dumpPreimage dumps the preimage data to specified json file in streaming way.
449
+ func dumpPreimage (ctx * cli.Context ) error {
450
+ // Make sure the export json file has been specified.
451
+ if len (ctx .Args ()) < 1 {
452
+ utils .Fatalf ("This command requires an argument." )
453
+ }
454
+
455
+ // Encode preimage data to json file in streaming way.
456
+ file , err := os .Create (ctx .Args ().First ())
457
+ if err != nil {
458
+ return err
459
+ }
460
+ encoder := json .NewEncoder (file )
461
+
462
+ stack := makeFullNode (ctx )
463
+ db := utils .MakeChainDatabase (ctx , stack )
464
+
465
+ // Dump all preimage entries.
466
+ it := db .(* ethdb.LDBDatabase ).NewIteratorByPrefix (secureKeyPrefix )
467
+ for it .Next () {
468
+ hash := it .Key ()[len (secureKeyPrefix ):]
469
+ if err := encoder .Encode (PreimageEntry {common .Bytes2Hex (hash ), common .Bytes2Hex (it .Value ())}); err != nil {
470
+ return err
471
+ }
472
+ }
473
+ return nil
474
+ }
475
+
476
+ // importPreimages imports preimage data from the specified file.
477
+ func importPreimage (ctx * cli.Context ) error {
478
+ // Make sure the export json file has been specified.
479
+ if len (ctx .Args ()) < 1 {
480
+ utils .Fatalf ("This command requires an argument." )
481
+ }
482
+
483
+ // Decode the preimage data in streaming way.
484
+ file , err := os .Open (ctx .Args ().First ())
485
+ if err != nil {
486
+ return err
487
+ }
488
+ decoder := json .NewDecoder (file )
489
+
490
+ stack := makeFullNode (ctx )
491
+ db := utils .MakeChainDatabase (ctx , stack )
492
+
493
+ var (
494
+ entry PreimageEntry
495
+ preimages = make (map [common.Hash ][]byte )
496
+ )
497
+
498
+ for decoder .More () {
499
+ if err := decoder .Decode (& entry ); err != nil {
500
+ return err
501
+ }
502
+ preimages [common .HexToHash (entry .Hash )] = common .Hex2Bytes (entry .Preimage )
503
+ // Flush to database in batch
504
+ if len (preimages ) > 1024 {
505
+ err := core .WritePreimages (db , 0 , preimages )
506
+ if err != nil {
507
+ return err
508
+ }
509
+ preimages = make (map [common.Hash ][]byte )
510
+ }
511
+ }
512
+ // Flush the last batch preimage data
513
+ if len (preimages ) > 0 {
514
+ err := core .WritePreimages (db , 0 , preimages )
515
+ if err != nil {
516
+ return err
517
+ }
518
+ }
519
+ return nil
520
+ }
521
+
409
522
// hashish returns true for strings that look like hashes.
410
523
func hashish (x string ) bool {
411
524
_ , err := strconv .Atoi (x )
0 commit comments