cmd/geth: add ability to init from an http server

This commit is contained in:
islishude 2023-10-24 18:10:55 +08:00
parent a8617c6d4d
commit 263464485c

View file

@ -17,9 +17,15 @@
package main package main
import ( import (
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io"
"net/http"
"net/url"
"os" "os"
"runtime" "runtime"
"strconv" "strconv"
@ -47,7 +53,7 @@ var (
Action: initGenesis, Action: initGenesis,
Name: "init", Name: "init",
Usage: "Bootstrap and initialize a new genesis block", Usage: "Bootstrap and initialize a new genesis block",
ArgsUsage: "<genesisPath>", ArgsUsage: "<genesisPath> [<checksum>]",
Flags: flags.Merge([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.CachePreimagesFlag, utils.CachePreimagesFlag,
}, utils.DatabaseFlags), }, utils.DatabaseFlags),
@ -56,7 +62,10 @@ The init command initializes a new genesis block and definition for the network.
This is a destructive action and changes the network in which you will be This is a destructive action and changes the network in which you will be
participating. participating.
It expects the genesis file as argument.`, It expects the genesis file or url as argument.
If the argument is a url, you can also provide a sha256 hex string as checksum.
`,
} }
dumpGenesisCommand = &cli.Command{ dumpGenesisCommand = &cli.Command{
Action: dumpGenesis, Action: dumpGenesis,
@ -171,15 +180,38 @@ This command dumps out the state for a given block (or latest, if none provided)
// initGenesis will initialise the given JSON format genesis file and writes it as // initGenesis will initialise the given JSON format genesis file and writes it as
// the zero'd block (i.e. genesis) or will fail hard if it can't succeed. // the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
func initGenesis(ctx *cli.Context) error { func initGenesis(ctx *cli.Context) (err error) {
if ctx.Args().Len() != 1 {
utils.Fatalf("need genesis.json file as the only argument")
}
genesisPath := ctx.Args().First() genesisPath := ctx.Args().First()
if len(genesisPath) == 0 { if len(genesisPath) == 0 {
utils.Fatalf("invalid path to genesis file") utils.Fatalf("invalid path to genesis file")
} }
file, err := os.Open(genesisPath)
var file io.ReadCloser
// if the genesis path is a URL, then fetch it from the http server
// if not so, open it from local file system
if u, e := url.Parse(genesisPath); e == nil && (u.Scheme == "http" || u.Scheme == "https") {
resp, err := http.Get(genesisPath)
if err != nil {
return err
}
// sha256 checksum
if checksum := ctx.Args().Get(1); checksum != "" {
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
hashFn := sha256.New()
_, _ = hashFn.Write(body)
if gotHash := hex.EncodeToString(hashFn.Sum(nil)); gotHash != checksum {
utils.Fatalf("genesis hash does not match, expected: %s but got: %s", checksum, gotHash)
}
file = io.NopCloser(bytes.NewReader(body))
} else {
file = resp.Body
}
} else {
file, err = os.Open(genesisPath)
}
if err != nil { if err != nil {
utils.Fatalf("Failed to read genesis file: %v", err) utils.Fatalf("Failed to read genesis file: %v", err)
} }