Skip to content

Commit b6b6f52

Browse files
rjl493456442karalabe
authored andcommitted
cmd: implement preimage dump and import cmds
1 parent 933972d commit b6b6f52

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

cmd/geth/chaincmd.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ import (
4040
"gopkg.in/urfave/cli.v1"
4141
)
4242

43+
var (
44+
// secureKeyPrefix is the database key prefix used to store trie node preimages.
45+
secureKeyPrefix = []byte("secure-key-")
46+
)
47+
4348
var (
4449
initCommand = cli.Command{
4550
Action: utils.MigrateFlags(initGenesis),
@@ -141,6 +146,34 @@ Remove blockchain and state databases`,
141146
The arguments are interpreted as block numbers or hashes.
142147
Use "ethereum dump 0" to dump the genesis block.`,
143148
}
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+
}
144177
)
145178

146179
// initGenesis will initialise the given JSON format genesis file and writes it as
@@ -406,6 +439,86 @@ func dump(ctx *cli.Context) error {
406439
return nil
407440
}
408441

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+
409522
// hashish returns true for strings that look like hashes.
410523
func hashish(x string) bool {
411524
_, err := strconv.Atoi(x)

cmd/geth/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ func init() {
158158
copydbCommand,
159159
removedbCommand,
160160
dumpCommand,
161+
preimageDumpCommand,
162+
preimageImportCommand,
161163
// See monitorcmd.go:
162164
monitorCommand,
163165
// See accountcmd.go:

ethdb/database.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/syndtr/goleveldb/leveldb/filter"
3030
"github.com/syndtr/goleveldb/leveldb/iterator"
3131
"github.com/syndtr/goleveldb/leveldb/opt"
32+
"github.com/syndtr/goleveldb/leveldb/util"
3233
)
3334

3435
var OpenFileLimit = 64
@@ -121,6 +122,11 @@ func (db *LDBDatabase) NewIterator() iterator.Iterator {
121122
return db.db.NewIterator(nil, nil)
122123
}
123124

125+
// NewIteratorByPrefix returns a iterator to iterate over subset of database content with a particular prefix.
126+
func (db *LDBDatabase) NewIteratorByPrefix(prefix []byte) iterator.Iterator {
127+
return db.db.NewIterator(util.BytesPrefix(prefix), nil)
128+
}
129+
124130
func (db *LDBDatabase) Close() {
125131
// Stop the metrics collection to avoid internal database races
126132
db.quitLock.Lock()

0 commit comments

Comments
 (0)