|
|
@@ -40,6 +40,11 @@ import (
|
|
|
"gopkg.in/urfave/cli.v1"
|
|
|
)
|
|
|
|
|
|
+var (
|
|
|
+ // secureKeyPrefix is the database key prefix used to store trie node preimages.
|
|
|
+ secureKeyPrefix = []byte("secure-key-")
|
|
|
+)
|
|
|
+
|
|
|
var (
|
|
|
initCommand = cli.Command{
|
|
|
Action: utils.MigrateFlags(initGenesis),
|
|
|
@@ -141,6 +146,34 @@ Remove blockchain and state databases`,
|
|
|
The arguments are interpreted as block numbers or hashes.
|
|
|
Use "ethereum dump 0" to dump the genesis block.`,
|
|
|
}
|
|
|
+ preimageDumpCommand = cli.Command{
|
|
|
+ Action: utils.MigrateFlags(dumpPreimage),
|
|
|
+ Name: "preimagedump",
|
|
|
+ Usage: "Dump the preimage database in json format",
|
|
|
+ ArgsUsage: "<dumpfile>",
|
|
|
+ Flags: []cli.Flag{
|
|
|
+ utils.DataDirFlag,
|
|
|
+ utils.CacheFlag,
|
|
|
+ utils.LightModeFlag,
|
|
|
+ },
|
|
|
+ Category: "BLOCKCHAIN COMMANDS",
|
|
|
+ Description: `
|
|
|
+Dump the preimage database in json format`,
|
|
|
+ }
|
|
|
+ preimageImportCommand = cli.Command{
|
|
|
+ Action: utils.MigrateFlags(importPreimage),
|
|
|
+ Name: "preimageimport",
|
|
|
+ Usage: "Import the preimage data from the specified file",
|
|
|
+ ArgsUsage: "<datafile>",
|
|
|
+ Flags: []cli.Flag{
|
|
|
+ utils.DataDirFlag,
|
|
|
+ utils.CacheFlag,
|
|
|
+ utils.LightModeFlag,
|
|
|
+ },
|
|
|
+ Category: "BLOCKCHAIN COMMANDS",
|
|
|
+ Description: `
|
|
|
+Import the preimage data from the specified file`,
|
|
|
+ }
|
|
|
)
|
|
|
|
|
|
// initGenesis will initialise the given JSON format genesis file and writes it as
|
|
|
@@ -406,6 +439,86 @@ func dump(ctx *cli.Context) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// PreimageEntry represents a map between preimage and hash.
|
|
|
+type PreimageEntry struct {
|
|
|
+ Hash string `json:"hash"`
|
|
|
+ Preimage string `json:"preimage"`
|
|
|
+}
|
|
|
+
|
|
|
+// dumpPreimage dumps the preimage data to specified json file in streaming way.
|
|
|
+func dumpPreimage(ctx *cli.Context) error {
|
|
|
+ // Make sure the export json file has been specified.
|
|
|
+ if len(ctx.Args()) < 1 {
|
|
|
+ utils.Fatalf("This command requires an argument.")
|
|
|
+ }
|
|
|
+
|
|
|
+ // Encode preimage data to json file in streaming way.
|
|
|
+ file, err := os.Create(ctx.Args().First())
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ encoder := json.NewEncoder(file)
|
|
|
+
|
|
|
+ stack := makeFullNode(ctx)
|
|
|
+ db := utils.MakeChainDatabase(ctx, stack)
|
|
|
+
|
|
|
+ // Dump all preimage entries.
|
|
|
+ it := db.(*ethdb.LDBDatabase).NewIteratorByPrefix(secureKeyPrefix)
|
|
|
+ for it.Next() {
|
|
|
+ hash := it.Key()[len(secureKeyPrefix):]
|
|
|
+ if err := encoder.Encode(PreimageEntry{common.Bytes2Hex(hash), common.Bytes2Hex(it.Value())}); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// importPreimages imports preimage data from the specified file.
|
|
|
+func importPreimage(ctx *cli.Context) error {
|
|
|
+ // Make sure the export json file has been specified.
|
|
|
+ if len(ctx.Args()) < 1 {
|
|
|
+ utils.Fatalf("This command requires an argument.")
|
|
|
+ }
|
|
|
+
|
|
|
+ // Decode the preimage data in streaming way.
|
|
|
+ file, err := os.Open(ctx.Args().First())
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ decoder := json.NewDecoder(file)
|
|
|
+
|
|
|
+ stack := makeFullNode(ctx)
|
|
|
+ db := utils.MakeChainDatabase(ctx, stack)
|
|
|
+
|
|
|
+ var (
|
|
|
+ entry PreimageEntry
|
|
|
+ preimages = make(map[common.Hash][]byte)
|
|
|
+ )
|
|
|
+
|
|
|
+ for decoder.More() {
|
|
|
+ if err := decoder.Decode(&entry); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ preimages[common.HexToHash(entry.Hash)] = common.Hex2Bytes(entry.Preimage)
|
|
|
+ // Flush to database in batch
|
|
|
+ if len(preimages) > 1024 {
|
|
|
+ err := core.WritePreimages(db, 0, preimages)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ preimages = make(map[common.Hash][]byte)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // Flush the last batch preimage data
|
|
|
+ if len(preimages) > 0 {
|
|
|
+ err := core.WritePreimages(db, 0, preimages)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
// hashish returns true for strings that look like hashes.
|
|
|
func hashish(x string) bool {
|
|
|
_, err := strconv.Atoi(x)
|